foolio 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +21 -0
  6. data/examples/timer.rb +20 -0
  7. data/ext/foolio/extconf.rb +34 -0
  8. data/ext/foolio/foolio_ext.c +921 -0
  9. data/ext/foolio/gen.rb +50 -0
  10. data/ext/foolio/make_table.rb +12 -0
  11. data/ext/foolio/templ +243 -0
  12. data/ext/libuv/.gitignore +33 -0
  13. data/ext/libuv/.mailmap +13 -0
  14. data/ext/libuv/.travis.yml +9 -0
  15. data/ext/libuv/AUTHORS +61 -0
  16. data/ext/libuv/LICENSE +44 -0
  17. data/ext/libuv/Makefile +71 -0
  18. data/ext/libuv/README.md +90 -0
  19. data/ext/libuv/common.gypi +178 -0
  20. data/ext/libuv/gyp_uv +73 -0
  21. data/ext/libuv/include/uv-private/eio.h +403 -0
  22. data/ext/libuv/include/uv-private/ev.h +838 -0
  23. data/ext/libuv/include/uv-private/ngx-queue.h +108 -0
  24. data/ext/libuv/include/uv-private/tree.h +768 -0
  25. data/ext/libuv/include/uv-private/uv-unix.h +324 -0
  26. data/ext/libuv/include/uv-private/uv-win.h +517 -0
  27. data/ext/libuv/include/uv.h +1838 -0
  28. data/ext/libuv/src/fs-poll.c +235 -0
  29. data/ext/libuv/src/inet.c +293 -0
  30. data/ext/libuv/src/unix/async.c +148 -0
  31. data/ext/libuv/src/unix/core.c +696 -0
  32. data/ext/libuv/src/unix/cygwin.c +83 -0
  33. data/ext/libuv/src/unix/darwin.c +342 -0
  34. data/ext/libuv/src/unix/dl.c +83 -0
  35. data/ext/libuv/src/unix/eio/Changes +63 -0
  36. data/ext/libuv/src/unix/eio/LICENSE +36 -0
  37. data/ext/libuv/src/unix/eio/Makefile.am +15 -0
  38. data/ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
  39. data/ext/libuv/src/unix/eio/autogen.sh +3 -0
  40. data/ext/libuv/src/unix/eio/config.h.in +86 -0
  41. data/ext/libuv/src/unix/eio/config_cygwin.h +80 -0
  42. data/ext/libuv/src/unix/eio/config_darwin.h +141 -0
  43. data/ext/libuv/src/unix/eio/config_freebsd.h +81 -0
  44. data/ext/libuv/src/unix/eio/config_linux.h +94 -0
  45. data/ext/libuv/src/unix/eio/config_netbsd.h +81 -0
  46. data/ext/libuv/src/unix/eio/config_openbsd.h +137 -0
  47. data/ext/libuv/src/unix/eio/config_sunos.h +84 -0
  48. data/ext/libuv/src/unix/eio/configure.ac +22 -0
  49. data/ext/libuv/src/unix/eio/demo.c +194 -0
  50. data/ext/libuv/src/unix/eio/ecb.h +370 -0
  51. data/ext/libuv/src/unix/eio/eio.3 +3428 -0
  52. data/ext/libuv/src/unix/eio/eio.c +2593 -0
  53. data/ext/libuv/src/unix/eio/eio.pod +969 -0
  54. data/ext/libuv/src/unix/eio/libeio.m4 +195 -0
  55. data/ext/libuv/src/unix/eio/xthread.h +164 -0
  56. data/ext/libuv/src/unix/error.c +105 -0
  57. data/ext/libuv/src/unix/ev/Changes +388 -0
  58. data/ext/libuv/src/unix/ev/LICENSE +36 -0
  59. data/ext/libuv/src/unix/ev/Makefile.am +18 -0
  60. data/ext/libuv/src/unix/ev/Makefile.in +771 -0
  61. data/ext/libuv/src/unix/ev/README +58 -0
  62. data/ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
  63. data/ext/libuv/src/unix/ev/autogen.sh +6 -0
  64. data/ext/libuv/src/unix/ev/config.guess +1526 -0
  65. data/ext/libuv/src/unix/ev/config.h.in +125 -0
  66. data/ext/libuv/src/unix/ev/config.sub +1658 -0
  67. data/ext/libuv/src/unix/ev/config_cygwin.h +123 -0
  68. data/ext/libuv/src/unix/ev/config_darwin.h +122 -0
  69. data/ext/libuv/src/unix/ev/config_freebsd.h +120 -0
  70. data/ext/libuv/src/unix/ev/config_linux.h +141 -0
  71. data/ext/libuv/src/unix/ev/config_netbsd.h +120 -0
  72. data/ext/libuv/src/unix/ev/config_openbsd.h +126 -0
  73. data/ext/libuv/src/unix/ev/config_sunos.h +122 -0
  74. data/ext/libuv/src/unix/ev/configure +13037 -0
  75. data/ext/libuv/src/unix/ev/configure.ac +18 -0
  76. data/ext/libuv/src/unix/ev/depcomp +630 -0
  77. data/ext/libuv/src/unix/ev/ev++.h +816 -0
  78. data/ext/libuv/src/unix/ev/ev.3 +5311 -0
  79. data/ext/libuv/src/unix/ev/ev.c +3925 -0
  80. data/ext/libuv/src/unix/ev/ev.pod +5243 -0
  81. data/ext/libuv/src/unix/ev/ev_epoll.c +266 -0
  82. data/ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
  83. data/ext/libuv/src/unix/ev/ev_poll.c +148 -0
  84. data/ext/libuv/src/unix/ev/ev_port.c +179 -0
  85. data/ext/libuv/src/unix/ev/ev_select.c +310 -0
  86. data/ext/libuv/src/unix/ev/ev_vars.h +203 -0
  87. data/ext/libuv/src/unix/ev/ev_win32.c +153 -0
  88. data/ext/libuv/src/unix/ev/ev_wrap.h +196 -0
  89. data/ext/libuv/src/unix/ev/event.c +402 -0
  90. data/ext/libuv/src/unix/ev/event.h +170 -0
  91. data/ext/libuv/src/unix/ev/install-sh +294 -0
  92. data/ext/libuv/src/unix/ev/libev.m4 +39 -0
  93. data/ext/libuv/src/unix/ev/ltmain.sh +8413 -0
  94. data/ext/libuv/src/unix/ev/missing +336 -0
  95. data/ext/libuv/src/unix/ev/mkinstalldirs +111 -0
  96. data/ext/libuv/src/unix/freebsd.c +326 -0
  97. data/ext/libuv/src/unix/fs.c +739 -0
  98. data/ext/libuv/src/unix/internal.h +188 -0
  99. data/ext/libuv/src/unix/kqueue.c +120 -0
  100. data/ext/libuv/src/unix/linux/inotify.c +239 -0
  101. data/ext/libuv/src/unix/linux/linux-core.c +557 -0
  102. data/ext/libuv/src/unix/linux/syscalls.c +388 -0
  103. data/ext/libuv/src/unix/linux/syscalls.h +124 -0
  104. data/ext/libuv/src/unix/loop-watcher.c +62 -0
  105. data/ext/libuv/src/unix/loop.c +94 -0
  106. data/ext/libuv/src/unix/netbsd.c +108 -0
  107. data/ext/libuv/src/unix/openbsd.c +295 -0
  108. data/ext/libuv/src/unix/pipe.c +259 -0
  109. data/ext/libuv/src/unix/poll.c +114 -0
  110. data/ext/libuv/src/unix/process.c +495 -0
  111. data/ext/libuv/src/unix/signal.c +269 -0
  112. data/ext/libuv/src/unix/stream.c +990 -0
  113. data/ext/libuv/src/unix/sunos.c +481 -0
  114. data/ext/libuv/src/unix/tcp.c +393 -0
  115. data/ext/libuv/src/unix/thread.c +251 -0
  116. data/ext/libuv/src/unix/timer.c +136 -0
  117. data/ext/libuv/src/unix/tty.c +145 -0
  118. data/ext/libuv/src/unix/udp.c +659 -0
  119. data/ext/libuv/src/unix/uv-eio.c +107 -0
  120. data/ext/libuv/src/unix/uv-eio.h +13 -0
  121. data/ext/libuv/src/uv-common.c +380 -0
  122. data/ext/libuv/src/uv-common.h +170 -0
  123. data/ext/libuv/src/win/async.c +100 -0
  124. data/ext/libuv/src/win/atomicops-inl.h +56 -0
  125. data/ext/libuv/src/win/core.c +278 -0
  126. data/ext/libuv/src/win/dl.c +86 -0
  127. data/ext/libuv/src/win/error.c +155 -0
  128. data/ext/libuv/src/win/fs-event.c +510 -0
  129. data/ext/libuv/src/win/fs.c +1948 -0
  130. data/ext/libuv/src/win/getaddrinfo.c +365 -0
  131. data/ext/libuv/src/win/handle-inl.h +149 -0
  132. data/ext/libuv/src/win/handle.c +154 -0
  133. data/ext/libuv/src/win/internal.h +343 -0
  134. data/ext/libuv/src/win/loop-watcher.c +122 -0
  135. data/ext/libuv/src/win/pipe.c +1672 -0
  136. data/ext/libuv/src/win/poll.c +616 -0
  137. data/ext/libuv/src/win/process-stdio.c +500 -0
  138. data/ext/libuv/src/win/process.c +1013 -0
  139. data/ext/libuv/src/win/req-inl.h +220 -0
  140. data/ext/libuv/src/win/req.c +25 -0
  141. data/ext/libuv/src/win/signal.c +57 -0
  142. data/ext/libuv/src/win/stream-inl.h +67 -0
  143. data/ext/libuv/src/win/stream.c +167 -0
  144. data/ext/libuv/src/win/tcp.c +1394 -0
  145. data/ext/libuv/src/win/thread.c +372 -0
  146. data/ext/libuv/src/win/threadpool.c +74 -0
  147. data/ext/libuv/src/win/timer.c +224 -0
  148. data/ext/libuv/src/win/tty.c +1799 -0
  149. data/ext/libuv/src/win/udp.c +716 -0
  150. data/ext/libuv/src/win/util.c +864 -0
  151. data/ext/libuv/src/win/winapi.c +132 -0
  152. data/ext/libuv/src/win/winapi.h +4452 -0
  153. data/ext/libuv/src/win/winsock.c +557 -0
  154. data/ext/libuv/src/win/winsock.h +171 -0
  155. data/ext/libuv/test/benchmark-async-pummel.c +97 -0
  156. data/ext/libuv/test/benchmark-async.c +137 -0
  157. data/ext/libuv/test/benchmark-fs-stat.c +135 -0
  158. data/ext/libuv/test/benchmark-getaddrinfo.c +94 -0
  159. data/ext/libuv/test/benchmark-list.h +127 -0
  160. data/ext/libuv/test/benchmark-loop-count.c +88 -0
  161. data/ext/libuv/test/benchmark-million-timers.c +65 -0
  162. data/ext/libuv/test/benchmark-ping-pongs.c +213 -0
  163. data/ext/libuv/test/benchmark-pound.c +324 -0
  164. data/ext/libuv/test/benchmark-pump.c +462 -0
  165. data/ext/libuv/test/benchmark-sizes.c +44 -0
  166. data/ext/libuv/test/benchmark-spawn.c +162 -0
  167. data/ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
  168. data/ext/libuv/test/benchmark-thread.c +64 -0
  169. data/ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
  170. data/ext/libuv/test/blackhole-server.c +118 -0
  171. data/ext/libuv/test/dns-server.c +321 -0
  172. data/ext/libuv/test/echo-server.c +378 -0
  173. data/ext/libuv/test/fixtures/empty_file +0 -0
  174. data/ext/libuv/test/fixtures/load_error.node +1 -0
  175. data/ext/libuv/test/run-benchmarks.c +64 -0
  176. data/ext/libuv/test/run-tests.c +138 -0
  177. data/ext/libuv/test/runner-unix.c +295 -0
  178. data/ext/libuv/test/runner-unix.h +36 -0
  179. data/ext/libuv/test/runner-win.c +285 -0
  180. data/ext/libuv/test/runner-win.h +42 -0
  181. data/ext/libuv/test/runner.c +355 -0
  182. data/ext/libuv/test/runner.h +159 -0
  183. data/ext/libuv/test/task.h +112 -0
  184. data/ext/libuv/test/test-async.c +118 -0
  185. data/ext/libuv/test/test-callback-order.c +76 -0
  186. data/ext/libuv/test/test-callback-stack.c +203 -0
  187. data/ext/libuv/test/test-connection-fail.c +148 -0
  188. data/ext/libuv/test/test-cwd-and-chdir.c +64 -0
  189. data/ext/libuv/test/test-delayed-accept.c +188 -0
  190. data/ext/libuv/test/test-dlerror.c +58 -0
  191. data/ext/libuv/test/test-error.c +59 -0
  192. data/ext/libuv/test/test-fail-always.c +29 -0
  193. data/ext/libuv/test/test-fs-event.c +474 -0
  194. data/ext/libuv/test/test-fs-poll.c +146 -0
  195. data/ext/libuv/test/test-fs.c +1843 -0
  196. data/ext/libuv/test/test-get-currentexe.c +63 -0
  197. data/ext/libuv/test/test-get-loadavg.c +36 -0
  198. data/ext/libuv/test/test-get-memory.c +38 -0
  199. data/ext/libuv/test/test-getaddrinfo.c +122 -0
  200. data/ext/libuv/test/test-getsockname.c +342 -0
  201. data/ext/libuv/test/test-hrtime.c +54 -0
  202. data/ext/libuv/test/test-idle.c +81 -0
  203. data/ext/libuv/test/test-ipc-send-recv.c +209 -0
  204. data/ext/libuv/test/test-ipc.c +620 -0
  205. data/ext/libuv/test/test-list.h +427 -0
  206. data/ext/libuv/test/test-loop-handles.c +336 -0
  207. data/ext/libuv/test/test-multiple-listen.c +102 -0
  208. data/ext/libuv/test/test-mutexes.c +63 -0
  209. data/ext/libuv/test/test-pass-always.c +28 -0
  210. data/ext/libuv/test/test-ping-pong.c +253 -0
  211. data/ext/libuv/test/test-pipe-bind-error.c +140 -0
  212. data/ext/libuv/test/test-pipe-connect-error.c +96 -0
  213. data/ext/libuv/test/test-platform-output.c +87 -0
  214. data/ext/libuv/test/test-poll-close.c +72 -0
  215. data/ext/libuv/test/test-poll.c +573 -0
  216. data/ext/libuv/test/test-process-title.c +49 -0
  217. data/ext/libuv/test/test-ref.c +338 -0
  218. data/ext/libuv/test/test-run-once.c +48 -0
  219. data/ext/libuv/test/test-semaphore.c +111 -0
  220. data/ext/libuv/test/test-shutdown-close.c +103 -0
  221. data/ext/libuv/test/test-shutdown-eof.c +183 -0
  222. data/ext/libuv/test/test-signal.c +162 -0
  223. data/ext/libuv/test/test-spawn.c +863 -0
  224. data/ext/libuv/test/test-stdio-over-pipes.c +246 -0
  225. data/ext/libuv/test/test-tcp-bind-error.c +191 -0
  226. data/ext/libuv/test/test-tcp-bind6-error.c +154 -0
  227. data/ext/libuv/test/test-tcp-close-while-connecting.c +80 -0
  228. data/ext/libuv/test/test-tcp-close.c +129 -0
  229. data/ext/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  230. data/ext/libuv/test/test-tcp-connect-error.c +70 -0
  231. data/ext/libuv/test/test-tcp-connect-timeout.c +85 -0
  232. data/ext/libuv/test/test-tcp-connect6-error.c +68 -0
  233. data/ext/libuv/test/test-tcp-flags.c +51 -0
  234. data/ext/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  235. data/ext/libuv/test/test-tcp-unexpected-read.c +113 -0
  236. data/ext/libuv/test/test-tcp-write-error.c +168 -0
  237. data/ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
  238. data/ext/libuv/test/test-tcp-writealot.c +170 -0
  239. data/ext/libuv/test/test-thread.c +183 -0
  240. data/ext/libuv/test/test-threadpool.c +57 -0
  241. data/ext/libuv/test/test-timer-again.c +141 -0
  242. data/ext/libuv/test/test-timer.c +152 -0
  243. data/ext/libuv/test/test-tty.c +110 -0
  244. data/ext/libuv/test/test-udp-dgram-too-big.c +86 -0
  245. data/ext/libuv/test/test-udp-ipv6.c +156 -0
  246. data/ext/libuv/test/test-udp-multicast-join.c +139 -0
  247. data/ext/libuv/test/test-udp-multicast-ttl.c +86 -0
  248. data/ext/libuv/test/test-udp-options.c +86 -0
  249. data/ext/libuv/test/test-udp-send-and-recv.c +208 -0
  250. data/ext/libuv/test/test-util.c +97 -0
  251. data/ext/libuv/test/test-walk-handles.c +77 -0
  252. data/ext/libuv/uv.gyp +375 -0
  253. data/ext/libuv/vcbuild.bat +105 -0
  254. data/foolio.gemspec +18 -0
  255. data/lib/foolio.rb +9 -0
  256. data/lib/foolio/handle.rb +27 -0
  257. data/lib/foolio/listener.rb +26 -0
  258. data/lib/foolio/loop.rb +79 -0
  259. data/lib/foolio/stream.rb +109 -0
  260. data/lib/foolio/version.rb +3 -0
  261. metadata +309 -0
@@ -0,0 +1,96 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "task.h"
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+
27
+
28
+ #ifdef _WIN32
29
+ # define BAD_PIPENAME "bad-pipe"
30
+ #else
31
+ # define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
32
+ #endif
33
+
34
+
35
+ static int close_cb_called = 0;
36
+ static int connect_cb_called = 0;
37
+
38
+
39
+ static void close_cb(uv_handle_t* handle) {
40
+ ASSERT(handle != NULL);
41
+ close_cb_called++;
42
+ }
43
+
44
+
45
+ static void connect_cb(uv_connect_t* connect_req, int status) {
46
+ ASSERT(status == -1);
47
+ ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOENT);
48
+ uv_close((uv_handle_t*)connect_req->handle, close_cb);
49
+ connect_cb_called++;
50
+ }
51
+
52
+
53
+ static void connect_cb_file(uv_connect_t* connect_req, int status) {
54
+ ASSERT(status == -1);
55
+ ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSOCK ||
56
+ uv_last_error(uv_default_loop()).code == UV_ECONNREFUSED);
57
+ uv_close((uv_handle_t*)connect_req->handle, close_cb);
58
+ connect_cb_called++;
59
+ }
60
+
61
+
62
+ TEST_IMPL(pipe_connect_bad_name) {
63
+ uv_pipe_t client;
64
+ uv_connect_t req;
65
+ int r;
66
+
67
+ r = uv_pipe_init(uv_default_loop(), &client, 0);
68
+ ASSERT(r == 0);
69
+ uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb);
70
+
71
+ uv_run(uv_default_loop());
72
+
73
+ ASSERT(close_cb_called == 1);
74
+ ASSERT(connect_cb_called == 1);
75
+
76
+ return 0;
77
+ }
78
+
79
+
80
+ TEST_IMPL(pipe_connect_to_file) {
81
+ const char* path = "test/fixtures/empty_file";
82
+ uv_pipe_t client;
83
+ uv_connect_t req;
84
+ int r;
85
+
86
+ r = uv_pipe_init(uv_default_loop(), &client, 0);
87
+ ASSERT(r == 0);
88
+ uv_pipe_connect(&req, &client, path, connect_cb_file);
89
+
90
+ uv_run(uv_default_loop());
91
+
92
+ ASSERT(close_cb_called == 1);
93
+ ASSERT(connect_cb_called == 1);
94
+
95
+ return 0;
96
+ }
@@ -0,0 +1,87 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "task.h"
24
+ #include <string.h>
25
+
26
+
27
+ TEST_IMPL(platform_output) {
28
+ char buffer[512];
29
+ size_t rss;
30
+ double uptime;
31
+ uv_cpu_info_t* cpus;
32
+ uv_interface_address_t* interfaces;
33
+ int count;
34
+ int i;
35
+ uv_err_t err;
36
+
37
+ err = uv_get_process_title(buffer, sizeof(buffer));
38
+ ASSERT(UV_OK == err.code);
39
+ printf("uv_get_process_title: %s\n", buffer);
40
+
41
+ err = uv_resident_set_memory(&rss);
42
+ ASSERT(UV_OK == err.code);
43
+ printf("uv_resident_set_memory: %llu\n", (unsigned long long) rss);
44
+
45
+ err = uv_uptime(&uptime);
46
+ ASSERT(UV_OK == err.code);
47
+ ASSERT(uptime > 0);
48
+ printf("uv_uptime: %f\n", uptime);
49
+
50
+ err = uv_cpu_info(&cpus, &count);
51
+ ASSERT(UV_OK == err.code);
52
+
53
+ printf("uv_cpu_info:\n");
54
+ for (i = 0; i < count; i++) {
55
+ printf(" model: %s\n", cpus[i].model);
56
+ printf(" speed: %d\n", cpus[i].speed);
57
+ printf(" times.sys: %llu\n", (unsigned long long) cpus[i].cpu_times.sys);
58
+ printf(" times.user: %llu\n",
59
+ (unsigned long long) cpus[i].cpu_times.user);
60
+ printf(" times.idle: %llu\n",
61
+ (unsigned long long) cpus[i].cpu_times.idle);
62
+ printf(" times.irq: %llu\n", (unsigned long long) cpus[i].cpu_times.irq);
63
+ printf(" times.nice: %llu\n",
64
+ (unsigned long long) cpus[i].cpu_times.nice);
65
+ }
66
+ uv_free_cpu_info(cpus, count);
67
+
68
+ err = uv_interface_addresses(&interfaces, &count);
69
+ ASSERT(UV_OK == err.code);
70
+
71
+ printf("uv_interface_addresses:\n");
72
+ for (i = 0; i < count; i++) {
73
+ printf(" name: %s\n", interfaces[i].name);
74
+ printf(" internal: %d\n", interfaces[i].is_internal);
75
+
76
+ if (interfaces[i].address.address4.sin_family == AF_INET) {
77
+ uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer));
78
+ } else if (interfaces[i].address.address4.sin_family == AF_INET6) {
79
+ uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer));
80
+ }
81
+
82
+ printf(" address: %s\n", buffer);
83
+ }
84
+ uv_free_interface_addresses(interfaces, count);
85
+
86
+ return 0;
87
+ }
@@ -0,0 +1,72 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include <errno.h>
23
+
24
+ #ifndef _WIN32
25
+ # include <fcntl.h>
26
+ # include <sys/socket.h>
27
+ # include <unistd.h>
28
+ #endif
29
+
30
+ #include "uv.h"
31
+ #include "task.h"
32
+
33
+ #define NUM_SOCKETS 64
34
+
35
+
36
+ static int close_cb_called = 0;
37
+
38
+
39
+ static void close_cb(uv_handle_t* handle) {
40
+ close_cb_called++;
41
+ }
42
+
43
+
44
+ TEST_IMPL(poll_close) {
45
+ uv_os_sock_t sockets[NUM_SOCKETS];
46
+ uv_poll_t poll_handles[NUM_SOCKETS];
47
+ int i;
48
+
49
+ #ifdef _WIN32
50
+ {
51
+ struct WSAData wsa_data;
52
+ int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
53
+ ASSERT(r == 0);
54
+ }
55
+ #endif
56
+
57
+ for (i = 0; i < NUM_SOCKETS; i++) {
58
+ sockets[i] = socket(AF_INET, SOCK_STREAM, 0);
59
+ uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]);
60
+ uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL);
61
+ }
62
+
63
+ for (i = 0; i < NUM_SOCKETS; i++) {
64
+ uv_close((uv_handle_t*) &poll_handles[i], close_cb);
65
+ }
66
+
67
+ uv_run(uv_default_loop());
68
+
69
+ ASSERT(close_cb_called == NUM_SOCKETS);
70
+
71
+ return 0;
72
+ }
@@ -0,0 +1,573 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include <errno.h>
23
+
24
+ #ifndef _WIN32
25
+ # include <fcntl.h>
26
+ # include <sys/socket.h>
27
+ # include <unistd.h>
28
+ #endif
29
+
30
+ #include "uv.h"
31
+ #include "task.h"
32
+
33
+
34
+ #define NUM_CLIENTS 5
35
+ #define TRANSFER_BYTES (1 << 16)
36
+
37
+ #undef MIN
38
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b));
39
+
40
+
41
+ typedef enum {
42
+ UNIDIRECTIONAL,
43
+ DUPLEX
44
+ } test_mode_t;
45
+
46
+ typedef struct connection_context_s {
47
+ uv_poll_t poll_handle;
48
+ uv_timer_t timer_handle;
49
+ uv_os_sock_t sock;
50
+ size_t read, sent;
51
+ int is_server_connection;
52
+ int open_handles;
53
+ int got_fin, sent_fin;
54
+ unsigned int events, delayed_events;
55
+ } connection_context_t;
56
+
57
+ typedef struct server_context_s {
58
+ uv_poll_t poll_handle;
59
+ uv_os_sock_t sock;
60
+ int connections;
61
+ } server_context_t;
62
+
63
+
64
+ static void delay_timer_cb(uv_timer_t* timer, int status);
65
+
66
+
67
+ static test_mode_t test_mode = DUPLEX;
68
+
69
+ static int closed_connections = 0;
70
+
71
+ static int valid_writable_wakeups = 0;
72
+ static int spurious_writable_wakeups = 0;
73
+
74
+
75
+ static int got_eagain() {
76
+ #ifdef _WIN32
77
+ return WSAGetLastError() == WSAEWOULDBLOCK;
78
+ #else
79
+ return errno == EAGAIN
80
+ || errno == EINPROGRESS
81
+ #ifdef EWOULDBLOCK
82
+ || errno == EWOULDBLOCK;
83
+ #endif
84
+ ;
85
+ #endif
86
+ }
87
+
88
+
89
+ static void set_nonblocking(uv_os_sock_t sock) {
90
+ int r;
91
+ #ifdef _WIN32
92
+ unsigned long on = 1;
93
+ r = ioctlsocket(sock, FIONBIO, &on);
94
+ ASSERT(r == 0);
95
+ #else
96
+ int flags = fcntl(sock, F_GETFL, 0);
97
+ ASSERT(flags >= 0);
98
+ r = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
99
+ ASSERT(r >= 0);
100
+ #endif
101
+ }
102
+
103
+
104
+ static uv_os_sock_t create_nonblocking_bound_socket(
105
+ struct sockaddr_in bind_addr) {
106
+ uv_os_sock_t sock;
107
+ int r;
108
+
109
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
110
+ #ifdef _WIN32
111
+ ASSERT(sock != INVALID_SOCKET);
112
+ #else
113
+ ASSERT(sock >= 0);
114
+ #endif
115
+
116
+ set_nonblocking(sock);
117
+
118
+ #ifndef _WIN32
119
+ {
120
+ /* Allow reuse of the port. */
121
+ int yes = 1;
122
+ r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
123
+ ASSERT(r == 0);
124
+ }
125
+ #endif
126
+
127
+ r = bind(sock, (const struct sockaddr*) &bind_addr, sizeof bind_addr);
128
+ ASSERT(r == 0);
129
+
130
+ return sock;
131
+ }
132
+
133
+
134
+ static void close_socket(uv_os_sock_t sock) {
135
+ int r;
136
+ #ifdef _WIN32
137
+ r = closesocket(sock);
138
+ #else
139
+ r = close(sock);
140
+ #endif
141
+ ASSERT(r == 0);
142
+ }
143
+
144
+
145
+ static connection_context_t* create_connection_context(
146
+ uv_os_sock_t sock, int is_server_connection) {
147
+ int r;
148
+ connection_context_t* context;
149
+
150
+ context = (connection_context_t*) malloc(sizeof *context);
151
+ ASSERT(context != NULL);
152
+
153
+ context->sock = sock;
154
+ context->is_server_connection = is_server_connection;
155
+ context->read = 0;
156
+ context->sent = 0;
157
+ context->open_handles = 0;
158
+ context->events = 0;
159
+ context->delayed_events = 0;
160
+ context->got_fin = 0;
161
+ context->sent_fin = 0;
162
+
163
+ r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock);
164
+ context->open_handles++;
165
+ context->poll_handle.data = context;
166
+ ASSERT(r == 0);
167
+
168
+ r = uv_timer_init(uv_default_loop(), &context->timer_handle);
169
+ context->open_handles++;
170
+ context->timer_handle.data = context;
171
+ ASSERT(r == 0);
172
+
173
+ return context;
174
+ }
175
+
176
+
177
+ static void connection_close_cb(uv_handle_t* handle) {
178
+ connection_context_t* context = (connection_context_t*) handle->data;
179
+
180
+ if (--context->open_handles == 0) {
181
+ if (test_mode == DUPLEX || context->is_server_connection) {
182
+ ASSERT(context->read == TRANSFER_BYTES);
183
+ } else {
184
+ ASSERT(context->read == 0);
185
+ }
186
+
187
+ if (test_mode == DUPLEX || !context->is_server_connection) {
188
+ ASSERT(context->sent == TRANSFER_BYTES);
189
+ } else {
190
+ ASSERT(context->sent == 0);
191
+ }
192
+
193
+ closed_connections++;
194
+
195
+ free(context);
196
+ }
197
+ }
198
+
199
+
200
+ static void destroy_connection_context(connection_context_t* context) {
201
+ uv_close((uv_handle_t*) &context->poll_handle, connection_close_cb);
202
+ uv_close((uv_handle_t*) &context->timer_handle, connection_close_cb);
203
+ }
204
+
205
+
206
+ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
207
+ connection_context_t* context = (connection_context_t*) handle->data;
208
+ int new_events;
209
+ int r;
210
+
211
+ ASSERT(status == 0);
212
+ ASSERT(events & context->events);
213
+ ASSERT(!(events & ~context->events));
214
+
215
+ new_events = context->events;
216
+
217
+ if (events & UV_READABLE) {
218
+ int action = rand() % 7;
219
+
220
+ switch (action) {
221
+ case 0:
222
+ case 1: {
223
+ /* Read a couple of bytes. */
224
+ static char buffer[74];
225
+ r = recv(context->sock, buffer, sizeof buffer, 0);
226
+ ASSERT(r >= 0);
227
+
228
+ if (r > 0) {
229
+ context->read += r;
230
+ } else {
231
+ /* Got FIN. */
232
+ context->got_fin = 1;
233
+ new_events &= ~UV_READABLE;
234
+ }
235
+
236
+ break;
237
+ }
238
+
239
+ case 2:
240
+ case 3: {
241
+ /* Read until EAGAIN. */
242
+ static char buffer[931];
243
+ r = recv(context->sock, buffer, sizeof buffer, 0);
244
+ ASSERT(r >= 0);
245
+
246
+ while (r > 0) {
247
+ context->read += r;
248
+ r = recv(context->sock, buffer, sizeof buffer, 0);
249
+ }
250
+
251
+ if (r == 0) {
252
+ /* Got FIN. */
253
+ context->got_fin = 1;
254
+ new_events &= ~UV_READABLE;
255
+ } else {
256
+ ASSERT(got_eagain());
257
+ }
258
+
259
+ break;
260
+ }
261
+
262
+ case 4:
263
+ /* Ignore. */
264
+ break;
265
+
266
+ case 5:
267
+ /* Stop reading for a while. Restart in timer callback. */
268
+ new_events &= ~UV_READABLE;
269
+ if (!uv_is_active((uv_handle_t*) &context->timer_handle)) {
270
+ context->delayed_events = UV_READABLE;
271
+ uv_timer_start(&context->timer_handle, delay_timer_cb, 10, 0);
272
+ } else {
273
+ context->delayed_events |= UV_READABLE;
274
+ }
275
+ break;
276
+
277
+ case 6:
278
+ /* Fudge with the event mask. */
279
+ uv_poll_start(&context->poll_handle, UV_WRITABLE, connection_poll_cb);
280
+ uv_poll_start(&context->poll_handle, UV_READABLE, connection_poll_cb);
281
+ context->events = UV_READABLE;
282
+ break;
283
+
284
+ default:
285
+ ASSERT(0);
286
+ }
287
+ }
288
+
289
+ if (events & UV_WRITABLE) {
290
+ if (context->sent < TRANSFER_BYTES &&
291
+ !(test_mode == UNIDIRECTIONAL && context->is_server_connection)) {
292
+ /* We have to send more bytes. */
293
+ int action = rand() % 7;
294
+
295
+ switch (action) {
296
+ case 0:
297
+ case 1: {
298
+ /* Send a couple of bytes. */
299
+ static char buffer[103];
300
+
301
+ int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
302
+ ASSERT(send_bytes > 0);
303
+
304
+ r = send(context->sock, buffer, send_bytes, 0);
305
+
306
+ if (r < 0) {
307
+ ASSERT(got_eagain());
308
+ spurious_writable_wakeups++;
309
+ break;
310
+ }
311
+
312
+ ASSERT(r > 0);
313
+ context->sent += r;
314
+ valid_writable_wakeups++;
315
+ break;
316
+ }
317
+
318
+ case 2:
319
+ case 3: {
320
+ /* Send until EAGAIN. */
321
+ static char buffer[1234];
322
+
323
+ int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
324
+ ASSERT(send_bytes > 0);
325
+
326
+ r = send(context->sock, buffer, send_bytes, 0);
327
+
328
+ if (r < 0) {
329
+ ASSERT(got_eagain());
330
+ spurious_writable_wakeups++;
331
+ break;
332
+ }
333
+
334
+ ASSERT(r > 0);
335
+ valid_writable_wakeups++;
336
+ context->sent += r;
337
+
338
+ while (context->sent < TRANSFER_BYTES) {
339
+ send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
340
+ ASSERT(send_bytes > 0);
341
+
342
+ r = send(context->sock, buffer, send_bytes, 0);
343
+
344
+ if (r <= 0) break;
345
+ context->sent += r;
346
+ }
347
+ ASSERT(r > 0 || got_eagain());
348
+ break;
349
+ }
350
+
351
+ case 4:
352
+ /* Ignore. */
353
+ break;
354
+
355
+ case 5:
356
+ /* Stop sending for a while. Restart in timer callback. */
357
+ new_events &= ~UV_WRITABLE;
358
+ if (!uv_is_active((uv_handle_t*) &context->timer_handle)) {
359
+ context->delayed_events = UV_WRITABLE;
360
+ uv_timer_start(&context->timer_handle, delay_timer_cb, 100, 0);
361
+ } else {
362
+ context->delayed_events |= UV_WRITABLE;
363
+ }
364
+ break;
365
+
366
+ case 6:
367
+ /* Fudge with the event mask. */
368
+ uv_poll_start(&context->poll_handle,
369
+ UV_READABLE,
370
+ connection_poll_cb);
371
+ uv_poll_start(&context->poll_handle,
372
+ UV_WRITABLE,
373
+ connection_poll_cb);
374
+ context->events = UV_WRITABLE;
375
+ break;
376
+
377
+ default:
378
+ ASSERT(0);
379
+ }
380
+
381
+ } else {
382
+ /* Nothing more to write. Send FIN. */
383
+ int r;
384
+ #ifdef _WIN32
385
+ r = shutdown(context->sock, SD_SEND);
386
+ #else
387
+ r = shutdown(context->sock, SHUT_WR);
388
+ #endif
389
+ ASSERT(r == 0);
390
+ context->sent_fin = 1;
391
+ new_events &= ~UV_WRITABLE;
392
+ }
393
+ }
394
+
395
+ if (context->got_fin && context->sent_fin) {
396
+ /* Sent and received FIN. Close and destroy context. */
397
+ close_socket(context->sock);
398
+ destroy_connection_context(context);
399
+ context->events = 0;
400
+
401
+ } else if (new_events != context->events) {
402
+ /* Poll mask changed. Call uv_poll_start again. */
403
+ context->events = new_events;
404
+ uv_poll_start(handle, new_events, connection_poll_cb);
405
+ }
406
+
407
+ /* Assert that uv_is_active works correctly for poll handles. */
408
+ if (context->events != 0) {
409
+ ASSERT(uv_is_active((uv_handle_t*) handle));
410
+ } else {
411
+ ASSERT(!uv_is_active((uv_handle_t*) handle));
412
+ }
413
+ }
414
+
415
+
416
+ static void delay_timer_cb(uv_timer_t* timer, int status) {
417
+ connection_context_t* context = (connection_context_t*) timer->data;
418
+ int r;
419
+
420
+ /* Timer should auto stop. */
421
+ ASSERT(!uv_is_active((uv_handle_t*) timer));
422
+
423
+ /* Add the requested events to the poll mask. */
424
+ ASSERT(context->delayed_events != 0);
425
+ context->events |= context->delayed_events;
426
+ context->delayed_events = 0;
427
+
428
+ r = uv_poll_start(&context->poll_handle,
429
+ context->events,
430
+ connection_poll_cb);
431
+ ASSERT(r == 0);
432
+ }
433
+
434
+
435
+ static server_context_t* create_server_context(
436
+ uv_os_sock_t sock) {
437
+ int r;
438
+ server_context_t* context;
439
+
440
+ context = (server_context_t*) malloc(sizeof *context);
441
+ ASSERT(context != NULL);
442
+
443
+ context->sock = sock;
444
+ context->connections = 0;
445
+
446
+ r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock);
447
+ context->poll_handle.data = context;
448
+ ASSERT(r == 0);
449
+
450
+ return context;
451
+ }
452
+
453
+
454
+ static void server_close_cb(uv_handle_t* handle) {
455
+ server_context_t* context = (server_context_t*) handle->data;
456
+ free(context);
457
+ }
458
+
459
+
460
+ static void destroy_server_context(server_context_t* context) {
461
+ uv_close((uv_handle_t*) &context->poll_handle, server_close_cb);
462
+ }
463
+
464
+
465
+ static void server_poll_cb(uv_poll_t* handle, int status, int events) {
466
+ server_context_t* server_context = (server_context_t*)
467
+ handle->data;
468
+ connection_context_t* connection_context;
469
+ struct sockaddr_in addr;
470
+ socklen_t addr_len;
471
+ uv_os_sock_t sock;
472
+ int r;
473
+
474
+ addr_len = sizeof addr;
475
+ sock = accept(server_context->sock, (struct sockaddr*) &addr, &addr_len);
476
+ #ifdef _WIN32
477
+ ASSERT(sock != INVALID_SOCKET);
478
+ #else
479
+ ASSERT(sock >= 0);
480
+ #endif
481
+
482
+ set_nonblocking(sock);
483
+
484
+ connection_context = create_connection_context(sock, 1);
485
+ connection_context->events = UV_READABLE | UV_WRITABLE;
486
+ r = uv_poll_start(&connection_context->poll_handle,
487
+ UV_READABLE | UV_WRITABLE,
488
+ connection_poll_cb);
489
+ ASSERT(r == 0);
490
+
491
+ if (++server_context->connections == NUM_CLIENTS) {
492
+ close_socket(server_context->sock);
493
+ destroy_server_context(server_context);
494
+ }
495
+ }
496
+
497
+
498
+ static void start_server() {
499
+ uv_os_sock_t sock;
500
+ server_context_t* context;
501
+ int r;
502
+
503
+ sock = create_nonblocking_bound_socket(uv_ip4_addr("127.0.0.1", TEST_PORT));
504
+ context = create_server_context(sock);
505
+
506
+ r = listen(sock, 100);
507
+ ASSERT(r == 0);
508
+
509
+ r = uv_poll_start(&context->poll_handle, UV_READABLE, server_poll_cb);
510
+ ASSERT(r == 0);
511
+ }
512
+
513
+
514
+ static void start_client() {
515
+ uv_os_sock_t sock;
516
+ connection_context_t* context;
517
+ struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
518
+ int r;
519
+
520
+ sock = create_nonblocking_bound_socket(uv_ip4_addr("0.0.0.0", 0));
521
+ context = create_connection_context(sock, 0);
522
+
523
+ context->events = UV_READABLE | UV_WRITABLE;
524
+ r = uv_poll_start(&context->poll_handle,
525
+ UV_READABLE | UV_WRITABLE,
526
+ connection_poll_cb);
527
+ ASSERT(r == 0);
528
+
529
+ r = connect(sock, (struct sockaddr*) &server_addr, sizeof server_addr);
530
+ ASSERT(r == 0 || got_eagain());
531
+ }
532
+
533
+
534
+ static void start_poll_test() {
535
+ int i, r;
536
+
537
+ #ifdef _WIN32
538
+ {
539
+ struct WSAData wsa_data;
540
+ int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
541
+ ASSERT(r == 0);
542
+ }
543
+ #endif
544
+
545
+ start_server();
546
+
547
+ for (i = 0; i < NUM_CLIENTS; i++)
548
+ start_client();
549
+
550
+ r = uv_run(uv_default_loop());
551
+ ASSERT(r == 0);
552
+
553
+ /* Assert that at most five percent of the writable wakeups was spurious. */
554
+ ASSERT(spurious_writable_wakeups == 0 ||
555
+ (valid_writable_wakeups + spurious_writable_wakeups) /
556
+ spurious_writable_wakeups > 20);
557
+
558
+ ASSERT(closed_connections == NUM_CLIENTS * 2);
559
+ }
560
+
561
+
562
+ TEST_IMPL(poll_duplex) {
563
+ test_mode = DUPLEX;
564
+ start_poll_test();
565
+ return 0;
566
+ }
567
+
568
+
569
+ TEST_IMPL(poll_unidirectional) {
570
+ test_mode = UNIDIRECTIONAL;
571
+ start_poll_test();
572
+ return 0;
573
+ }