libuv-svace-build
299 строк · 7.8 Кб
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
25#include <stdlib.h>26#include <string.h>27
28
29static char exepath[1024];30static size_t exepath_size = 1024;31static char* args[3];32static uv_process_options_t options;33static int close_cb_called;34static int exit_cb_called;35static int on_read_cb_called;36static int after_write_cb_called;37static uv_pipe_t in;38static uv_pipe_t out;39static uv_loop_t* loop;40#define OUTPUT_SIZE 102441static char output[OUTPUT_SIZE];42static int output_used;43
44
45static void close_cb(uv_handle_t* handle) {46close_cb_called++;47}
48
49
50static void exit_cb(uv_process_t* process,51int64_t exit_status,52int term_signal) {53printf("exit_cb\n");54exit_cb_called++;55ASSERT_OK(exit_status);56ASSERT_OK(term_signal);57uv_close((uv_handle_t*)process, close_cb);58uv_close((uv_handle_t*)&in, close_cb);59uv_close((uv_handle_t*)&out, close_cb);60}
61
62
63static void init_process_options(char* test, uv_exit_cb exit_cb) {64int r = uv_exepath(exepath, &exepath_size);65ASSERT_OK(r);66exepath[exepath_size] = '\0';67args[0] = exepath;68args[1] = test;69args[2] = NULL;70options.file = exepath;71options.args = args;72options.exit_cb = exit_cb;73}
74
75
76static void on_alloc(uv_handle_t* handle,77size_t suggested_size,78uv_buf_t* buf) {79buf->base = output + output_used;80buf->len = OUTPUT_SIZE - output_used;81}
82
83
84static void after_write(uv_write_t* req, int status) {85if (status) {86fprintf(stderr, "uv_write error: %s\n", uv_strerror(status));87ASSERT(0);88}89
90/* Free the read/write buffer and the request */91free(req);92
93after_write_cb_called++;94}
95
96
97static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* rdbuf) {98uv_write_t* req;99uv_buf_t wrbuf;100int r;101
102ASSERT(nread > 0 || nread == UV_EOF);103
104if (nread > 0) {105output_used += nread;106if (output_used % 12 == 0) {107ASSERT_OK(memcmp("hello world\n", output, 12));108wrbuf = uv_buf_init(output, 12);109req = malloc(sizeof(*req));110r = uv_write(req, (uv_stream_t*) &in, &wrbuf, 1, after_write);111ASSERT_OK(r);112}113}114
115on_read_cb_called++;116}
117
118
119static void test_stdio_over_pipes(int overlapped) {120int r;121uv_process_t process;122uv_stdio_container_t stdio[3];123
124loop = uv_default_loop();125
126init_process_options("stdio_over_pipes_helper", exit_cb);127
128uv_pipe_init(loop, &out, 0);129uv_pipe_init(loop, &in, 0);130
131options.stdio = stdio;132options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE |133(overlapped ? UV_OVERLAPPED_PIPE : 0);134options.stdio[0].data.stream = (uv_stream_t*) ∈135options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE |136(overlapped ? UV_OVERLAPPED_PIPE : 0);137options.stdio[1].data.stream = (uv_stream_t*) &out;138options.stdio[2].flags = UV_INHERIT_FD;139options.stdio[2].data.fd = 2;140options.stdio_count = 3;141
142r = uv_spawn(loop, &process, &options);143ASSERT_OK(r);144
145r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);146ASSERT_OK(r);147
148r = uv_run(loop, UV_RUN_DEFAULT);149ASSERT_OK(r);150
151ASSERT_GT(on_read_cb_called, 1);152ASSERT_EQ(2, after_write_cb_called);153ASSERT_EQ(1, exit_cb_called);154ASSERT_EQ(3, close_cb_called);155ASSERT_OK(memcmp("hello world\nhello world\n", output, 24));156ASSERT_EQ(24, output_used);157
158MAKE_VALGRIND_HAPPY(loop);159}
160
161TEST_IMPL(stdio_over_pipes) {162test_stdio_over_pipes(0);163return 0;164}
165
166TEST_IMPL(stdio_emulate_iocp) {167test_stdio_over_pipes(1);168return 0;169}
170
171
172/* Everything here runs in a child process. */
173
174static int on_pipe_read_called;175static int after_write_called;176static uv_pipe_t stdin_pipe1;177static uv_pipe_t stdout_pipe1;178static uv_pipe_t stdin_pipe2;179static uv_pipe_t stdout_pipe2;180
181static void on_pipe_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) {182ASSERT_GT(nread, 0);183ASSERT_OK(memcmp("hello world\n", buf->base, nread));184on_pipe_read_called++;185
186free(buf->base);187
188uv_read_stop(pipe);189}
190
191
192static void after_pipe_write(uv_write_t* req, int status) {193ASSERT_OK(status);194after_write_called++;195}
196
197
198static void on_read_alloc(uv_handle_t* handle,199size_t suggested_size,200uv_buf_t* buf) {201buf->base = malloc(suggested_size);202buf->len = suggested_size;203}
204
205
206int stdio_over_pipes_helper(void) {207/* Write several buffers to test that the write order is preserved. */208char* buffers[] = {209"he",210"ll",211"o ",212"wo",213"rl",214"d",215"\n"216};217
218uv_write_t write_req[ARRAY_SIZE(buffers)];219uv_buf_t buf[ARRAY_SIZE(buffers)];220unsigned int i;221int j;222int r;223uv_loop_t* loop = uv_default_loop();224
225ASSERT_EQ(UV_NAMED_PIPE, uv_guess_handle(0));226ASSERT_EQ(UV_NAMED_PIPE, uv_guess_handle(1));227
228r = uv_pipe_init(loop, &stdin_pipe1, 0);229ASSERT_OK(r);230r = uv_pipe_init(loop, &stdout_pipe1, 0);231ASSERT_OK(r);232r = uv_pipe_init(loop, &stdin_pipe2, 0);233ASSERT_OK(r);234r = uv_pipe_init(loop, &stdout_pipe2, 0);235ASSERT_OK(r);236
237uv_pipe_open(&stdin_pipe1, 0);238uv_pipe_open(&stdout_pipe1, 1);239uv_pipe_open(&stdin_pipe2, 0);240uv_pipe_open(&stdout_pipe2, 1);241
242for (j = 0; j < 2; j++) {243/* Unref both stdio handles to make sure that all writes complete. */244uv_unref((uv_handle_t*) &stdin_pipe1);245uv_unref((uv_handle_t*) &stdout_pipe1);246uv_unref((uv_handle_t*) &stdin_pipe2);247uv_unref((uv_handle_t*) &stdout_pipe2);248
249for (i = 0; i < ARRAY_SIZE(buffers); i++) {250buf[i] = uv_buf_init((char*) buffers[i], strlen(buffers[i]));251}252
253for (i = 0; i < ARRAY_SIZE(buffers); i++) {254r = uv_write(&write_req[i],255(uv_stream_t*) (j == 0 ? &stdout_pipe1 : &stdout_pipe2),256&buf[i],2571,258after_pipe_write);259ASSERT_OK(r);260}261
262notify_parent_process();263uv_run(loop, UV_RUN_DEFAULT);264
265ASSERT_EQ(after_write_called, 7 * (j + 1));266ASSERT_EQ(on_pipe_read_called, j);267ASSERT_OK(close_cb_called);268
269uv_ref((uv_handle_t*) &stdout_pipe1);270uv_ref((uv_handle_t*) &stdin_pipe1);271uv_ref((uv_handle_t*) &stdout_pipe2);272uv_ref((uv_handle_t*) &stdin_pipe2);273
274r = uv_read_start((uv_stream_t*) (j == 0 ? &stdin_pipe1 : &stdin_pipe2),275on_read_alloc,276on_pipe_read);277ASSERT_OK(r);278
279uv_run(loop, UV_RUN_DEFAULT);280
281ASSERT_EQ(after_write_called, 7 * (j + 1));282ASSERT_EQ(on_pipe_read_called, j + 1);283ASSERT_OK(close_cb_called);284}285
286uv_close((uv_handle_t*)&stdin_pipe1, close_cb);287uv_close((uv_handle_t*)&stdout_pipe1, close_cb);288uv_close((uv_handle_t*)&stdin_pipe2, close_cb);289uv_close((uv_handle_t*)&stdout_pipe2, close_cb);290
291uv_run(loop, UV_RUN_DEFAULT);292
293ASSERT_EQ(14, after_write_called);294ASSERT_EQ(2, on_pipe_read_called);295ASSERT_EQ(4, close_cb_called);296
297MAKE_VALGRIND_HAPPY(loop);298return 0;299}
300