Clean up test error handling
Define FATAL and ASSERT macros. Dont use libc's assert as it might get optimized away.
This commit is contained in:
parent
9f746952cf
commit
93dd5f74c7
@ -29,7 +29,6 @@ void after_write(oio_req* req) {
|
|||||||
|
|
||||||
void after_read(oio_req* req, size_t nread) {
|
void after_read(oio_req* req, size_t nread) {
|
||||||
peer_t* peer;
|
peer_t* peer;
|
||||||
int r;
|
|
||||||
|
|
||||||
if (nread == 0) {
|
if (nread == 0) {
|
||||||
oio_close(req->handle);
|
oio_close(req->handle);
|
||||||
@ -38,20 +37,18 @@ void after_read(oio_req* req, size_t nread) {
|
|||||||
peer->buf.len = nread;
|
peer->buf.len = nread;
|
||||||
oio_req_init(&peer->req, &peer->handle, after_write);
|
oio_req_init(&peer->req, &peer->handle, after_write);
|
||||||
peer->req.data = peer;
|
peer->req.data = peer;
|
||||||
r = oio_write(&peer->req, &peer->buf, 1);
|
if (oio_write(&peer->req, &peer->buf, 1))
|
||||||
assert(!r);
|
FATAL(oio_write failed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void try_read(peer_t* peer) {
|
void try_read(peer_t* peer) {
|
||||||
int r;
|
|
||||||
|
|
||||||
peer->buf.len = BUFSIZE;
|
peer->buf.len = BUFSIZE;
|
||||||
oio_req_init(&peer->req, &peer->handle, after_read);
|
oio_req_init(&peer->req, &peer->handle, after_read);
|
||||||
peer->req.data = peer;
|
peer->req.data = peer;
|
||||||
r = oio_read(&peer->req, &peer->buf, 1);
|
if (oio_read(&peer->req, &peer->buf, 1))
|
||||||
assert(!r);
|
FATAL(oio_read failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -64,10 +61,9 @@ void on_close(oio_handle* peer, oio_err err) {
|
|||||||
|
|
||||||
void on_accept(oio_handle* server) {
|
void on_accept(oio_handle* server) {
|
||||||
peer_t* p = (peer_t*)malloc(sizeof(peer_t));
|
peer_t* p = (peer_t*)malloc(sizeof(peer_t));
|
||||||
int r;
|
|
||||||
|
|
||||||
r = oio_tcp_handle_accept(server, &p->handle, on_close, (void*)p);
|
if (oio_tcp_handle_accept(server, &p->handle, on_close, (void*)p))
|
||||||
assert(!r);
|
FATAL(oio_tcp_handle_accept failed)
|
||||||
|
|
||||||
p->buf.base = (char*)&p->read_buffer;
|
p->buf.base = (char*)&p->read_buffer;
|
||||||
|
|
||||||
@ -76,11 +72,8 @@ void on_accept(oio_handle* server) {
|
|||||||
|
|
||||||
|
|
||||||
void on_server_close(oio_handle* handle, oio_err err) {
|
void on_server_close(oio_handle* handle, oio_err err) {
|
||||||
assert(handle == &server);
|
ASSERT(handle == &server);
|
||||||
|
ASSERT(!err)
|
||||||
if (err) {
|
|
||||||
fprintf(stdout, "Socket error\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,30 +6,31 @@ int nested = 0;
|
|||||||
int close_cb_called = 0;
|
int close_cb_called = 0;
|
||||||
|
|
||||||
|
|
||||||
void close_cb(oio_handle *handle, oio_err e) {
|
void close_cb(oio_handle *handle, oio_err err) {
|
||||||
assert("oio_close error" && e == 0);
|
ASSERT(!err)
|
||||||
assert("oio_close_cb not called from a fresh stack" && nested == 0);
|
ASSERT(nested == 0 && "oio_close_cb must be called from a fresh stack")
|
||||||
close_cb_called++;
|
close_cb_called++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(close_cb_stack) {
|
TEST_IMPL(close_cb_stack) {
|
||||||
oio_handle handle;
|
oio_handle handle;
|
||||||
int r;
|
|
||||||
|
|
||||||
oio_init();
|
oio_init();
|
||||||
|
|
||||||
r = oio_tcp_handle_init(&handle, &close_cb, NULL);
|
if (oio_tcp_handle_init(&handle, &close_cb, NULL))
|
||||||
assert(!r);
|
FATAL(oio_tcp_handle_init failed)
|
||||||
|
|
||||||
nested++;
|
nested++;
|
||||||
r = oio_close(&handle);
|
|
||||||
assert(!r);
|
if (oio_close(&handle))
|
||||||
|
FATAL(oio_close failed)
|
||||||
|
|
||||||
nested--;
|
nested--;
|
||||||
|
|
||||||
oio_run();
|
oio_run();
|
||||||
|
|
||||||
assert("oio_close_cb not called exactly once" && close_cb_called);
|
ASSERT(close_cb_called && "oio_close_cb must be called exactly once")
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2,6 +2,5 @@
|
|||||||
|
|
||||||
TEST_IMPL(fail_always) {
|
TEST_IMPL(fail_always) {
|
||||||
/* This test always fails. It is used to test the test runner. */
|
/* This test always fails. It is used to test the test runner. */
|
||||||
assert("Yes, it always fails" && 0);
|
FATAL("Yes, it always fails")
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
#include "../oio.h"
|
#include "../oio.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@ -30,8 +29,8 @@ void pinger_try_read(pinger_t* pinger);
|
|||||||
void pinger_on_close(oio_handle* handle, oio_err err) {
|
void pinger_on_close(oio_handle* handle, oio_err err) {
|
||||||
pinger_t* pinger = (pinger_t*)handle->data;
|
pinger_t* pinger = (pinger_t*)handle->data;
|
||||||
|
|
||||||
assert(!err);
|
ASSERT(!err)
|
||||||
assert(NUM_PINGS == pinger->pongs);
|
ASSERT(NUM_PINGS == pinger->pongs)
|
||||||
|
|
||||||
free(pinger);
|
free(pinger);
|
||||||
|
|
||||||
@ -46,12 +45,12 @@ void pinger_after_write(oio_req *req) {
|
|||||||
|
|
||||||
void pinger_write_ping(pinger_t* pinger) {
|
void pinger_write_ping(pinger_t* pinger) {
|
||||||
oio_req *req;
|
oio_req *req;
|
||||||
int r;
|
|
||||||
|
|
||||||
req = (oio_req*)malloc(sizeof(*req));
|
req = (oio_req*)malloc(sizeof(*req));
|
||||||
oio_req_init(req, &pinger->handle, pinger_after_write);
|
oio_req_init(req, &pinger->handle, pinger_after_write);
|
||||||
r = oio_write2(req, (char*)&PING);
|
|
||||||
assert(!r);
|
if (oio_write2(req, (char*)&PING))
|
||||||
|
FATAL(oio_write2 failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
void pinger_after_read(oio_req* req, size_t nread) {
|
void pinger_after_read(oio_req* req, size_t nread) {
|
||||||
@ -67,7 +66,7 @@ void pinger_after_read(oio_req* req, size_t nread) {
|
|||||||
|
|
||||||
/* Now we count the pings */
|
/* Now we count the pings */
|
||||||
for (i = 0; i < nread; i++) {
|
for (i = 0; i < nread; i++) {
|
||||||
assert(pinger->buf.base[i] == PING[pinger->state]);
|
ASSERT(pinger->buf.base[i] == PING[pinger->state])
|
||||||
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
|
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
|
||||||
if (pinger->state == 0) {
|
if (pinger->state == 0) {
|
||||||
pinger->pongs++;
|
pinger->pongs++;
|
||||||
@ -92,9 +91,7 @@ void pinger_try_read(pinger_t* pinger) {
|
|||||||
void pinger_on_connect(oio_req *req, oio_err err) {
|
void pinger_on_connect(oio_req *req, oio_err err) {
|
||||||
pinger_t *pinger = (pinger_t*)req->handle->data;
|
pinger_t *pinger = (pinger_t*)req->handle->data;
|
||||||
|
|
||||||
if (err) {
|
ASSERT(!err)
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pinger_try_read(pinger);
|
pinger_try_read(pinger);
|
||||||
pinger_write_ping(pinger);
|
pinger_write_ping(pinger);
|
||||||
@ -136,7 +133,7 @@ TEST_IMPL(ping_pong) {
|
|||||||
|
|
||||||
oio_run();
|
oio_run();
|
||||||
|
|
||||||
assert(completed_pingers == 1);
|
ASSERT(completed_pingers == 1)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
|
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ int process_wait(process_info_t *vec, int n, int timeout) {
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
assert(n <= MAXIMUM_WAIT_OBJECTS);
|
ASSERT(n <= MAXIMUM_WAIT_OBJECTS)
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
handles[i] = vec[i].process;
|
handles[i] = vec[i].process;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
|
#include "test.h"
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -15,13 +15,6 @@
|
|||||||
/* The time in milliseconds after which a single test times out, */
|
/* The time in milliseconds after which a single test times out, */
|
||||||
#define TEST_TIMEOUT 20000
|
#define TEST_TIMEOUT 20000
|
||||||
|
|
||||||
/* Die with fatal error. */
|
|
||||||
#define FATAL(msg) assert(msg && 0);
|
|
||||||
|
|
||||||
/* Log to stderr. */
|
|
||||||
#define LOG(...) fprintf(stderr, "%s", __VA_ARGS__)
|
|
||||||
#define LOGF(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Runs an individual test; returns 1 if the test succeeded, 0 if it failed.
|
* Runs an individual test; returns 1 if the test succeeded, 0 if it failed.
|
||||||
@ -62,7 +55,7 @@ int run_test(test_entry_t *test) {
|
|||||||
/* Wait for the main process to terminate. */
|
/* Wait for the main process to terminate. */
|
||||||
result = process_wait(main_process, 1, TEST_TIMEOUT);
|
result = process_wait(main_process, 1, TEST_TIMEOUT);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
FATAL("process_wait failed\n");
|
FATAL(process_wait failed)
|
||||||
} else if (result == -2) {
|
} else if (result == -2) {
|
||||||
snprintf((char*)&errmsg, sizeof(errmsg), "timeout.");
|
snprintf((char*)&errmsg, sizeof(errmsg), "timeout.");
|
||||||
goto finalize;
|
goto finalize;
|
||||||
@ -86,7 +79,7 @@ finalize:
|
|||||||
|
|
||||||
/* Wait until all processes have really terminated. */
|
/* Wait until all processes have really terminated. */
|
||||||
if (process_wait((process_info_t*)&processes, process_count, -1) < 0)
|
if (process_wait((process_info_t*)&processes, process_count, -1) < 0)
|
||||||
FATAL("process_wait failed\n");
|
FATAL(process_wait failed)
|
||||||
|
|
||||||
/* Show error and output from processes if the test failed. */
|
/* Show error and output from processes if the test failed. */
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#ifndef TEST_RUNNER_H_
|
#ifndef TEST_RUNNER_H_
|
||||||
#define TEST_RUNNER_H_
|
#define TEST_RUNNER_H_
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Struct to store both tests and to define helper processes for tests.
|
* Struct to store both tests and to define helper processes for tests.
|
||||||
*/
|
*/
|
||||||
|
|||||||
43
test/test.h
43
test/test.h
@ -1,13 +1,46 @@
|
|||||||
#ifndef TEST_H_
|
#ifndef TEST_H_
|
||||||
#define TEST_H_
|
#define TEST_H_
|
||||||
|
|
||||||
#include <assert.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define TEST_IMPL(name) \
|
|
||||||
int run_##name()
|
|
||||||
|
|
||||||
#define TEST_PORT 8123
|
#define TEST_PORT 8123
|
||||||
#define TEST_PORT_2 8124
|
#define TEST_PORT_2 8124
|
||||||
|
|
||||||
|
|
||||||
|
/* Log to stderr. */
|
||||||
|
#define LOG(...) fprintf(stderr, "%s", __VA_ARGS__)
|
||||||
|
#define LOGF(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
|
||||||
|
/* Die with fatal error. */
|
||||||
|
#define FATAL(msg) \
|
||||||
|
do { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"Fatal error in %s on line %d: %s\n", \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#msg); \
|
||||||
|
abort(); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have our own assert, so we are sure it does not get optimized away in
|
||||||
|
* a release build.
|
||||||
|
*/
|
||||||
|
#define ASSERT(expr) \
|
||||||
|
if (!(expr)) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"Assertion failed in %s on line %d: %s\n", \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#expr); \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Just sugar for wrapping the main() for a test. */
|
||||||
|
#define TEST_IMPL(name) \
|
||||||
|
int run_##name()
|
||||||
|
|
||||||
#endif /* TEST_H_ */
|
#endif /* TEST_H_ */
|
||||||
Loading…
Reference in New Issue
Block a user