Skip to content

Commit af3ed08

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 4d81127 commit af3ed08

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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+
int res = select(maxfd + 1, &readfds, NULL, NULL, &tv);
101+
assert(res == 1);
102+
gettimeofday(&end, NULL);
103+
assert(FD_ISSET(pipe_shared[0], &readfds));
104+
duration = (end.tv_sec - begin.tv_sec) * 1000000 + end.tv_usec - begin.tv_usec;
105+
assert((duration >= 1000000) && (duration < 4000000));
106+
107+
return NULL;
108+
}
109+
110+
// Check if select works in a thread
111+
void test_select_in_threads()
112+
{
113+
pthread_t tid1, tid2;
114+
const char *t = "test\n";
115+
116+
assert(pipe(pipe_shared) == 0);
117+
118+
assert(pthread_create(&tid1, NULL, do_select_in_thread, NULL) == 0);
119+
assert(pthread_create(&tid2, NULL, do_select_in_thread, NULL) == 0);
120+
121+
sleep(2);
122+
write(pipe_shared[1], t, strlen(t));
123+
124+
pthread_join(tid1, NULL);
125+
pthread_join(tid2, NULL);
126+
127+
close(pipe_shared[0]); close(pipe_shared[1]);
128+
}
129+
130+
// Check if select works with ready fds
131+
void test_ready_fds()
132+
{
133+
struct timeval tv;
134+
fd_set readfds;
135+
int maxfd;
136+
const char *t = "test\n";
137+
int pipe_c[2];
138+
int pipe_d[2];
139+
140+
assert(pipe(pipe_c) == 0);
141+
assert(pipe(pipe_d) == 0);
142+
143+
write(pipe_c[1], t, strlen(t));
144+
write(pipe_d[1], t, strlen(t));
145+
maxfd = (pipe_c[0] > pipe_d[0] ? pipe_c[0] : pipe_d[0]);
146+
147+
tv.tv_sec = 0;
148+
tv.tv_usec = 0;
149+
FD_ZERO(&readfds);
150+
FD_SET(pipe_c[0], &readfds);
151+
FD_SET(pipe_d[0], &readfds);
152+
assert(select(maxfd + 1, &readfds, NULL, NULL, &tv) == 2);
153+
assert(FD_ISSET(pipe_c[0], &readfds));
154+
assert(FD_ISSET(pipe_d[0], &readfds));
155+
156+
FD_ZERO(&readfds);
157+
FD_SET(pipe_c[0], &readfds);
158+
FD_SET(pipe_d[0], &readfds);
159+
assert(select(maxfd + 1, &readfds, NULL, NULL, NULL) == 2);
160+
assert(FD_ISSET(pipe_c[0], &readfds));
161+
assert(FD_ISSET(pipe_d[0], &readfds));
162+
163+
close(pipe_c[0]); close(pipe_c[1]);
164+
close(pipe_d[0]); close(pipe_d[1]);
165+
}
166+
167+
int main()
168+
{
169+
test_select_in_threads();
170+
test_timeout_without_fds();
171+
test_timeout_with_fds_without_events();
172+
test_unblock_select();
173+
test_ready_fds();
174+
return 0;
175+
}

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)