libuv-svace-build
857 строк · 21.0 Кб
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 <stdio.h>26#include <string.h>27
28static uv_pipe_t channel;29static uv_tcp_t tcp_server;30static uv_tcp_t tcp_server2;31static uv_tcp_t tcp_connection;32
33static int exit_cb_called;34static int read_cb_called;35static int tcp_write_cb_called;36static int tcp_read_cb_called;37static int on_pipe_read_called;38static int local_conn_accepted;39static int remote_conn_accepted;40static int tcp_server_listening;41static uv_write_t write_req;42static uv_write_t write_req2;43static uv_write_t conn_notify_req;44static int close_cb_called;45static int connection_accepted;46static int tcp_conn_read_cb_called;47static int tcp_conn_write_cb_called;48static int send_zero_write;49
50typedef struct {51uv_connect_t conn_req;52uv_write_t tcp_write_req;53uv_tcp_t conn;54} tcp_conn;55
56#define CONN_COUNT 10057#define BACKLOG 12858
59
60static void close_server_conn_cb(uv_handle_t* handle) {61free(handle);62}
63
64
65static void on_connection(uv_stream_t* server, int status) {66uv_tcp_t* conn;67int r;68
69if (!local_conn_accepted) {70/* Accept the connection and close it. Also and close the server. */71ASSERT_OK(status);72ASSERT_PTR_EQ(&tcp_server, server);73
74conn = malloc(sizeof(*conn));75ASSERT_NOT_NULL(conn);76r = uv_tcp_init(server->loop, conn);77ASSERT_OK(r);78
79r = uv_accept(server, (uv_stream_t*)conn);80ASSERT_OK(r);81
82uv_close((uv_handle_t*)conn, close_server_conn_cb);83uv_close((uv_handle_t*)server, NULL);84local_conn_accepted = 1;85}86}
87
88
89static void exit_cb(uv_process_t* process,90int64_t exit_status,91int term_signal) {92printf("exit_cb\n");93exit_cb_called++;94ASSERT_OK(exit_status);95ASSERT_OK(term_signal);96uv_close((uv_handle_t*)process, NULL);97}
98
99
100static void on_alloc(uv_handle_t* handle,101size_t suggested_size,102uv_buf_t* buf) {103buf->base = malloc(suggested_size);104buf->len = suggested_size;105}
106
107
108static void close_client_conn_cb(uv_handle_t* handle) {109tcp_conn* p = (tcp_conn*)handle->data;110free(p);111}
112
113
114static void connect_cb(uv_connect_t* req, int status) {115uv_close((uv_handle_t*)req->handle, close_client_conn_cb);116}
117
118
119static void make_many_connections(void) {120tcp_conn* conn;121struct sockaddr_in addr;122int r, i;123
124for (i = 0; i < CONN_COUNT; i++) {125conn = malloc(sizeof(*conn));126ASSERT_NOT_NULL(conn);127
128r = uv_tcp_init(uv_default_loop(), &conn->conn);129ASSERT_OK(r);130ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));131
132r = uv_tcp_connect(&conn->conn_req,133(uv_tcp_t*) &conn->conn,134(const struct sockaddr*) &addr,135connect_cb);136ASSERT_OK(r);137
138conn->conn.data = conn;139}140}
141
142
143static void on_read(uv_stream_t* handle,144ssize_t nread,145const uv_buf_t* buf) {146int r;147uv_pipe_t* pipe;148uv_handle_type pending;149uv_buf_t outbuf;150
151pipe = (uv_pipe_t*) handle;152
153if (nread == 0) {154/* Everything OK, but nothing read. */155free(buf->base);156return;157}158
159if (nread < 0) {160if (nread == UV_EOF) {161free(buf->base);162return;163}164
165printf("error recving on channel: %s\n", uv_strerror(nread));166abort();167}168
169fprintf(stderr, "got %d bytes\n", (int)nread);170
171pending = uv_pipe_pending_type(pipe);172if (!tcp_server_listening) {173ASSERT_EQ(1, uv_pipe_pending_count(pipe));174ASSERT_GT(nread, 0);175ASSERT_NOT_NULL(buf->base);176ASSERT_NE(pending, UV_UNKNOWN_HANDLE);177read_cb_called++;178
179/* Accept the pending TCP server, and start listening on it. */180ASSERT_EQ(pending, UV_TCP);181r = uv_tcp_init(uv_default_loop(), &tcp_server);182ASSERT_OK(r);183
184r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);185ASSERT_OK(r);186
187r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);188ASSERT_OK(r);189
190tcp_server_listening = 1;191
192/* Make sure that the expected data is correctly multiplexed. */193ASSERT_MEM_EQ("hello\n", buf->base, nread);194
195outbuf = uv_buf_init("foobar\n", 7);196r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL);197ASSERT_OK(r);198
199/* Create a bunch of connections to get both servers to accept. */200make_many_connections();201} else if (memcmp("accepted_connection\n", buf->base, nread) == 0) {202/* Remote server has accepted a connection. Close the channel. */203ASSERT_OK(uv_pipe_pending_count(pipe));204ASSERT_EQ(pending, UV_UNKNOWN_HANDLE);205remote_conn_accepted = 1;206uv_close((uv_handle_t*)&channel, NULL);207}208
209free(buf->base);210}
211
212#ifdef _WIN32213static void on_read_listen_after_bound_twice(uv_stream_t* handle,214ssize_t nread,215const uv_buf_t* buf) {216int r;217uv_pipe_t* pipe;218uv_handle_type pending;219
220pipe = (uv_pipe_t*) handle;221
222if (nread == 0) {223/* Everything OK, but nothing read. */224free(buf->base);225return;226}227
228if (nread < 0) {229if (nread == UV_EOF) {230free(buf->base);231return;232}233
234printf("error recving on channel: %s\n", uv_strerror(nread));235abort();236}237
238fprintf(stderr, "got %d bytes\n", (int)nread);239
240ASSERT_GT(uv_pipe_pending_count(pipe), 0);241pending = uv_pipe_pending_type(pipe);242ASSERT_GT(nread, 0);243ASSERT_NOT_NULL(buf->base);244ASSERT_NE(pending, UV_UNKNOWN_HANDLE);245read_cb_called++;246
247if (read_cb_called == 1) {248/* Accept the first TCP server, and start listening on it. */249ASSERT_EQ(pending, UV_TCP);250r = uv_tcp_init(uv_default_loop(), &tcp_server);251ASSERT_OK(r);252
253r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);254ASSERT_OK(r);255
256r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);257ASSERT_OK(r);258} else if (read_cb_called == 2) {259/* Accept the second TCP server, and start listening on it. */260ASSERT_EQ(pending, UV_TCP);261r = uv_tcp_init(uv_default_loop(), &tcp_server2);262ASSERT_OK(r);263
264r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2);265ASSERT_OK(r);266
267r = uv_listen((uv_stream_t*)&tcp_server2, BACKLOG, on_connection);268ASSERT_EQ(r, UV_EADDRINUSE);269
270uv_close((uv_handle_t*)&tcp_server, NULL);271uv_close((uv_handle_t*)&tcp_server2, NULL);272ASSERT_OK(uv_pipe_pending_count(pipe));273uv_close((uv_handle_t*)&channel, NULL);274}275
276free(buf->base);277}
278#endif279
280void spawn_helper(uv_pipe_t* channel,281uv_process_t* process,282const char* helper) {283uv_process_options_t options;284size_t exepath_size;285char exepath[1024];286char* args[3];287int r;288uv_stdio_container_t stdio[3];289
290r = uv_pipe_init(uv_default_loop(), channel, 1);291ASSERT_OK(r);292ASSERT_NE(0, channel->ipc);293
294exepath_size = sizeof(exepath);295r = uv_exepath(exepath, &exepath_size);296ASSERT_OK(r);297
298exepath[exepath_size] = '\0';299args[0] = exepath;300args[1] = (char*)helper;301args[2] = NULL;302
303memset(&options, 0, sizeof(options));304options.file = exepath;305options.args = args;306options.exit_cb = exit_cb;307options.stdio = stdio;308options.stdio_count = ARRAY_SIZE(stdio);309
310stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE;311stdio[0].data.stream = (uv_stream_t*) channel;312stdio[1].flags = UV_INHERIT_FD;313stdio[1].data.fd = 1;314stdio[2].flags = UV_INHERIT_FD;315stdio[2].data.fd = 2;316
317r = uv_spawn(uv_default_loop(), process, &options);318ASSERT_OK(r);319}
320
321
322static void on_tcp_write(uv_write_t* req, int status) {323ASSERT_OK(status);324ASSERT_PTR_EQ(req->handle, &tcp_connection);325tcp_write_cb_called++;326}
327
328
329static void on_read_alloc(uv_handle_t* handle,330size_t suggested_size,331uv_buf_t* buf) {332buf->base = malloc(suggested_size);333buf->len = suggested_size;334}
335
336
337static void on_tcp_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {338ASSERT_GT(nread, 0);339ASSERT_MEM_EQ("hello again\n", buf->base, nread);340ASSERT_PTR_EQ(tcp, &tcp_connection);341free(buf->base);342
343tcp_read_cb_called++;344
345uv_close((uv_handle_t*)tcp, NULL);346uv_close((uv_handle_t*)&channel, NULL);347}
348
349
350static void on_read_connection(uv_stream_t* handle,351ssize_t nread,352const uv_buf_t* buf) {353int r;354uv_buf_t outbuf;355uv_pipe_t* pipe;356uv_handle_type pending;357
358pipe = (uv_pipe_t*) handle;359if (nread == 0) {360/* Everything OK, but nothing read. */361free(buf->base);362return;363}364
365if (nread < 0) {366if (nread == UV_EOF) {367free(buf->base);368return;369}370
371printf("error recving on channel: %s\n", uv_strerror(nread));372abort();373}374
375fprintf(stderr, "got %d bytes\n", (int)nread);376
377ASSERT_EQ(1, uv_pipe_pending_count(pipe));378pending = uv_pipe_pending_type(pipe);379
380ASSERT_GT(nread, 0);381ASSERT_NOT_NULL(buf->base);382ASSERT_NE(pending, UV_UNKNOWN_HANDLE);383read_cb_called++;384
385/* Accept the pending TCP connection */386ASSERT_EQ(pending, UV_TCP);387r = uv_tcp_init(uv_default_loop(), &tcp_connection);388ASSERT_OK(r);389
390r = uv_accept(handle, (uv_stream_t*)&tcp_connection);391ASSERT_OK(r);392
393/* Make sure that the expected data is correctly multiplexed. */394ASSERT_MEM_EQ("hello\n", buf->base, nread);395
396/* Write/read to/from the connection */397outbuf = uv_buf_init("world\n", 6);398r = uv_write(&write_req, (uv_stream_t*)&tcp_connection, &outbuf, 1,399on_tcp_write);400ASSERT_OK(r);401
402r = uv_read_start((uv_stream_t*)&tcp_connection, on_read_alloc, on_tcp_read);403ASSERT_OK(r);404
405free(buf->base);406}
407
408
409static void on_read_send_zero(uv_stream_t* handle,410ssize_t nread,411const uv_buf_t* buf) {412ASSERT(nread == 0 || nread == UV_EOF);413free(buf->base);414}
415
416
417static int run_ipc_test(const char* helper, uv_read_cb read_cb) {418uv_process_t process;419int r;420
421spawn_helper(&channel, &process, helper);422uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb);423
424r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);425ASSERT_OK(r);426
427MAKE_VALGRIND_HAPPY(uv_default_loop());428return 0;429}
430
431
432TEST_IMPL(ipc_listen_before_write) {433#if defined(NO_SEND_HANDLE_ON_PIPE)434RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);435#endif436int r = run_ipc_test("ipc_helper_listen_before_write", on_read);437ASSERT_EQ(1, local_conn_accepted);438ASSERT_EQ(1, remote_conn_accepted);439ASSERT_EQ(1, read_cb_called);440ASSERT_EQ(1, exit_cb_called);441return r;442}
443
444
445TEST_IMPL(ipc_listen_after_write) {446#if defined(NO_SEND_HANDLE_ON_PIPE)447RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);448#endif449int r = run_ipc_test("ipc_helper_listen_after_write", on_read);450ASSERT_EQ(1, local_conn_accepted);451ASSERT_EQ(1, remote_conn_accepted);452ASSERT_EQ(1, read_cb_called);453ASSERT_EQ(1, exit_cb_called);454return r;455}
456
457
458TEST_IMPL(ipc_tcp_connection) {459#if defined(NO_SEND_HANDLE_ON_PIPE)460RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);461#endif462int r = run_ipc_test("ipc_helper_tcp_connection", on_read_connection);463ASSERT_EQ(1, read_cb_called);464ASSERT_EQ(1, tcp_write_cb_called);465ASSERT_EQ(1, tcp_read_cb_called);466ASSERT_EQ(1, exit_cb_called);467return r;468}
469
470
471#ifdef _WIN32472TEST_IMPL(listen_with_simultaneous_accepts) {473uv_tcp_t server;474int r;475struct sockaddr_in addr;476
477ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));478
479r = uv_tcp_init(uv_default_loop(), &server);480ASSERT_OK(r);481
482r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);483ASSERT_OK(r);484
485r = uv_tcp_simultaneous_accepts(&server, 1);486ASSERT_OK(r);487
488r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);489ASSERT_OK(r);490ASSERT_EQ(32, server.reqs_pending);491
492MAKE_VALGRIND_HAPPY(uv_default_loop());493return 0;494}
495
496
497TEST_IMPL(listen_no_simultaneous_accepts) {498uv_tcp_t server;499int r;500struct sockaddr_in addr;501
502ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));503
504r = uv_tcp_init(uv_default_loop(), &server);505ASSERT_OK(r);506
507r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);508ASSERT_OK(r);509
510r = uv_tcp_simultaneous_accepts(&server, 0);511ASSERT_OK(r);512
513r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);514ASSERT_OK(r);515ASSERT_EQ(1, server.reqs_pending);516
517MAKE_VALGRIND_HAPPY(uv_default_loop());518return 0;519}
520
521TEST_IMPL(ipc_listen_after_bind_twice) {522#if defined(NO_SEND_HANDLE_ON_PIPE)523RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);524#endif525int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice);526ASSERT_EQ(2, read_cb_called);527ASSERT_EQ(1, exit_cb_called);528return r;529}
530#endif531
532TEST_IMPL(ipc_send_zero) {533int r;534r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero);535ASSERT_OK(r);536return 0;537}
538
539
540/* Everything here runs in a child process. */
541
542static tcp_conn conn;543
544
545static void close_cb(uv_handle_t* handle) {546close_cb_called++;547}
548
549
550static void conn_notify_write_cb(uv_write_t* req, int status) {551uv_close((uv_handle_t*)&tcp_server, close_cb);552uv_close((uv_handle_t*)&channel, close_cb);553}
554
555
556static void tcp_connection_write_cb(uv_write_t* req, int status) {557ASSERT_PTR_EQ(&conn.conn, req->handle);558uv_close((uv_handle_t*)req->handle, close_cb);559uv_close((uv_handle_t*)&channel, close_cb);560uv_close((uv_handle_t*)&tcp_server, close_cb);561tcp_conn_write_cb_called++;562}
563
564
565static void send_zero_write_cb(uv_write_t* req, int status) {566ASSERT_OK(status);567send_zero_write++;568}
569
570static void on_tcp_child_process_read(uv_stream_t* tcp,571ssize_t nread,572const uv_buf_t* buf) {573uv_buf_t outbuf;574int r;575
576if (nread < 0) {577if (nread == UV_EOF) {578free(buf->base);579return;580}581
582printf("error recving on tcp connection: %s\n", uv_strerror(nread));583abort();584}585
586ASSERT_GT(nread, 0);587ASSERT_MEM_EQ("world\n", buf->base, nread);588on_pipe_read_called++;589free(buf->base);590
591/* Write to the socket */592outbuf = uv_buf_init("hello again\n", 12);593r = uv_write(&conn.tcp_write_req, tcp, &outbuf, 1, tcp_connection_write_cb);594ASSERT_OK(r);595
596tcp_conn_read_cb_called++;597}
598
599
600static void connect_child_process_cb(uv_connect_t* req, int status) {601int r;602
603ASSERT_OK(status);604r = uv_read_start(req->handle, on_read_alloc, on_tcp_child_process_read);605ASSERT_OK(r);606}
607
608
609static void ipc_on_connection(uv_stream_t* server, int status) {610int r;611uv_buf_t buf;612
613if (!connection_accepted) {614/*615* Accept the connection and close it. Also let the other
616* side know.
617*/
618ASSERT_OK(status);619ASSERT_PTR_EQ(&tcp_server, server);620
621r = uv_tcp_init(server->loop, &conn.conn);622ASSERT_OK(r);623
624r = uv_accept(server, (uv_stream_t*)&conn.conn);625ASSERT_OK(r);626
627uv_close((uv_handle_t*)&conn.conn, close_cb);628
629buf = uv_buf_init("accepted_connection\n", 20);630r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,631NULL, conn_notify_write_cb);632ASSERT_OK(r);633
634connection_accepted = 1;635}636}
637
638
639static void close_and_free_cb(uv_handle_t* handle) {640close_cb_called++;641free(handle);642}
643
644static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) {645int r;646uv_buf_t buf;647uv_tcp_t* conn;648
649ASSERT_OK(status);650ASSERT_PTR_EQ(&tcp_server, server);651
652conn = malloc(sizeof(*conn));653ASSERT_NOT_NULL(conn);654
655r = uv_tcp_init(server->loop, conn);656ASSERT_OK(r);657
658r = uv_accept(server, (uv_stream_t*)conn);659ASSERT_OK(r);660
661/* Send the accepted connection to the other process */662buf = uv_buf_init("hello\n", 6);663r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,664(uv_stream_t*)conn, NULL);665ASSERT_OK(r);666
667r = uv_read_start((uv_stream_t*) conn,668on_read_alloc,669on_tcp_child_process_read);670ASSERT_OK(r);671
672uv_close((uv_handle_t*)conn, close_and_free_cb);673}
674
675
676int ipc_helper(int listen_after_write) {677/*678* This is launched from test-ipc.c. stdin is a duplex channel that we
679* over which a handle will be transmitted.
680*/
681struct sockaddr_in addr;682int r;683uv_buf_t buf;684
685ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));686
687r = uv_pipe_init(uv_default_loop(), &channel, 1);688ASSERT_OK(r);689
690uv_pipe_open(&channel, 0);691
692ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));693ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));694ASSERT_OK(uv_is_closing((uv_handle_t*) &channel));695
696r = uv_tcp_init(uv_default_loop(), &tcp_server);697ASSERT_OK(r);698
699r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);700ASSERT_OK(r);701
702if (!listen_after_write) {703r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);704ASSERT_OK(r);705}706
707buf = uv_buf_init("hello\n", 6);708r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,709(uv_stream_t*)&tcp_server, NULL);710ASSERT_OK(r);711
712if (listen_after_write) {713r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);714ASSERT_OK(r);715}716
717notify_parent_process();718r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);719ASSERT_OK(r);720
721ASSERT_EQ(1, connection_accepted);722ASSERT_EQ(3, close_cb_called);723
724MAKE_VALGRIND_HAPPY(uv_default_loop());725return 0;726}
727
728
729int ipc_helper_tcp_connection(void) {730/*731* This is launched from test-ipc.c. stdin is a duplex channel
732* over which a handle will be transmitted.
733*/
734
735int r;736struct sockaddr_in addr;737
738r = uv_pipe_init(uv_default_loop(), &channel, 1);739ASSERT_OK(r);740
741uv_pipe_open(&channel, 0);742
743ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));744ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));745ASSERT_OK(uv_is_closing((uv_handle_t*) &channel));746
747r = uv_tcp_init(uv_default_loop(), &tcp_server);748ASSERT_OK(r);749
750ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));751
752r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);753ASSERT_OK(r);754
755r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection_tcp_conn);756ASSERT_OK(r);757
758/* Make a connection to the server */759r = uv_tcp_init(uv_default_loop(), &conn.conn);760ASSERT_OK(r);761
762ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));763
764r = uv_tcp_connect(&conn.conn_req,765(uv_tcp_t*) &conn.conn,766(const struct sockaddr*) &addr,767connect_child_process_cb);768ASSERT_OK(r);769
770r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);771ASSERT_OK(r);772
773ASSERT_EQ(1, tcp_conn_read_cb_called);774ASSERT_EQ(1, tcp_conn_write_cb_called);775ASSERT_EQ(4, close_cb_called);776
777MAKE_VALGRIND_HAPPY(uv_default_loop());778return 0;779}
780
781int ipc_helper_bind_twice(void) {782/*783* This is launched from test-ipc.c. stdin is a duplex channel
784* over which two handles will be transmitted.
785*/
786struct sockaddr_in addr;787int r;788uv_buf_t buf;789
790ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));791
792r = uv_pipe_init(uv_default_loop(), &channel, 1);793ASSERT_OK(r);794
795uv_pipe_open(&channel, 0);796
797ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));798ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));799ASSERT_OK(uv_is_closing((uv_handle_t*) &channel));800
801buf = uv_buf_init("hello\n", 6);802
803r = uv_tcp_init(uv_default_loop(), &tcp_server);804ASSERT_OK(r);805r = uv_tcp_init(uv_default_loop(), &tcp_server2);806ASSERT_OK(r);807
808r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);809ASSERT_OK(r);810r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0);811ASSERT_OK(r);812
813r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,814(uv_stream_t*)&tcp_server, NULL);815ASSERT_OK(r);816r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1,817(uv_stream_t*)&tcp_server2, NULL);818ASSERT_OK(r);819
820r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);821ASSERT_OK(r);822
823MAKE_VALGRIND_HAPPY(uv_default_loop());824return 0;825}
826
827int ipc_helper_send_zero(void) {828int r;829uv_buf_t zero_buf;830
831zero_buf = uv_buf_init(0, 0);832
833r = uv_pipe_init(uv_default_loop(), &channel, 0);834ASSERT_OK(r);835
836uv_pipe_open(&channel, 0);837
838ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));839ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));840ASSERT_OK(uv_is_closing((uv_handle_t*) &channel));841
842r = uv_write(&write_req,843(uv_stream_t*)&channel,844&zero_buf,8451,846send_zero_write_cb);847
848ASSERT_OK(r);849
850r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);851ASSERT_OK(r);852
853ASSERT_EQ(1, send_zero_write);854
855MAKE_VALGRIND_HAPPY(uv_default_loop());856return 0;857}
858