diff options
author | Thomas Habets <habets@google.com> | 2015-02-18 10:59:02 +0000 |
---|---|---|
committer | Thomas Habets <thomas@habets.se> | 2015-04-22 20:21:58 +0100 |
commit | 2a4eab7019e997eaf6a53bb124cb9cacdbccbe61 (patch) | |
tree | 8b7f9d21b623ca4ad43f3aa02f4ea50056b6b174 | |
parent | c7e5d01dcde34e844a87cb6c488e289c58005d78 (diff) | |
download | arping-2a4eab7019e997eaf6a53bb124cb9cacdbccbe61.tar.gz |
Add tests on output.
-rw-r--r-- | src/arping_test.c | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/src/arping_test.c b/src/arping_test.c index a09e80b..487b5a1 100644 --- a/src/arping_test.c +++ b/src/arping_test.c @@ -16,6 +16,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include<assert.h> +#include<errno.h> +#include<fcntl.h> #include<inttypes.h> #include<stdlib.h> @@ -29,6 +32,118 @@ static void* test_registry[1024]; #define MYTEST(a) static void a(int);__attribute__((constructor)) static void cons_##a() { test_registry[numtests++] = a;} START_TEST(a) +/** + * + */ +static void +xclose(int* fd) +{ + if (0 > close(*fd)) { + fprintf(stderr, "close(%d): %s", *fd, strerror(errno)); + *fd = -1; + } +} + +struct captured_output { + int saved_fd; // Old fd, will be dup2()ed back in place when done. + int fno; // Overridden fd (e.g. stdout or stderr). + int reader_fd; // Reader end of the pipe. + char* buffer; // Output buffer. + size_t bufsize; // Buffer size. + pthread_t thread; // Reader thread. +}; + +/** + * Helper function for stdout/stderr catching. + * + * This is the main() for the thread that reads from the fake stdout pipe + * and writes into the buffer. + * + */ +static void* +read_main(void* p) +{ + struct captured_output* out = p; + char *cur = out->buffer; + + while (1) { + ssize_t n; + n = out->bufsize - (cur - out->buffer); + assert(n > 0); + n = read(out->reader_fd, cur, n); + if (n > 0) { + cur += n; + } + if (n == 0) { + break; + } + } +} + +/** + * Helper function to capture stdout/stderr output. + * + * Args: + * fd: The fd to capture. + * Returns: + * A structure to be used as a handle. Only thing caller should do with + * this structure is call stop_capture(), read its .buffer member, and + * uncapture(). + */ +static struct captured_output* +capture(int fd) +{ + struct captured_output* out; + + out = calloc(1, sizeof(struct captured_output)); + fail_if(out == NULL); + + out->fno = fd; + out->saved_fd = dup(fd); + out->bufsize = 1024*100; + out->buffer = calloc(1, out->bufsize); + + fail_if(0 > out->saved_fd); + fail_if(out->buffer == NULL); + + // set up pipe + int fds[2]; + fail_if(0 > pipe(fds)); + fail_if(0 > dup2(fds[1], fd)); + out->reader_fd = fds[0]; + xclose(&fds[1]); + + fail_if(pthread_create(&out->thread, NULL, read_main, (void*)out)); + return out; +} + +/** + * Helper function to capture stdout/stderr output. + * + * Stop capture, so that .buffer becomes readable. + */ +static void +stop_capture(struct captured_output* out) +{ + fail_if(0 > dup2(out->saved_fd, out->fno)); + xclose(&out->saved_fd); + fail_if(pthread_join(out->thread, NULL)); + xclose(&out->reader_fd); +} + +/** + * Helper function to capture stdout/stderr output. + * + * Deallocate buffer. stop_capture() must be called before uncapture(). + */ +static void +uncapture(struct captured_output* out) +{ + free(out->buffer); + out->buffer = NULL; + free(out); +} + // Received uninteresting packet, should not record anything. MYTEST(pingip_uninteresting_packet) { @@ -37,7 +152,11 @@ MYTEST(pingip_uninteresting_packet) int prev_numrecvd = numrecvd; + struct captured_output* sout; + sout = capture(1); pingip_recv(NULL, &pkthdr, packet); + stop_capture(sout); + fail_unless(strlen(sout->buffer) == 0); fail_unless(prev_numrecvd == numrecvd); } END_TEST @@ -69,7 +188,23 @@ MYTEST(pingip_interesting_packet) dstip = htonl(0x12345678); + pkthdr.ts.tv_sec = time(NULL); + pkthdr.ts.tv_usec = 0; + pkthdr.len = 60; + pkthdr.caplen = 60; + + struct captured_output *sout; + + // First ping. + const char* correct0 = + "60 bytes from 77:88:99:aa:bb:cc (18.52.86.120): " + "index=0 time="; + sout = capture(1); pingip_recv(NULL, &pkthdr, packet); + stop_capture(sout); + fail_unless(!strncmp(sout->buffer, correct0, strlen(correct0))); + uncapture(sout); + fail_unless(numrecvd == prev_numrecvd + 1, "numrecvd not incremented"); @@ -84,7 +219,6 @@ arping_suite(void) int c; Suite* s = suite_create("Arping"); - /* Core test case */ //tcase_add_checked_fixture (tc_core, setup, teardown); TCase *tc_core = tcase_create("Receiving"); for (c = 0; c < numtests; c++) { |