More extensive test-callback-stack. Fails on windows now.

This commit is contained in:
Bert Belder 2011-05-04 17:10:33 +02:00
parent b87f07dee4
commit 9d9c242a24
3 changed files with 130 additions and 15 deletions

View File

@ -28,45 +28,159 @@
#include "task.h" #include "task.h"
const char MESSAGE[] = "Failure is for the weak. Everyone dies alone.";
oio_handle client;
oio_req connect_req, write_req, timeout_req, shutdown_req;
int nested = 0; int nested = 0;
int close_cb_called = 0; int close_cb_called = 0;
int connect_cb_called = 0;
int write_cb_called = 0;
int timeout_cb_called = 0;
int bytes_received = 0;
int shutdown_cb_called = 0;
void close_cb(oio_handle* handle, int status) { void close_cb(oio_handle* handle, int status) {
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(nested == 0 && "oio_close_cb must be called from a fresh stack"); ASSERT(nested == 0 && "close_cb must be called from a fresh stack");
close_cb_called++; close_cb_called++;
} }
void shutdown_cb(oio_req* req, int status) {
ASSERT(status == 0);
ASSERT(nested == 0 && "shutdown_cb must be called from a fresh stack");
shutdown_cb_called++;
}
void read_cb(oio_handle* handle, int nread, oio_buf buf) {
ASSERT(nested == 0 && "read_cb must be called from a fresh stack");
if (nread == -1) {
ASSERT(oio_last_error().code == OIO_EOF);
nested++;
if (oio_close(handle)) {
FATAL("oio_close failed");
}
nested--;
return;
}
bytes_received += nread;
free(buf.base);
/* We call shutdown here because when bytes_received == sizeof MESSAGE */
/* there will be no more data sent nor received, so here it would be */
/* possible for a backend to to call shutdown_cb immediately and *not* */
/* from a fresh stack. */
if (bytes_received == sizeof MESSAGE) {
nested++;
oio_req_init(&shutdown_req, handle, shutdown_cb);
if (oio_shutdown(&shutdown_req)) {
FATAL("oio_shutdown failed");
}
nested--;
}
}
void timeout_cb(oio_req* req, int64_t skew, int status) {
ASSERT(status == 0);
ASSERT(nested == 0 && "timeout_cb must be called from a fresh stack");
nested++;
if (oio_read_start(&client, read_cb)) {
FATAL("oio_read_start failed");
}
nested--;
timeout_cb_called++;
}
void write_cb(oio_req* req, int status) {
ASSERT(status == 0);
ASSERT(nested == 0 && "write_cb must be called from a fresh stack");
/* After the data has been sent, we're going to wait for a while, then */
/* start reading. This makes us certain that the message has been echoed */
/* back to our receive buffer when we start reading. This maximizes the */
/* tempation for the backend to use dirty stack for calling read_cb. */
nested++;
oio_req_init(&timeout_req, NULL, timeout_cb);
if (oio_timeout(&timeout_req, 500)) {
FATAL("oio_timeout failed");
}
nested--;
write_cb_called++;
}
void connect_cb(oio_req* req, int status) {
oio_buf buf;
ASSERT(status == 0);
ASSERT(nested == 0 && "connect_cb must be called from a fresh stack");
nested++;
buf.base = (char*) &MESSAGE;
buf.len = sizeof MESSAGE;
oio_req_init(&write_req, req->handle, write_cb);
if (oio_write(&write_req, &buf, 1)) {
FATAL("oio_write failed");
}
nested--;
connect_cb_called++;
}
static oio_buf alloc_cb(oio_handle* handle, size_t size) { static oio_buf alloc_cb(oio_handle* handle, size_t size) {
oio_buf buf = {0, 0}; oio_buf buf;
FATAL("alloc should not be called"); buf.len = size;
buf.base = (char*) malloc(size);
ASSERT(buf.base);
return buf; return buf;
} }
TEST_IMPL(close_cb_stack) { TEST_IMPL(callback_stack) {
oio_handle handle; struct sockaddr_in addr = oio_ip4_addr("127.0.0.1", TEST_PORT);
oio_init(alloc_cb); oio_init(alloc_cb);
if (oio_tcp_init(&handle, &close_cb, NULL)) { if (oio_tcp_init(&client, &close_cb, NULL)) {
FATAL("oio_tcp_init failed"); FATAL("oio_tcp_init failed");
} }
nested++; nested++;
oio_req_init(&connect_req, &client, connect_cb);
if (oio_close(&handle)) { if (oio_connect(&connect_req, (struct sockaddr*) &addr)) {
FATAL("oio_close failed"); FATAL("oio_connect failed");
} }
nested--; nested--;
oio_run(); oio_run();
ASSERT(nested == 0); ASSERT(nested == 0);
ASSERT(close_cb_called == 1 && "oio_close_cb must be called exactly once"); ASSERT(connect_cb_called == 1 && "connect_cb must be called exactly once");
ASSERT(write_cb_called == 1 && "write_cb must be called exactly once");
ASSERT(timeout_cb_called == 1 && "timeout_cb must be called exactly once");
ASSERT(bytes_received == sizeof MESSAGE);
ASSERT(shutdown_cb_called == 1 && "shutdown_cb must be called exactly once");
ASSERT(close_cb_called == 1 && "close_cb must be called exactly once");
return 0; return 0;
} }

View File

@ -28,7 +28,7 @@ TEST_DECLARE (bind_error_addrnotavail_2)
TEST_DECLARE (bind_error_fault) TEST_DECLARE (bind_error_fault)
TEST_DECLARE (bind_error_inval) TEST_DECLARE (bind_error_inval)
TEST_DECLARE (connection_fail) TEST_DECLARE (connection_fail)
TEST_DECLARE (close_cb_stack) TEST_DECLARE (callback_stack)
TEST_DECLARE (timeout) TEST_DECLARE (timeout)
TEST_DECLARE (fail_always) TEST_DECLARE (fail_always)
TEST_DECLARE (pass_always) TEST_DECLARE (pass_always)
@ -55,7 +55,8 @@ TASK_LIST_START
TEST_ENTRY (connection_fail) TEST_ENTRY (connection_fail)
TEST_ENTRY (close_cb_stack) TEST_ENTRY (callback_stack)
TEST_HELPER (callback_stack, echo_server)
TEST_ENTRY (timeout) TEST_ENTRY (timeout)