X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Foserver%2Ftest%2Frun.c;h=b093a560c56fa273745134d4e360799328c57ec6;hb=a88d58b2667c6fbd20c7fea563eed0d92654ea39;hp=b8e9dc3042c67312aade84acc9a4a95abaabf1a3;hpb=a2a89814bd9b71612778cbb1fed3ae0d8cadc6b5;p=ccan-lca-2011.git diff --git a/ccan/oserver/test/run.c b/ccan/oserver/test/run.c index b8e9dc3..b093a56 100644 --- a/ccan/oserver/test/run.c +++ b/ccan/oserver/test/run.c @@ -1,54 +1,133 @@ -#include #include #include #include -#include #include #include +#include #include -#include #include #include -#include -static void exit_test(void) +static void exit_quietly(struct tevent_context *ev, + struct tevent_fd *fde, uint16_t flags, void *unused) { - failtest_exit(exit_status()); + talloc_free(ev); + exit(0); +} + +static void run_server(int readyfd, int exitfd) +{ + struct tevent_context *ev = tevent_context_init(NULL); + + if (oserver_setup(ev, OSERVER_PORT) == NULL) + exit(1); + + /* Tell parent we are ready to go. */ + write(readyfd, "", 1); + + tevent_add_fd(ev, ev, exitfd, TEVENT_FD_READ, exit_quietly, NULL); + while (tevent_loop_wait(ev) == 0); +} + +static bool write_sall(int fd, const char *str) +{ + while (str[0]) { + ssize_t len = write(fd, str, strlen(str)); + if (len < 0) + return false; + str += len; + } + return true; +} + +static bool input_is(int fd, const char *str) +{ + while (str[0]) { + char buffer[1000]; + ssize_t len = read(fd, buffer, strlen(str)); + if (len < 0) + return false; + if (strncmp(str, buffer, len) != 0) + return false; + str += len; + } + return true; +} + +static bool no_input(int fd) +{ + fd_set set; + struct timeval t = { 0, 0 }; + + FD_ZERO(&set); + FD_SET(fd, &set); + return (select(fd+1, &set, NULL, NULL, &t) == 0); } int main(int argc, char *argv[]) { - int fd; - char buf[200]; - const char *input; + int readyfd[2], exitfd[2]; + union { + struct sockaddr addr; + struct sockaddr_in in; + } u; + int sfd1, sfd2; + char c; /* This is how many tests you plan to run */ - plan_tests(3 * 6); - failtest_init(argc, argv); - tap_fail_callback = exit_test; - - foreach_ptr(input, - "This is a test\n", - "This is a test\r", - "This is a test\r\n", - "This is a test\nWith extra", - "This is a test\rWith extra", - "This is a test\r\nWith extra") { - fd = open("run-fd", O_RDWR|O_CREAT|O_TRUNC, 0600); - - write(fd, input, strlen(input)); - lseek(fd, 0, SEEK_SET); - - ok1(oserver_serve(fd)); - - lseek(fd, 0, SEEK_SET); - buf[read(fd, buf, sizeof(buf)-1)] = '\0'; - - ok1(strncmp(buf, input, strlen("This is a test")) == 0); - ok1(streq(buf + strlen("This is a test") + 1, - "Louder, like this: 'THIS IS A TEST'\r\n")); + plan_tests(15); + + pipe(readyfd); + pipe(exitfd); + if (fork() == 0) { + close(exitfd[1]); + close(readyfd[0]); + run_server(readyfd[1], exitfd[0]); + err(1, "Event loop failed"); } + close(exitfd[0]); + close(readyfd[1]); + + sfd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + sfd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + u.in.sin_family = AF_INET; + u.in.sin_port = htons(OSERVER_PORT); + u.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + /* Wait until child is ready... */ + if (read(readyfd[0], &c, 1) != 1) + errx(1, "Child problems"); + + /* Go! */ + ok1(connect(sfd1, &u.addr, sizeof(u.in)) == 0); + ok1(connect(sfd2, &u.addr, sizeof(u.in)) == 0); + + ok1(input_is(sfd1, "Welcome. Please ask your question.\n")); + ok1(input_is(sfd2, "Welcome. Please ask your question.\n")); + + ok1(write_sall(sfd1, "question")); + ok1(write_sall(sfd2, "question")); + /* It shouldn't say anything until we've finished! */ + ok1(no_input(sfd1)); + ok1(no_input(sfd2)); + + ok1(write_sall(sfd1, " 1\n")); + ok1(write_sall(sfd2, " 2\n")); + + ok1(input_is(sfd1, "Our answer is:\nQUESTION 1\n")); + ok1(input_is(sfd2, "Our answer is:\nQUESTION 2\n")); + + /* Sockets should be dead now. */ + ok1(read(sfd1, &c, 1) == 0); + ok1(read(sfd2, &c, 1) == 0); + + /* Shut down server. */ + write(exitfd[1], "", 1); + + /* This will close once it's shut down, and return. */ + ok1(read(readyfd[0], &c, 1) == 0); /* This exits depending on whether all tests passed */ - failtest_exit(exit_status()); + return exit_status(); }