Skip to content

Commit 98445e3

Browse files
committed
test: Add tests for timeout on select with PROXY_TO_PTHREAD
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
1 parent 483d71b commit 98445e3

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#include <sys/select.h>
2+
#include <time.h>
3+
#include <assert.h>
4+
#include <stdio.h>
5+
#include <unistd.h>
6+
#include <pthread.h>
7+
#include <string.h>
8+
#include <sys/time.h>
9+
10+
// Check if timeout works without fds
11+
void test_timeout_without_fds()
12+
{
13+
struct timeval tv, begin, end;
14+
15+
tv.tv_sec = 1;
16+
tv.tv_usec = 0;
17+
gettimeofday(&begin, NULL);
18+
assert(select(0, NULL, NULL, NULL, &tv) == 0);
19+
gettimeofday(&end, NULL);
20+
assert((end.tv_sec - begin.tv_sec) * 1000000 + end.tv_usec - begin.tv_usec >= 1000000);
21+
}
22+
23+
// Check if timeout works with fds without events
24+
void test_timeout_with_fds_without_events()
25+
{
26+
struct timeval tv, begin, end;
27+
fd_set readfds;
28+
int pipe_a[2];
29+
30+
assert(pipe(pipe_a) == 0);
31+
32+
tv.tv_sec = 1;
33+
tv.tv_usec = 0;
34+
FD_ZERO(&readfds);
35+
FD_SET(pipe_a[0], &readfds);
36+
gettimeofday(&begin, NULL);
37+
assert(select(pipe_a[0] + 1, &readfds, NULL, NULL, &tv) == 0);
38+
gettimeofday(&end, NULL);
39+
assert((end.tv_sec - begin.tv_sec) * 1000000 + end.tv_usec - begin.tv_usec >= 1000000);
40+
41+
close(pipe_a[0]); close(pipe_a[1]);
42+
}
43+
44+
int pipe_shared[2];
45+
46+
void *wakeup_after_2s(void * arg)
47+
{
48+
const char *t = "test\n";
49+
50+
sleep(2);
51+
write(pipe_shared[1], t, strlen(t));
52+
53+
return NULL;
54+
}
55+
56+
// Check if select can unblock on an event
57+
void test_unblock_select()
58+
{
59+
struct timeval begin, end;
60+
fd_set readfds;
61+
int maxfd;
62+
pthread_t tid;
63+
int pipe_a[2];
64+
65+
assert(pipe(pipe_a) == 0);
66+
assert(pipe(pipe_shared) == 0);
67+
68+
FD_ZERO(&readfds);
69+
FD_SET(pipe_a[0], &readfds);
70+
FD_SET(pipe_shared[0], &readfds);
71+
maxfd = (pipe_a[0] > pipe_shared[0] ? pipe_a[0] : pipe_shared[0]);
72+
assert(pthread_create(&tid, NULL, wakeup_after_2s, NULL) == 0);
73+
gettimeofday(&begin, NULL);
74+
assert(select(maxfd + 1, &readfds, NULL, NULL, NULL) == 1);
75+
gettimeofday(&end, NULL);
76+
assert(FD_ISSET(pipe_shared[0], &readfds));
77+
assert((end.tv_sec - begin.tv_sec) * 1000000 + end.tv_usec - begin.tv_usec >= 1000000);
78+
79+
pthread_join(tid, NULL);
80+
81+
close(pipe_a[0]); close(pipe_a[1]);
82+
close(pipe_shared[0]); close(pipe_shared[1]);
83+
}
84+
85+
void *do_select_in_thread(void * arg)
86+
{
87+
struct timeval begin, end;
88+
fd_set readfds;
89+
int maxfd;
90+
struct timeval tv;
91+
int duration;
92+
tv.tv_sec = 4;
93+
tv.tv_usec = 0;
94+
95+
FD_ZERO(&readfds);
96+
FD_SET(pipe_shared[0], &readfds);
97+
maxfd = pipe_shared[0];
98+
99+
gettimeofday(&begin, NULL);
100+
assert(select(maxfd + 1, &readfds, NULL, NULL, &tv) == 1);
101+
gettimeofday(&end, NULL);
102+
assert(FD_ISSET(pipe_shared[0], &readfds));
103+
duration = (end.tv_sec - begin.tv_sec) * 1000000 + end.tv_usec - begin.tv_usec;
104+
assert((duration >= 1000000) && (duration < 4000000));
105+
106+
return NULL;
107+
}
108+
109+
// Check if select works in threads
110+
void test_select_in_threads()
111+
{
112+
pthread_t tid1, tid2;
113+
const char *t = "test\n";
114+
115+
assert(pipe(pipe_shared) == 0);
116+
117+
assert(pthread_create(&tid1, NULL, do_select_in_thread, NULL) == 0);
118+
assert(pthread_create(&tid2, NULL, do_select_in_thread, NULL) == 0);
119+
120+
sleep(2);
121+
write(pipe_shared[1], t, strlen(t));
122+
123+
pthread_join(tid1, NULL);
124+
pthread_join(tid2, NULL);
125+
126+
close(pipe_shared[0]); close(pipe_shared[1]);
127+
}
128+
129+
// Check if select works with ready fds
130+
void test_ready_fds()
131+
{
132+
struct timeval tv;
133+
fd_set readfds;
134+
int maxfd;
135+
const char *t = "test\n";
136+
int pipe_c[2];
137+
int pipe_d[2];
138+
139+
assert(pipe(pipe_c) == 0);
140+
assert(pipe(pipe_d) == 0);
141+
142+
write(pipe_c[1], t, strlen(t));
143+
write(pipe_d[1], t, strlen(t));
144+
maxfd = (pipe_c[0] > pipe_d[0] ? pipe_c[0] : pipe_d[0]);
145+
146+
tv.tv_sec = 0;
147+
tv.tv_usec = 0;
148+
FD_ZERO(&readfds);
149+
FD_SET(pipe_c[0], &readfds);
150+
FD_SET(pipe_d[0], &readfds);
151+
assert(select(maxfd + 1, &readfds, NULL, NULL, &tv) == 2);
152+
assert(FD_ISSET(pipe_c[0], &readfds));
153+
assert(FD_ISSET(pipe_d[0], &readfds));
154+
155+
FD_ZERO(&readfds);
156+
FD_SET(pipe_c[0], &readfds);
157+
FD_SET(pipe_d[0], &readfds);
158+
assert(select(maxfd + 1, &readfds, NULL, NULL, NULL) == 2);
159+
assert(FD_ISSET(pipe_c[0], &readfds));
160+
assert(FD_ISSET(pipe_d[0], &readfds));
161+
162+
close(pipe_c[0]); close(pipe_c[1]);
163+
close(pipe_d[0]); close(pipe_d[1]);
164+
}
165+
166+
int main()
167+
{
168+
test_select_in_threads();
169+
test_timeout_without_fds();
170+
test_timeout_with_fds_without_events();
171+
test_unblock_select();
172+
test_ready_fds();
173+
return 0;
174+
}

test/test_core.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9662,6 +9662,9 @@ def test_wasm_global(self, dynlink):
96629662
def test_syscall_intercept(self):
96639663
self.do_core_test('test_syscall_intercept.c')
96649664

9665+
def test_pthread_select_timeout(self):
9666+
self.do_runf('core/test_pthread_select_timeout.c', cflags=['-pthread', '-sPROXY_TO_PTHREAD=1', '-sEXIT_RUNTIME=1', '-Wno-pthreads-mem-growth'])
9667+
96659668
@also_without_bigint
96669669
def test_jslib_i64_params(self):
96679670
# Tests the defineI64Param and receiveI64ParamAsI53 helpers that are

0 commit comments

Comments
 (0)