diff --git a/src/tests/.params b/src/tests/.params new file mode 100644 index 0000000..cd43cf6 --- /dev/null +++ b/src/tests/.params @@ -0,0 +1 @@ +tests c tests liblwevent diff --git a/src/tests/build.default b/src/tests/build.default new file mode 100644 index 0000000..1f0ae49 --- /dev/null +++ b/src/tests/build.default @@ -0,0 +1,3 @@ +source src/tests/build.tests +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: syntax=sh:expandtab:ts=4:sw=4 diff --git a/src/tests/build.tests b/src/tests/build.tests new file mode 100644 index 0000000..c868ad9 --- /dev/null +++ b/src/tests/build.tests @@ -0,0 +1,43 @@ +# These are external variables, and shouldn't clash with anything else +# tests_BUILT +# + +build_target liblwevent || return 1 + +if [ -z ${tests_BUILT} ] +then + LIBS="${liblwevent} ${liblwevent_DEP_CFLAGS} ${liblwevent_DEP_LIBS} " + EXTRAS="-D_GNU_SOURCE -std=c99" + + echo "Building test programs..." + do_cmd mkdir -p obj/tests || return 1 + + for SRC in src/tests/*.c + do + TEST="obj/tests/$(basename ${SRC} | sed -e 's,.c$,,')" + MODIFIED=0 + for file in ${LIBS} ${SRC} src/tests/build.tests + do + if [ ${file} -nt ${TEST} ] + then + MODIFIED=1 + break + fi + done + + if [ ${MODIFIED} -ne 0 ] + then + do_cmd ${CC} -Iobj ${CFLAGS} -o ${TEST} ${SRC} ${LIBS} ${EXTRAS} || return 1 + print_success "Built ${TEST}" + else + print_success "${TEST} is up to date" + fi + done + + print_success "All tests built" + + tests_BUILT=1 +fi + +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: syntax=sh:expandtab:ts=4:sw=4 diff --git a/src/tests/echoserver.c b/src/tests/echoserver.c new file mode 100644 index 0000000..3eb49cd --- /dev/null +++ b/src/tests/echoserver.c @@ -0,0 +1,185 @@ +/* liblwevent/src/tests/echoserver.c + * + * (c)2007, Laurence Withers, . + * Released under the GNU GPLv3. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#include "lwevent.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +char buf[4096]; + + + +void client_callback(struct lwevent* ev, int revents) +{ + ssize_t amt; + char* wr, * end; + int fd; + + if(revents & ~(EPOLLIN | EPOLLHUP | EPOLLRDHUP)) { + fprintf(stderr, "Unexpected flags in client_callback(): 0x%X.\n", revents); + lwevent_loop_exit = 1; + } + + if(revents & (EPOLLHUP | EPOLLRDHUP)) { + fputs("Client closed.\n", stdout); + lwevent_free_and_close(ev); + return; + } + + fd = lwevent_get_fd(ev); + + while(1) { + amt = TEMP_FAILURE_RETRY( read(fd, buf, sizeof(buf)) ); + if(amt == -1) { + if(errno != EAGAIN) { + perror("read"); + lwevent_free_and_close(ev); + } + return; + } + if(amt == 0) { + fputs("Client closed (EOF).\n", stdout); + lwevent_free_and_close(ev); + return; + } + + wr = buf; + end = buf + amt; + + while(wr != end) { + amt = TEMP_FAILURE_RETRY( write(fd, wr, end - wr) ); + if(amt == -1) { + perror("write"); + lwevent_free_and_close(ev); + return; + } + wr += amt; + } + } +} + + + +void server_callback(struct lwevent* ev, int revents) +{ + int ret; + + if(revents & ~EPOLLIN) { + fprintf(stderr, "Unexpected flags in server_callback(): 0x%X.\n", revents); + lwevent_loop_exit = 1; + } + + while(1) { + /* accept a possible client connection */ + ret = TEMP_FAILURE_RETRY( accept(lwevent_get_fd(ev), 0, 0) ); + if(ret == -1) { + if(errno == EAGAIN) return; + + perror("accept"); + lwevent_loop_exit = 1; + } + + /* set up a new client */ + if(lwevent_nonblock(ret)) { + perror("lwevent_nonblock"); + close(ret); + continue; + } + if(!lwevent_new(ret, EPOLLIN | EPOLLRDHUP | EPOLLET, client_callback)) { + perror("lwevent_new"); + close(ret); + } + fputs("New client.\n", stdout); + } +} + + + +int main(int argc, char* argv[]) +{ + int ret = 0, fd; + struct addrinfo* saddr; + + /* parse commandline arguments */ + if(argc == 2 && !strcmp(argv[1], "--print-summary")) { + fputs("TCP echo server.\n", stdout); + return 0; + } + + if(argc != 3) { + fputs("Expecting server name (or IP address) and port number.\n", stderr); + return 1; + } + + /* initialise liblwevent */ + if(lwevent_init()) { + perror("lwevent_init"); + return 1; + } + +#if 0 + if(!lwevent_signalfd_default()) { + perror("lwevent_signalfd_default"); + return 1; + } +#endif + + /* get hostname and socket, and bind it */ + ret = getaddrinfo(argv[1], argv[2], 0, &saddr); + if(ret) { + fputs("getaddrinfo: ", stderr); + fputs(gai_strerror(ret), stderr); + putc('\n', stderr); + return 1; + } + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(fd == -1) { + perror("socket"); + return 1; + } + + if(lwevent_nonblock(fd)) { + perror("lwevent_nonblock"); + return 1; + } + + if(bind(fd, saddr->ai_addr, saddr->ai_addrlen)) { + perror("bind"); + return 1; + } + + freeaddrinfo(saddr); + + if(listen(fd, 16)) { + perror("listen"); + return 1; + } + + /* set up server event */ + if(!lwevent_new(fd, EPOLLIN | EPOLLET, server_callback)) { + perror("lwevent_new"); + return 1; + } + + /* main event loop */ + ret = lwevent_loop(); + if(ret) perror("lwevent_loop"); + return ret; +} + +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/tests/template b/src/tests/template new file mode 100644 index 0000000..fc222e3 --- /dev/null +++ b/src/tests/template @@ -0,0 +1,36 @@ +/* liblwevent/src/tests/???.c + * + * (c)2007, Laurence Withers, . + * Released under the GNU GPLv3. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#include "lwevent.h" + +#include +#include + + + +int main(int argc, char* argv[]) +{ + int ret = 0; + + if(argc == 2 && !strcmp(argv[1], "--print-summary")) { + printf("One line summary.\n"); + return 0; + } + + if(argc == 1) { + /* empty argument list */ + } + + /* TODO */ + + return ret; +} + +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/