X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Foserver%2Ftest%2Frun.c;h=b093a560c56fa273745134d4e360799328c57ec6;hb=a88d58b2667c6fbd20c7fea563eed0d92654ea39;hp=3a93be8974e9976d51900b902dabe27d325126c6;hpb=b3458dbe49ae218f183affcb239433d66839e2c9;p=ccan-lca-2011.git diff --git a/ccan/oserver/test/run.c b/ccan/oserver/test/run.c index 3a93be8..b093a56 100644 --- a/ccan/oserver/test/run.c +++ b/ccan/oserver/test/run.c @@ -1,39 +1,132 @@ -#include #include +#include #include #include #include +#include #include #include #include -#include -int main(void) +static void exit_quietly(struct tevent_context *ev, + struct tevent_fd *fde, uint16_t flags, void *unused) +{ + 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) { - int fd; - int status; - char buf[200]; + 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 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); + 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")); - fd = open("run-fd", O_RDWR|O_CREAT|O_TRUNC, 0600); - write(fd, "This is a test\n", sizeof("This is a test\n")); - lseek(fd, 0, SEEK_SET); + 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)); - if (fork() == 0) - oserver_serve(fd); + ok1(write_sall(sfd1, " 1\n")); + ok1(write_sall(sfd2, " 2\n")); - wait(&status); + ok1(input_is(sfd1, "Our answer is:\nQUESTION 1\n")); + ok1(input_is(sfd2, "Our answer is:\nQUESTION 2\n")); - ok1(WIFEXITED(status)); - ok1(WEXITSTATUS(status) == 0); + /* Sockets should be dead now. */ + ok1(read(sfd1, &c, 1) == 0); + ok1(read(sfd2, &c, 1) == 0); - lseek(fd, 0, SEEK_SET); - buf[read(fd, buf, sizeof(buf)-1)] = '\0'; + /* Shut down server. */ + write(exitfd[1], "", 1); - ok1(streq(buf, "This is a test\n" - "Louder, like this: 'THIS IS A TEST'\r\n")); + /* 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 */ return exit_status();