diff --git a/Makefile b/Makefile index 66c47769..27b045ee 100644 --- a/Makefile +++ b/Makefile @@ -21,9 +21,9 @@ all: oio.a test/run-tests test/run-benchmarks CFLAGS=-ansi -g -LINKFLAGS=-g -lm +LINKFLAGS=-lm TESTS=test/echo-server.c test/test-*.c -BENCHMARKS=test/benchmark-*.c +BENCHMARKS=test/echo-server.c test/benchmark-*.c test/run-tests: test/*.h test/run-tests.c test/runner.c test/runner-unix.c $(TESTS) oio.a $(CC) $(CFLAGS) $(LINKFLAGS) -o test/run-tests test/run-tests.c \ diff --git a/test/benchmark-dummy.c b/test/benchmark-dummy.c index f4a6b715..75f3c600 100644 --- a/test/benchmark-dummy.c +++ b/test/benchmark-dummy.c @@ -25,4 +25,4 @@ BENCHMARK_IMPL(dummy) { LOG("23487 foos/bar\n"); return 0; -} \ No newline at end of file +} diff --git a/test/benchmark-list.h b/test/benchmark-list.h index 82a08f77..1f27ccec 100644 --- a/test/benchmark-list.h +++ b/test/benchmark-list.h @@ -19,8 +19,12 @@ * IN THE SOFTWARE. */ +BENCHMARK_DECLARE (echo_server) +BENCHMARK_DECLARE (ping_pongs) BENCHMARK_DECLARE (dummy) TASK_LIST_START BENCHMARK_ENTRY (dummy) -TASK_LIST_END \ No newline at end of file + BENCHMARK_ENTRY (ping_pongs) + BENCHMARK_HELPER (ping_pongs, echo_server) +TASK_LIST_END diff --git a/test/benchmark-ping-pongs.c b/test/benchmark-ping-pongs.c new file mode 100644 index 00000000..14c442fe --- /dev/null +++ b/test/benchmark-ping-pongs.c @@ -0,0 +1,166 @@ +/* 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 "../oio.h" +#include "task.h" + +#include +#include + +static int completed_pingers = 0; +static int64_t start_time; + +/* Run the benchmark for this many ms */ +#define TIME 1000 + +/* 64 bytes is enough for a pinger */ +#define BUFSIZE 1024 + +static char PING[] = "PING\n"; + + +typedef struct { + int pongs; + int state; + oio_handle handle; + oio_req connect_req; + oio_req read_req; + oio_buf buf; + char read_buffer[BUFSIZE]; +} pinger_t; + +void pinger_try_read(pinger_t* pinger); + + +void pinger_on_close(oio_handle* handle, oio_err err) { + pinger_t* pinger = (pinger_t*)handle->data; + + printf("%d pings\n", pinger->pongs); + + ASSERT(!err); + + free(pinger); + + completed_pingers++; +} + + +void pinger_after_write(oio_req *req) { + free(req); +} + + +static void pinger_write_ping(pinger_t* pinger) { + oio_req *req; + + req = (oio_req*)malloc(sizeof(*req)); + oio_req_init(req, &pinger->handle, pinger_after_write); + + if (oio_write2(req, (char*)&PING)) { + FATAL("oio_write2 failed"); + } +} + + +static void pinger_after_read(oio_req* req, size_t nread) { + unsigned int i; + pinger_t* pinger; + + pinger = (pinger_t*)req->handle->data; + + if (nread == 0) { + puts("got EOF"); + oio_close(&pinger->handle); + return; + } + + /* Now we count the pings */ + for (i = 0; i < nread; i++) { + ASSERT(pinger->buf.base[i] == PING[pinger->state]); + pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); + if (pinger->state == 0) { + pinger->pongs++; + if (oio_now() - start_time > TIME) { + oio_close(&pinger->handle); + return; + } else { + pinger_write_ping(pinger); + } + } + } + + pinger_try_read(pinger); +} + + +void pinger_try_read(pinger_t* pinger) { + oio_req_init(&pinger->read_req, &pinger->handle, pinger_after_read); + oio_read(&pinger->read_req, &pinger->buf, 1); +} + + +void pinger_on_connect(oio_req *req, oio_err err) { + pinger_t *pinger = (pinger_t*)req->handle->data; + + ASSERT(!err); + + pinger_try_read(pinger); + pinger_write_ping(pinger); +} + + +void pinger_new() { + int r; + struct sockaddr_in client_addr = oio_ip4_addr("0.0.0.0", 0); + struct sockaddr_in server_addr = oio_ip4_addr("127.0.0.1", TEST_PORT); + pinger_t *pinger; + + pinger = (pinger_t*)malloc(sizeof(*pinger)); + pinger->state = 0; + pinger->pongs = 0; + pinger->buf.len = BUFSIZE; + pinger->buf.base = (char*)&pinger->read_buffer; + + /* Try to connec to the server and do NUM_PINGS ping-pongs. */ + r = oio_tcp_init(&pinger->handle, pinger_on_close, (void*)pinger); + ASSERT(!r); + + /* We are never doing multiple reads/connects at a time anyway. */ + /* so these handles can be pre-initialized. */ + oio_req_init(&pinger->connect_req, &pinger->handle, pinger_on_connect); + + oio_bind(&pinger->handle, (struct sockaddr*)&client_addr); + r = oio_connect(&pinger->connect_req, (struct sockaddr*)&server_addr); + ASSERT(!r); +} + + +BENCHMARK_IMPL(ping_pongs) { + oio_init(); + start_time = oio_now(); + + pinger_new(); + oio_run(); + + ASSERT(completed_pingers == 1); + + return 0; +} diff --git a/test/echo-server.c b/test/echo-server.c index 61aa7ab5..7a253b73 100644 --- a/test/echo-server.c +++ b/test/echo-server.c @@ -144,3 +144,14 @@ TEST_IMPL(echo_server) { oio_run(); return 0; } + +/* FIXME: Ugly. Isn't there a better way to do this? */ +BENCHMARK_IMPL(echo_server) { + oio_init(); + if (echo_start(TEST_PORT)) + return 1; + + fprintf(stderr, "Listening!\n"); + oio_run(); + return 0; +}