Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <errno.h>
#include <string.h> /* memset */
#include <signal.h> /* signal */
static uv_tcp_t tcp_server;
static void connect_cb(uv_connect_t* req, int status);
static void write_cb(uv_write_t* req, int status);
static void close_cb(uv_handle_t* handle);
static void write(uv_stream_t *handle, long seq, size_t size) {
unsigned char *data;
uv_write_t* req;
uv_buf_t buf;
int r;
data = malloc(size);
ASSERT(data != NULL);
memset(data, 'x', size);
buf = uv_buf_init(data, size);
req = malloc(sizeof *req);
req->data = (void*)seq;
ASSERT(req != NULL);
r = uv_write(req, handle, &buf, 1, write_cb);
ASSERT(r == 0);
}
static void connect_cb(uv_connect_t* conn_req, int status) {
/* Small write will fit in the kernel write buffer */
write(conn_req->handle, 0, 1);
/* Large write will not fit in the kernel write buffer; it needs more ticks
* to finish, but will fail very fast because we close the server next */
write(conn_req->handle, 1, 10*1024*1024);
/* Close server */
uv_close((uv_handle_t*)&tcp_server, NULL);
}
static void write_cb(uv_write_t* req, int status) {
static int write_cb_called = 0;
/* callbacks should be called in the order they are created */
printf("callback nr %ld, (expected: %d)\n", (long)req->data, write_cb_called);
ASSERT((long)req->data == write_cb_called++);
/* the second one should fail */
if ((long)req->data) {
ASSERT(status == -1);
}
free(req);
}
static void connection_cb(uv_stream_t* server, int status) {
ASSERT(status == 0);
}
static void start_server(uv_loop_t* loop, uv_tcp_t* handle) {
int r;
r = uv_tcp_init(loop, handle);
ASSERT(r == 0);
r = uv_tcp_bind(handle, uv_ip4_addr("127.0.0.1", TEST_PORT));
ASSERT(r == 0);
r = uv_listen((uv_stream_t*)handle, 128, connection_cb);
ASSERT(r == 0);
uv_unref(loop);
}
/* Check that pending write requests have their callbacks
* invoked when the handle is closed.
*/
TEST_IMPL(tcp_write_callback_order) {
uv_loop_t* loop;
uv_tcp_t tcp_handle;
uv_connect_t connect_req;
int r;
/* Ignore SIGPIPE, which we'll probably see when closing the server. */
signal(SIGPIPE, SIG_IGN);
loop = uv_default_loop();
/* We can't use the echo server, it doesn't handle ECONNRESET. */
start_server(loop, &tcp_server);
r = uv_tcp_init(loop, &tcp_handle);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req,
&tcp_handle,
uv_ip4_addr("127.0.0.1", TEST_PORT),
connect_cb);
ASSERT(r == 0);
r = uv_run(loop);
ASSERT(r == 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.