asyncengine 0.0.1.testing1 → 0.0.2.alpha1

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 (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -21,10 +21,16 @@
21
21
 
22
22
  #include "uv.h"
23
23
  #include "task.h"
24
+ #include <fcntl.h>
24
25
  #include <stdio.h>
25
26
  #include <stdlib.h>
26
27
  #include <string.h>
27
28
 
29
+ #ifndef _WIN32
30
+ #include <unistd.h>
31
+ #endif
32
+
33
+
28
34
  static int close_cb_called;
29
35
  static int exit_cb_called;
30
36
  static uv_process_t process;
@@ -55,6 +61,22 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
55
61
  }
56
62
 
57
63
 
64
+ static void exit_cb_failure_expected(uv_process_t* process, int exit_status,
65
+ int term_signal) {
66
+ printf("exit_cb\n");
67
+ exit_cb_called++;
68
+ ASSERT(exit_status == 127);
69
+ ASSERT(term_signal == 0);
70
+ uv_close((uv_handle_t*)process, close_cb);
71
+ }
72
+
73
+
74
+ static void exit_cb_unexpected(uv_process_t* process, int exit_status,
75
+ int term_signal) {
76
+ ASSERT(0 && "should not have been called");
77
+ }
78
+
79
+
58
80
  static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
59
81
  uv_err_t err;
60
82
 
@@ -77,6 +99,10 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
77
99
  ASSERT(err.code == UV_ESRCH);
78
100
  }
79
101
 
102
+ static void detach_failure_cb(uv_process_t* process, int exit_status, int term_signal) {
103
+ printf("detach_cb\n");
104
+ exit_cb_called++;
105
+ }
80
106
 
81
107
  static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
82
108
  uv_buf_t buf;
@@ -92,9 +118,8 @@ void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
92
118
  if (nread > 0) {
93
119
  output_used += nread;
94
120
  } else if (nread < 0) {
95
- if (err.code == UV_EOF) {
96
- uv_close((uv_handle_t*)tcp, close_cb);
97
- }
121
+ ASSERT(err.code == UV_EOF);
122
+ uv_close((uv_handle_t*)tcp, close_cb);
98
123
  }
99
124
  }
100
125
 
@@ -116,6 +141,7 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) {
116
141
  options.file = exepath;
117
142
  options.args = args;
118
143
  options.exit_cb = exit_cb;
144
+ options.flags = 0;
119
145
  }
120
146
 
121
147
 
@@ -146,11 +172,16 @@ TEST_IMPL(spawn_exit_code) {
146
172
  TEST_IMPL(spawn_stdout) {
147
173
  int r;
148
174
  uv_pipe_t out;
175
+ uv_stdio_container_t stdio[2];
149
176
 
150
177
  init_process_options("spawn_helper2", exit_cb);
151
178
 
152
179
  uv_pipe_init(uv_default_loop(), &out, 0);
153
- options.stdout_stream = &out;
180
+ options.stdio = stdio;
181
+ options.stdio[0].flags = UV_IGNORE;
182
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
183
+ options.stdio[1].data.stream = (uv_stream_t*)&out;
184
+ options.stdio_count = 2;
154
185
 
155
186
  r = uv_spawn(uv_default_loop(), &process, options);
156
187
  ASSERT(r == 0);
@@ -164,7 +195,59 @@ TEST_IMPL(spawn_stdout) {
164
195
  ASSERT(exit_cb_called == 1);
165
196
  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
166
197
  printf("output is: %s", output);
167
- ASSERT(strcmp("hello world\n", output) == 0 || strcmp("hello world\r\n", output) == 0);
198
+ ASSERT(strcmp("hello world\n", output) == 0);
199
+
200
+ return 0;
201
+ }
202
+
203
+
204
+ TEST_IMPL(spawn_stdout_to_file) {
205
+ int r;
206
+ uv_file file;
207
+ uv_fs_t fs_req;
208
+ uv_stdio_container_t stdio[2];
209
+
210
+ /* Setup. */
211
+ unlink("stdout_file");
212
+
213
+ init_process_options("spawn_helper2", exit_cb);
214
+
215
+ r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
216
+ S_IREAD | S_IWRITE, NULL);
217
+ ASSERT(r != -1);
218
+ uv_fs_req_cleanup(&fs_req);
219
+
220
+ file = r;
221
+
222
+ options.stdio = stdio;
223
+ options.stdio[0].flags = UV_IGNORE;
224
+ options.stdio[1].flags = UV_INHERIT_FD;
225
+ options.stdio[1].data.fd = file;
226
+ options.stdio_count = 2;
227
+
228
+ r = uv_spawn(uv_default_loop(), &process, options);
229
+ ASSERT(r == 0);
230
+
231
+ r = uv_run(uv_default_loop());
232
+ ASSERT(r == 0);
233
+
234
+ ASSERT(exit_cb_called == 1);
235
+ ASSERT(close_cb_called == 1);
236
+
237
+ r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
238
+ 0, NULL);
239
+ ASSERT(r == 12);
240
+ uv_fs_req_cleanup(&fs_req);
241
+
242
+ r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
243
+ ASSERT(r == 0);
244
+ uv_fs_req_cleanup(&fs_req);
245
+
246
+ printf("output is: %s", output);
247
+ ASSERT(strcmp("hello world\n", output) == 0);
248
+
249
+ /* Cleanup. */
250
+ unlink("stdout_file");
168
251
 
169
252
  return 0;
170
253
  }
@@ -176,14 +259,19 @@ TEST_IMPL(spawn_stdin) {
176
259
  uv_pipe_t in;
177
260
  uv_write_t write_req;
178
261
  uv_buf_t buf;
262
+ uv_stdio_container_t stdio[2];
179
263
  char buffer[] = "hello-from-spawn_stdin";
180
264
 
181
265
  init_process_options("spawn_helper3", exit_cb);
182
266
 
183
267
  uv_pipe_init(uv_default_loop(), &out, 0);
184
268
  uv_pipe_init(uv_default_loop(), &in, 0);
185
- options.stdout_stream = &out;
186
- options.stdin_stream = &in;
269
+ options.stdio = stdio;
270
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
271
+ options.stdio[0].data.stream = (uv_stream_t*)&in;
272
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
273
+ options.stdio[1].data.stream = (uv_stream_t*)&out;
274
+ options.stdio_count = 2;
187
275
 
188
276
  r = uv_spawn(uv_default_loop(), &process, options);
189
277
  ASSERT(r == 0);
@@ -207,6 +295,61 @@ TEST_IMPL(spawn_stdin) {
207
295
  }
208
296
 
209
297
 
298
+ TEST_IMPL(spawn_stdio_greater_than_3) {
299
+ int r;
300
+ uv_pipe_t pipe;
301
+ uv_stdio_container_t stdio[4];
302
+
303
+ init_process_options("spawn_helper5", exit_cb);
304
+
305
+ uv_pipe_init(uv_default_loop(), &pipe, 0);
306
+ options.stdio = stdio;
307
+ options.stdio[0].flags = UV_IGNORE;
308
+ options.stdio[1].flags = UV_IGNORE;
309
+ options.stdio[2].flags = UV_IGNORE;
310
+ options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
311
+ options.stdio[3].data.stream = (uv_stream_t*)&pipe;
312
+ options.stdio_count = 4;
313
+
314
+ r = uv_spawn(uv_default_loop(), &process, options);
315
+ ASSERT(r == 0);
316
+
317
+ r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read);
318
+ ASSERT(r == 0);
319
+
320
+ r = uv_run(uv_default_loop());
321
+ ASSERT(r == 0);
322
+
323
+ ASSERT(exit_cb_called == 1);
324
+ ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
325
+ printf("output from stdio[3] is: %s", output);
326
+ ASSERT(strcmp("fourth stdio!\n", output) == 0);
327
+
328
+ return 0;
329
+ }
330
+
331
+
332
+ TEST_IMPL(spawn_ignored_stdio) {
333
+ int r;
334
+
335
+ init_process_options("spawn_helper6", exit_cb);
336
+
337
+ options.stdio = NULL;
338
+ options.stdio_count = 0;
339
+
340
+ r = uv_spawn(uv_default_loop(), &process, options);
341
+ ASSERT(r == 0);
342
+
343
+ r = uv_run(uv_default_loop());
344
+ ASSERT(r == 0);
345
+
346
+ ASSERT(exit_cb_called == 1);
347
+ ASSERT(close_cb_called == 1);
348
+
349
+ return 0;
350
+ }
351
+
352
+
210
353
  TEST_IMPL(spawn_and_kill) {
211
354
  int r;
212
355
 
@@ -230,22 +373,75 @@ TEST_IMPL(spawn_and_kill) {
230
373
  return 0;
231
374
  }
232
375
 
376
+ TEST_IMPL(spawn_detached) {
377
+ int r;
378
+ uv_err_t err;
379
+
380
+ init_process_options("spawn_helper4", detach_failure_cb);
381
+
382
+ options.flags |= UV_PROCESS_DETACHED;
383
+
384
+ r = uv_spawn(uv_default_loop(), &process, options);
385
+ ASSERT(r == 0);
386
+
387
+ uv_unref((uv_handle_t*)&process);
388
+
389
+ r = uv_run(uv_default_loop());
390
+ ASSERT(r == 0);
391
+
392
+ ASSERT(exit_cb_called == 0);
393
+
394
+ err = uv_kill(process.pid, 0);
395
+ ASSERT(err.code == 0);
396
+
397
+ err = uv_kill(process.pid, 15);
398
+ ASSERT(err.code == 0);
399
+
400
+ return 0;
401
+ }
233
402
 
234
403
  TEST_IMPL(spawn_and_kill_with_std) {
235
404
  int r;
236
- uv_pipe_t out;
237
- uv_pipe_t in;
405
+ uv_pipe_t in, out, err;
406
+ uv_write_t write;
407
+ char message[] = "Nancy's joining me because the message this evening is "
408
+ "not my message but ours.";
409
+ uv_buf_t buf;
410
+ uv_stdio_container_t stdio[3];
238
411
 
239
412
  init_process_options("spawn_helper4", kill_cb);
240
413
 
241
- uv_pipe_init(uv_default_loop(), &out, 0);
242
- uv_pipe_init(uv_default_loop(), &in, 0);
243
- options.stdout_stream = &out;
244
- options.stdin_stream = &in;
414
+ r = uv_pipe_init(uv_default_loop(), &in, 0);
415
+ ASSERT(r == 0);
416
+
417
+ r = uv_pipe_init(uv_default_loop(), &out, 0);
418
+ ASSERT(r == 0);
419
+
420
+ r = uv_pipe_init(uv_default_loop(), &err, 0);
421
+ ASSERT(r == 0);
422
+
423
+ options.stdio = stdio;
424
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
425
+ options.stdio[0].data.stream = (uv_stream_t*)&in;
426
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
427
+ options.stdio[1].data.stream = (uv_stream_t*)&out;
428
+ options.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
429
+ options.stdio[2].data.stream = (uv_stream_t*)&err;
430
+ options.stdio_count = 3;
245
431
 
246
432
  r = uv_spawn(uv_default_loop(), &process, options);
247
433
  ASSERT(r == 0);
248
434
 
435
+ buf = uv_buf_init(message, sizeof message);
436
+ r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb);
437
+ ASSERT(r == 0);
438
+
439
+ r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
440
+ ASSERT(r == 0);
441
+
442
+ r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read);
443
+ ASSERT(r == 0);
444
+
249
445
  r = uv_timer_init(uv_default_loop(), &timer);
250
446
  ASSERT(r == 0);
251
447
 
@@ -256,7 +452,7 @@ TEST_IMPL(spawn_and_kill_with_std) {
256
452
  ASSERT(r == 0);
257
453
 
258
454
  ASSERT(exit_cb_called == 1);
259
- ASSERT(close_cb_called == 2); /* Once for process and once for timer. */
455
+ ASSERT(close_cb_called == 5); /* process x 1, timer x 1, stdio x 3. */
260
456
 
261
457
  return 0;
262
458
  }
@@ -266,6 +462,7 @@ TEST_IMPL(spawn_and_ping) {
266
462
  uv_write_t write_req;
267
463
  uv_pipe_t in, out;
268
464
  uv_buf_t buf;
465
+ uv_stdio_container_t stdio[2];
269
466
  int r;
270
467
 
271
468
  init_process_options("spawn_helper3", exit_cb);
@@ -273,8 +470,12 @@ TEST_IMPL(spawn_and_ping) {
273
470
 
274
471
  uv_pipe_init(uv_default_loop(), &out, 0);
275
472
  uv_pipe_init(uv_default_loop(), &in, 0);
276
- options.stdout_stream = &out;
277
- options.stdin_stream = &in;
473
+ options.stdio = stdio;
474
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
475
+ options.stdio[0].data.stream = (uv_stream_t*)&in;
476
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
477
+ options.stdio[1].data.stream = (uv_stream_t*)&out;
478
+ options.stdio_count = 2;
278
479
 
279
480
  r = uv_spawn(uv_default_loop(), &process, options);
280
481
  ASSERT(r == 0);
@@ -342,11 +543,16 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
342
543
  uv_pipe_t out;
343
544
  char name[64];
344
545
  HANDLE pipe_handle;
546
+ uv_stdio_container_t stdio[2];
345
547
 
346
548
  init_process_options("spawn_helper2", exit_cb);
347
549
 
348
550
  uv_pipe_init(uv_default_loop(), &out, 0);
349
- options.stdout_stream = &out;
551
+ options.stdio = stdio;
552
+ options.stdio[0].flags = UV_IGNORE;
553
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
554
+ options.stdio[1].data.stream = (uv_stream_t*)&out;
555
+ options.stdio_count = 2;
350
556
 
351
557
  /* Create a pipe that'll cause a collision. */
352
558
  _snprintf(name, sizeof(name), "\\\\.\\pipe\\uv\\%p-%d", &out, GetCurrentProcessId());
@@ -372,7 +578,7 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
372
578
  ASSERT(exit_cb_called == 1);
373
579
  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
374
580
  printf("output is: %s", output);
375
- ASSERT(strcmp("hello world\n", output) == 0 || strcmp("hello world\r\n", output) == 0);
581
+ ASSERT(strcmp("hello world\n", output) == 0);
376
582
 
377
583
  return 0;
378
584
  }
@@ -485,7 +691,7 @@ TEST_IMPL(environment_creation) {
485
691
  ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE", ptr, expected + sizeof(expected) - ptr);
486
692
  ++ptr;
487
693
  *ptr = '\0';
488
-
694
+
489
695
  result = make_program_env(environment);
490
696
 
491
697
  for (str = result; *str; str += wcslen(str) + 1) {
@@ -493,7 +699,149 @@ TEST_IMPL(environment_creation) {
493
699
  }
494
700
 
495
701
  ASSERT(wcscmp(expected, result) == 0);
496
-
702
+
703
+ return 0;
704
+ }
705
+ #endif
706
+
707
+ #ifndef _WIN32
708
+ TEST_IMPL(spawn_setuid_setgid) {
709
+ int r;
710
+
711
+ /* if not root, then this will fail. */
712
+ uv_uid_t uid = getuid();
713
+ if (uid != 0) {
714
+ fprintf(stderr, "spawn_setuid_setgid skipped: not root\n");
715
+ return 0;
716
+ }
717
+
718
+ init_process_options("spawn_helper1", exit_cb);
719
+
720
+ /* become the "nobody" user. */
721
+ struct passwd* pw;
722
+ pw = getpwnam("nobody");
723
+ ASSERT(pw != NULL);
724
+ options.uid = pw->pw_uid;
725
+ options.gid = pw->pw_gid;
726
+ options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
727
+
728
+ r = uv_spawn(uv_default_loop(), &process, options);
729
+ ASSERT(r == 0);
730
+
731
+ r = uv_run(uv_default_loop());
732
+ ASSERT(r == 0);
733
+
734
+ ASSERT(exit_cb_called == 1);
735
+ ASSERT(close_cb_called == 1);
736
+
737
+ return 0;
738
+ }
739
+ #endif
740
+
741
+
742
+ #ifndef _WIN32
743
+ TEST_IMPL(spawn_setuid_fails) {
744
+ int r;
745
+
746
+ /* if root, become nobody. */
747
+ uv_uid_t uid = getuid();
748
+ if (uid == 0) {
749
+ struct passwd* pw;
750
+ pw = getpwnam("nobody");
751
+ ASSERT(pw != NULL);
752
+ r = setuid(pw->pw_uid);
753
+ ASSERT(r == 0);
754
+ }
755
+
756
+ init_process_options("spawn_helper1", exit_cb_failure_expected);
757
+
758
+ options.flags |= UV_PROCESS_SETUID;
759
+ options.uid = (uv_uid_t) -42424242;
760
+
761
+ r = uv_spawn(uv_default_loop(), &process, options);
762
+ ASSERT(r == 0);
763
+
764
+ r = uv_run(uv_default_loop());
765
+ ASSERT(r == 0);
766
+
767
+ ASSERT(exit_cb_called == 1);
768
+ ASSERT(close_cb_called == 1);
769
+
770
+ return 0;
771
+ }
772
+
773
+
774
+ TEST_IMPL(spawn_setgid_fails) {
775
+ int r;
776
+
777
+ /* if root, become nobody. */
778
+ uv_uid_t uid = getuid();
779
+ if (uid == 0) {
780
+ struct passwd* pw;
781
+ pw = getpwnam("nobody");
782
+ ASSERT(pw != NULL);
783
+ r = setuid(pw->pw_uid);
784
+ ASSERT(r == 0);
785
+ }
786
+
787
+ init_process_options("spawn_helper1", exit_cb_failure_expected);
788
+
789
+ options.flags |= UV_PROCESS_SETGID;
790
+ options.gid = (uv_gid_t) -42424242;
791
+
792
+ r = uv_spawn(uv_default_loop(), &process, options);
793
+ ASSERT(r == 0);
794
+
795
+ r = uv_run(uv_default_loop());
796
+ ASSERT(r == 0);
797
+
798
+ ASSERT(exit_cb_called == 1);
799
+ ASSERT(close_cb_called == 1);
800
+
801
+ return 0;
802
+ }
803
+ #endif
804
+
805
+
806
+ #ifdef _WIN32
807
+ TEST_IMPL(spawn_setuid_fails) {
808
+ int r;
809
+
810
+ init_process_options("spawn_helper1", exit_cb_unexpected);
811
+
812
+ options.flags |= UV_PROCESS_SETUID;
813
+ options.uid = (uv_uid_t) -42424242;
814
+
815
+ r = uv_spawn(uv_default_loop(), &process, options);
816
+ ASSERT(r == -1);
817
+ ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP);
818
+
819
+ r = uv_run(uv_default_loop());
820
+ ASSERT(r == 0);
821
+
822
+ ASSERT(close_cb_called == 0);
823
+
824
+ return 0;
825
+ }
826
+
827
+
828
+ TEST_IMPL(spawn_setgid_fails) {
829
+ int r;
830
+
831
+ init_process_options("spawn_helper1", exit_cb_unexpected);
832
+
833
+ options.flags |= UV_PROCESS_SETGID;
834
+ options.gid = (uv_gid_t) -42424242;
835
+
836
+ r = uv_spawn(uv_default_loop(), &process, options);
837
+ ASSERT(r == -1);
838
+ ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP);
839
+
840
+ r = uv_run(uv_default_loop());
841
+ ASSERT(r == 0);
842
+
843
+ ASSERT(close_cb_called == 0);
844
+
497
845
  return 0;
498
846
  }
499
847
  #endif