summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <habets@google.com>2015-02-18 10:59:02 +0000
committerThomas Habets <thomas@habets.se>2015-04-22 20:21:58 +0100
commit2a4eab7019e997eaf6a53bb124cb9cacdbccbe61 (patch)
tree8b7f9d21b623ca4ad43f3aa02f4ea50056b6b174
parentc7e5d01dcde34e844a87cb6c488e289c58005d78 (diff)
downloadarping-2a4eab7019e997eaf6a53bb124cb9cacdbccbe61.tar.gz
Add tests on output.
-rw-r--r--src/arping_test.c136
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++) {