From 0172e7906dbadbbc8898f1f0c3fd61616ac12e47 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 1 May 2017 17:44:45 -0700 Subject: [PATCH] improved unit test coverage --- README.md | 14 +- test/unit/comprehensive.cpp | 564 ------------------------- test/unit/unit.cpp | 807 ++++++++++++++++++++++++++++++++++++ 3 files changed, 817 insertions(+), 568 deletions(-) delete mode 100644 test/unit/comprehensive.cpp create mode 100644 test/unit/unit.cpp diff --git a/README.md b/README.md index 1c40736..bc4a948 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,19 @@ Bindings also exist for [many popular languages](). ### Tests - `make tests`: Will output to `build/tests/` -Then run the comprehensive test suite with whatever configuration you need. For instance: +Then run the unit test suite with whatever configuration you need. For instance: -To run a single-test IPv4 server on port 8787: +To run a single-test IPv4 client/server test: - - Host 1: `./build/test/comprehensive c7cd7c9e1b0f52a2 simple 4 server 8787` - - Host 2: `./build/test/comprehensive c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787` + - Host 1: `./build/test/unit zt1 c7cd7c9e1b0f52a2 simple 4 server 8787` + - Host 2: `./build/test/unit zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787` +To run a multi-message IPv4 client/server test: + - Host 1: ./build/test/unit zt2 c7cd7c9e1b0f52a2 simple 4 server 8787 n_bytes 100 50' + - Host 2: ./build/test/unit zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_bytes 100 50' + + - For more unit test examples, see the [testing]() page + ## Using Language Bindings `SDK_LANG_JAVA=1` `SDK_LANG_CSHARP=1` diff --git a/test/unit/comprehensive.cpp b/test/unit/comprehensive.cpp deleted file mode 100644 index 3009d8d..0000000 --- a/test/unit/comprehensive.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// Comprehensive stress test for socket-like API - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ZeroTierSDK.h" - -#define PASSED 0 -#define FAILED -1 - -std::string str = "welcome to the machine"; - -// [] random -// [OK] simple client ipv4 -// [OK] simple server ipv4 -// [?] simple client ipv6 -// [?] simple server ipv6 -// [OK] sustained client ipv4 -// [OK] sustained server ipv4 -// [?] sustained client ipv6 -// [?] sustained server ipv6 -// [] comprehensive client ipv4 -// [] comprehensive server ipv6 - -// --- - -// comprehensive client addr port -// comprehensive server port -// simple [4|6] client addr port -// simple [4|6] server port - -/****************************************************************************/ -/* SIMPLE CLIENT */ -/****************************************************************************/ - -// -int ipv4_tcp_client_test(struct sockaddr_in *addr, int port) -{ - int sockfd, err; - if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating ZeroTier socket"); - exit(0); - } - if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { - printf("error connecting to remote host (%d)\n", err); - exit(0); - } - printf("sleeping... before writing to fd = %d\n", sockfd); - int wrote = zts_write(sockfd, str.c_str(), str.length()); - while(1) - sleep(1); - err = zts_close(sockfd); - return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes -} - -// -int ipv6_tcp_client_test(struct sockaddr_in6 *addr, int port) -{ - int sockfd, err; - if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating ZeroTier socket"); - exit(0); - } - if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { - printf("error connecting to remote host (%d)\n", err); - exit(0); - } - int wrote = zts_write(sockfd, str.c_str(), str.length()); - err = zts_close(sockfd); - return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes -} - - - - -/****************************************************************************/ -/* SIMPLE SERVER */ -/****************************************************************************/ - -// -int ipv4_tcp_server_test(struct sockaddr_in *addr, int port) -{ - int sockfd, err; - if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating ZeroTier socket"); - exit(0); - } - if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { - printf("error binding to interface (%d)\n", err); - exit(0); - } - if((err = zts_listen(sockfd, 100)) < 0) { - printf("error placing socket in LISTENING state (%d)\n", err); - exit(0); - } - // TODO: handle new address - if((err = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { - printf("error accepting connection (%d)\n", err); - exit(0); - } - sleep(3); - printf("accept fd = %d\n", err); - char buf[32]; - int read = zts_read(err, buf, sizeof buf); - printf("buf = %s\n", buf); - err = zts_close(err); - //return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes - return err; -} - -// -int ipv6_tcp_server_test(struct sockaddr_in6 *addr, int port) -{ - int sockfd, err; - if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating ZeroTier socket"); - exit(0); - } - if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6)) < 0)) { - printf("error binding to interface (%d)\n", err); - exit(0); - } - if((err = zts_listen(sockfd, 1)) < 0) { - printf("error placing socket in LISTENING state (%d)\n", err); - exit(0); - } - // TODO: handle new address - if((err = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { - printf("error accepting connection (%d)\n", err); - exit(0); - } - int wrote = zts_write(sockfd, str.c_str(), str.length()); - err = zts_close(sockfd); - return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes -} - - - - - -/****************************************************************************/ -/* SUSTAINED CLIENT */ -/****************************************************************************/ - -// Maintain transfer for n_seconds OR n_times -int ipv4_tcp_client_sustained_test(struct sockaddr_in *addr, int port, int n_seconds, int n_times) -{ - int sockfd, err; - int msg_len = str.length(); - int wrote = 0; - if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("error creating ZeroTier socket"); - exit(0); - } - if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { - printf("error connecting to remote host (%d)\n", err); - exit(0); - } - if(n_seconds) { - /* - printf("testing for (%d) seconds\n", n_seconds); - int wrote; - for(int i=0; ih_addr, server->h_length); - addr6.sin6_port = htons(port); - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv6_tcp_client_test(&addr6, port) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - } - - // SIMPLE SERVER - if(mode == "server") - { - port = atoi(argv[7]); - printf("serving on port %s\n", argv[7]); - - // IPv4 - if(protocol == "4") { - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(argv[6]); - // addr.sin_addr.s_addr = htons(INADDR_ANY); - addr.sin_family = AF_INET; - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv4_tcp_server_test(&addr, port) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - - // IPv6 - if(protocol == "6") { - server = gethostbyname2(argv[6],AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); - - addr6.sin6_addr = in6addr_any; - //memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); - - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv6_tcp_server_test(&addr6, port) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - } - } - - /****************************************************************************/ - /* SUSTAINED */ - /****************************************************************************/ - - // SUSTAINED - // Performs a stress test for benchmarking performance - if(type == "sustained") - { - protocol = argv[4]; // 4, 6 - mode = argv[5]; // client, server - - // SUSTAINED CLIENT - if(mode == "client") - { - port = atoi(argv[7]); - printf("connecting to %s on port %s\n", argv[6], argv[7]); - - // IPv4 - if(protocol == "4") { - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(argv[6]); - addr.sin_family = AF_INET; - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv4_tcp_client_sustained_test(&addr, port, n_seconds, n_times) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - - // IPv6 - if(protocol == "6") { - server = gethostbyname2(argv[6],AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); - addr6.sin6_port = htons(port); - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv6_tcp_client_sustained_test(&addr6, port, n_seconds, n_times) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - } - - // SUSTAINED SERVER - if(mode == "server") - { - port = atoi(argv[7]); - printf("serving on port %s\n", argv[7]); - - // IPv4 - if(protocol == "4") { - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(argv[6]); - // addr.sin_addr.s_addr = htons(INADDR_ANY); - addr.sin_family = AF_INET; - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv4_tcp_server_sustained_test(&addr, port, n_seconds, n_times) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - - // IPv6 - if(protocol == "6") { - server = gethostbyname2(argv[6],AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); - - addr6.sin6_addr = in6addr_any; - //memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); - - printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); - if(ipv6_tcp_server_sustained_test(&addr6, port, n_seconds, n_times) == PASSED) - printf("PASSED\n"); - else - printf("FAILED\n"); - return 0; - } - } - } - - - /****************************************************************************/ - /* COMPREHENSIVE */ - /****************************************************************************/ - - // COMPREHENSIVE - // Tests ALL API calls - if(type == "comprehensive") - { - - } - - - /****************************************************************************/ - /* RANDOM */ - /****************************************************************************/ - - // RANDOM - // performs random API calls with plausible (and random) arguments/data - if(type == "random") - { - - } - - printf("invalid configuration. exiting.\n"); - return 0; -} \ No newline at end of file diff --git a/test/unit/unit.cpp b/test/unit/unit.cpp new file mode 100644 index 0000000..3b6e473 --- /dev/null +++ b/test/unit/unit.cpp @@ -0,0 +1,807 @@ +// Comprehensive stress test for socket-like API + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ZeroTierSDK.h" + +#define PASSED 0 +#define FAILED -1 + +#define ECHO_INTERVAL 100000 // us +#define STR_SIZE 32 + +#define TEST_OP_N_BYTES 10 +#define TEST_OP_N_SECONDS 11 +#define TEST_OP_N_TIMES 12 + +#define TEST_MODE_CLIENT 20 +#define TEST_MODE_SERVER 21 + +#define TEST_TYPE_SIMPLE 30 +#define TEST_TYPE_SUSTAINED 31 + +char str[STR_SIZE]; + +// [] random +// [OK] simple client ipv4 +// [OK] simple server ipv4 +// [?] simple client ipv6 +// [?] simple server ipv6 +// [OK] sustained client ipv4 +// [OK] sustained server ipv4 +// [?] sustained client ipv6 +// [?] sustained server ipv6 +// [] comprehensive client ipv4 +// [] comprehensive server ipv6 + +/* Performance Tests + +Throughput +Memory Usage +Processor usage + +socket API semantics + - Proper socket closure + - Proper handling of blocking/non-blocking behaviour + - replicate specific errno conditions and verify correctness + +Network semantics + - Multi-network handling + - Address handling + +ZeroTier-specific functionality + +*/ + +/****************************************************************************/ +/* SIMPLE CLIENT */ +/****************************************************************************/ + +// +int ipv4_tcp_client_test(struct sockaddr_in *addr, int port) +{ + int r, w, sockfd, err, len = strlen(str); + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { + printf("error connecting to remote host (%d)\n", err); + } + w = zts_write(sockfd, str, len); + r = zts_read(sockfd, rbuf, len); + err = zts_close(sockfd); + return (w == len && r == len && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; +} + +// +int ipv6_tcp_client_test(struct sockaddr_in6 *addr, int port) +{ + int r, w, sockfd, err, len = strlen(str); + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { + printf("error connecting to remote host (%d)\n", err); + } + w = zts_write(sockfd, str, len); + r = zts_read(sockfd, rbuf, len); + err = zts_close(sockfd); + return (w == len && r == len && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; +} + + + + +/****************************************************************************/ +/* SIMPLE SERVER */ +/****************************************************************************/ + +// +int ipv4_tcp_server_test(struct sockaddr_in *addr, int port) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { + printf("error binding to interface (%d)\n", err); + } + if((err = zts_listen(sockfd, 100)) < 0) { + printf("error placing socket in LISTENING state (%d)\n", err); + } + // TODO: handle new address + if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { + printf("error accepting connection (%d)\n", err); + } + r = zts_read(accfd, rbuf, sizeof rbuf); + w = zts_write(accfd, rbuf, len); + zts_close(sockfd); + zts_close(accfd); + return (w == len && r == len && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; +} + +// +int ipv6_tcp_server_test(struct sockaddr_in6 *addr, int port) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { + printf("error binding to interface (%d)\n", err); + } + if((err = zts_listen(sockfd, 100)) < 0) { + printf("error placing socket in LISTENING state (%d)\n", err); + } + // TODO: handle new address + if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { + printf("error accepting connection (%d)\n", err); + } + r = zts_read(accfd, rbuf, sizeof rbuf); + w = zts_write(accfd, rbuf, len); + zts_close(sockfd); + zts_close(accfd); + return (w == len && r == len && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; +} + + + + + +/****************************************************************************/ +/* SUSTAINED CLIENT */ +/****************************************************************************/ + +// Maintain transfer for n_count OR n_count +int ipv4_tcp_client_sustained_test(struct sockaddr_in *addr, int port, int operation, int n_count, int delay) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + int tot, n=0; + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { + printf("error connecting to remote host (%d)\n", err); + } + //zts_fcntl(sockfd, F_SETFL, O_NONBLOCK); + if(operation == TEST_OP_N_TIMES) { + tot = len*n_count; + for(int i=0; i 0) + w += n; + n = zts_read(sockfd, rbuf, len); + if (n > 0) + r += n; + } + err = zts_close(sockfd); + return (r == tot && w == tot && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; + } + if(operation == TEST_OP_N_BYTES) { + tot = n_count; + while(r < tot || w < tot) { + usleep(delay * 1000); + if (w < tot) + n = zts_write(sockfd, str, n_count); + if (n > 0) + w += n; + if (r < tot) + n = zts_read(sockfd, rbuf, n_count); + if (n > 0) + r += n; + } + err = zts_close(sockfd); + return (r == tot && w == tot && !err) ? PASSED : FAILED; + } + return FAILED; +} + +// Maintain transfer for n_count OR n_count +int ipv6_tcp_client_sustained_test(struct sockaddr_in6 *addr, int port, int operation, int n_count, int delay) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + int tot, n=0; + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { + printf("error connecting to remote host (%d)\n", err); + } + //zts_fcntl(sockfd, F_SETFL, O_NONBLOCK); + if(operation == TEST_OP_N_TIMES) { + tot = len*n_count; + for(int i=0; i 0) + w += n; + n = zts_read(sockfd, rbuf, len); + if (n > 0) + r += n; + } + err = zts_close(sockfd); + return (r == tot && w == tot && !err) && !strcmp(rbuf, str) ? PASSED : FAILED; + } + if(operation == TEST_OP_N_BYTES) { + tot = n_count; + while(r < tot || w < tot) { + usleep(delay * 1000); + if (w < tot) + n = zts_write(sockfd, str, n_count); + if (n > 0) + w += n; + if (r < tot) + n = zts_read(sockfd, rbuf, n_count); + if (n > 0) + r += n; + } + err = zts_close(sockfd); + return (r == tot && w == tot && !err) ? PASSED : FAILED; + } + return FAILED; +} + + + + + +/****************************************************************************/ +/* SUSTAINED SERVER */ +/****************************************************************************/ + +// Maintain transfer for n_count OR n_count +int ipv4_tcp_server_sustained_test(struct sockaddr_in *addr, int port, int operation, int n_count, int delay) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + int tot, n=0; + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_bind(sockfd, (struct sockaddr *)addr, (socklen_t)sizeof(struct sockaddr_in)) < 0)) { + printf("error binding to interface (%d)\n", err); + } + if((err = zts_listen(sockfd, 1)) < 0) { + printf("error placing socket in LISTENING state (%d)\n", err); + } + // TODO: handle new address + if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { + printf("error accepting connection (%d)\n", err); + } + //zts_fcntl(accfd, F_SETFL, O_NONBLOCK); + if(operation == TEST_OP_N_TIMES) { + tot = len*n_count; + for(int i=0; i 0) + r += n; + if (w < tot) + n = zts_write(accfd, str, n_count); + if (n > 0) + w += n; + } + zts_close(sockfd); + zts_close(accfd); + return (r == tot && w == tot && !err) ? PASSED : FAILED; + } + return FAILED; +} + +// Maintain transfer for n_count OR n_count +int ipv6_tcp_server_sustained_test(struct sockaddr_in6 *addr, int port, int operation, int n_count, int delay) +{ + int w=0, r=0, sockfd, accfd, err, len = strlen(str); + int tot, n=0; + char rbuf[STR_SIZE]; + if((sockfd = zts_socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + printf("error creating ZeroTier socket"); + } + if((err = zts_bind(sockfd, (struct sockaddr *)addr, (socklen_t)sizeof(struct sockaddr_in)) < 0)) { + printf("error binding to interface (%d)\n", err); + } + if((err = zts_listen(sockfd, 1)) < 0) { + printf("error placing socket in LISTENING state (%d)\n", err); + } + // TODO: handle new address + if((accfd = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { + printf("error accepting connection (%d)\n", err); + } + //zts_fcntl(accfd, F_SETFL, O_NONBLOCK); + if(operation == TEST_OP_N_TIMES) { + tot = len*n_count; + for(int i=0; i 0) + r += n; + if (w < tot) + n = zts_write(accfd, str, n_count); + if (n > 0) + w += n; + } + zts_close(sockfd); + zts_close(accfd); + return (r == tot && w == tot && !err) ? PASSED : FAILED; + } + return FAILED;} + + + + + +/****************************************************************************/ +/* RANDOMIZED API TEST */ +/****************************************************************************/ + +int random_api_test() +{ + // PASSED implies we didn't segfault or hang anywhere + + // + int calls_made = 0; + + // how many calls we'll make + int num_of_api_calls = 10; + +/* +zts_socket() +zts_connect() +zts_listen() +zts_accept() +zts_bind() +zts_getsockopt() +zts_setsockopt() +zts_fnctl() +zts_close() +*/ + + // variables which will be populated with random values + int fd, arg_val; + struct sockaddr_in addr; + struct sockaddr_in6 addr6; + + while(calls_made < num_of_api_calls) + { + fprintf(stderr, "calls_made = %d\n", calls_made); + int random_call = 0; + +/* + switch(random_call) + { + default: + printf() + } +*/ + + + + calls_made++; + } + return PASSED; +} + + +/****************************************************************************/ +/* test driver, called from main() */ +/****************************************************************************/ + +/* +* +* path = place where ZT keys, and config files will be stored +* nwid = network for app to join +* type = simple, sustained +* protocol = 4, 6 +* mode = client, server +* addr = ip address string +* port = integer +* operation = n_times, n_seconds, n_bytes, etc +* n_count = number of operations of type +* delay = delay between each operation +* +*/ +int do_test(std::string path, std::string nwid, int type, int protocol, int mode, std::string ipstr, int port, int operation, int n_count, int delay) +{ + struct hostent *server; + struct sockaddr_in6 addr6; + struct sockaddr_in addr; + + printf("\npath = %s\n", path.c_str()); + printf("nwid = %s\n", nwid.c_str()); + printf("type = %d\n", type); + printf("protocol = %d\n", protocol); + printf("mode = %d\n", mode); + printf("ipstr = %s\n", ipstr.c_str()); + printf("port = %d\n", port); + printf("operation = %d\n", operation); + printf("n_count = %d\n", n_count); + printf("delay = %d\n\n", delay); + + /****************************************************************************/ + /* SIMPLE */ + /****************************************************************************/ + + // SIMPLE + // performs a one-off test of a particular subset of the API + // For instance (ipv4 client, ipv6 server, etc) + if(type == TEST_TYPE_SIMPLE) { + if(mode == TEST_MODE_CLIENT) { + + std::cout << "connecting to " << ipstr << " on port " << port << std::endl; + // IPv4 + if(protocol == 4) { + addr.sin_addr.s_addr = inet_addr(ipstr.c_str()); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv4_tcp_client_test(&addr, port); + } + // IPv6 + if(protocol == 6) { + server = gethostbyname2(ipstr.c_str(),AF_INET6); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + addr6.sin6_port = htons(port); + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv6_tcp_client_test(&addr6, port); + } + } + + if(mode == TEST_MODE_SERVER) { + + //printf("serving on port %s\n", port); + // IPv4 + if(protocol == 4) { + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(ipstr.c_str()); + // addr.sin_addr.s_addr = htons(INADDR_ANY); + addr.sin_family = AF_INET; + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv4_tcp_server_test(&addr, port); + } + // IPv6 + if(protocol == 6) { + + struct hostent *server; + server = gethostbyname2("fde5:cd7a:9e1c:0fd2:7299:9369:4d7b:feff",AF_INET6); + if (server == NULL) { + printf("ERROR, no such host\n"); + exit(0); + } + + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + addr6.sin6_port = htons(port); + + /* + server = gethostbyname2(ipstr.c_str(),AF_INET6); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(port); + //addr6.sin6_addr = in6addr_any; + memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + printf("ipstr = %s\n", ipstr.c_str()); + + */ + return ipv6_tcp_server_test(&addr6, port); + } + } + } + + /****************************************************************************/ + /* SUSTAINED */ + /****************************************************************************/ + + // ./unit zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_seconds 10 50 + // ./unit zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_bytes 100 50 + // ./unit zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_times 100 50 + + // SUSTAINED + // Performs a stress test for benchmarking performance + if(type == TEST_TYPE_SUSTAINED) { + if(mode == TEST_MODE_CLIENT) { + + //printf("connecting to %s on port %d\n", ipstr, port); + // IPv4 + if(protocol == 4) { + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(ipstr.c_str()); + addr.sin_family = AF_INET; + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv4_tcp_client_sustained_test(&addr, port, operation, n_count, delay); + } + // IPv6 + if(protocol == 6) { + server = gethostbyname2(ipstr.c_str(),AF_INET6); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + addr6.sin6_port = htons(port); + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv6_tcp_client_sustained_test(&addr6, port, operation, n_count, delay); + } + } + + if(mode == TEST_MODE_SERVER) + { + //printf("serving on port %d\n", port); + // IPv4 + if(protocol == 4) { + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(ipstr.c_str()); + // addr.sin_addr.s_addr = htons(INADDR_ANY); + addr.sin_family = AF_INET; + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv4_tcp_server_sustained_test(&addr, port, operation, n_count, delay); + } + // IPv6 + if(protocol == 6) { + server = gethostbyname2(ipstr.c_str(),AF_INET6); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(port); + addr6.sin6_addr = in6addr_any; + //memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + //printf(" running (%d) test as ipv=%d\n", mode, protocol); + return ipv6_tcp_server_sustained_test(&addr6, port, operation, n_count, delay); + } + } + } + return 0; +} + + + + +/****************************************************************************/ +/* main (calls test driver: do_test(...)) */ +/****************************************************************************/ + +// zt2 c7cd7c9e1b0f52a2 simple 4 client 10.9.9.40 8787 n_seconds 10 50 +// int do_test(std::string path, std::string nwid, int type, int protocol, int mode, char *ipstr, int port, int operation, int n_count, int delay) + +int main(int argc , char *argv[]) +{ + if(argc < 3) { + printf("usage: ./unit <4|6> \n"); + return 1; + } + + int err = 0; + int type = 0; + int protocol = 0; + int mode = 0; + int port = 0; + int operation = 0; + int n_count = 0; + int delay = 0; + + std::string path = argv[1]; + std::string nwid = argv[2]; + std::string stype = argv[3]; + std::string ipstr, ipstr6; + + memcpy(str, "welcome to the machine", 22); + + // If we're performing a non-random test, join the network we want to test on + // and wait until the service initializes the SocketTap and provides an address + if(stype == "simple" || stype == "sustained" || stype == "comprehensive") { + zts_start(path.c_str()); + printf("waiting for service to start...\n"); + while(!zts_service_running()) + sleep(1); + printf("joining network...\n"); + zts_join_network(nwid.c_str()); + printf("waiting for address assignment...\n"); + while(!zts_has_address(nwid.c_str())) + sleep(1); + printf("complete\n"); + } + + // SIMPLE + // performs a one-off test of a particular subset of the API + // For instance (ipv4 client, ipv6 server, etc) + if(stype == "simple") + { + // Parse args + type = TEST_TYPE_SIMPLE; + protocol = atoi(argv[4]); + if(!strcmp(argv[5],"client")) + mode = TEST_MODE_CLIENT; + if(!strcmp(argv[5],"server")) + mode = TEST_MODE_SERVER; + ipstr = argv[6]; + port = atoi(argv[7]); + + // Perform test + if((err = do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay)) == PASSED) + fprintf(stderr, "PASSED\n"); + else + fprintf(stderr, "FAILED\n"); + return err; + } + + // SUSTAINED + // Performs a stress test for benchmarking performance + if(stype == "sustained") + { + type = TEST_TYPE_SUSTAINED; + protocol = atoi(argv[4]); + if(!strcmp(argv[5],"client")) + mode = TEST_MODE_CLIENT; + if(!strcmp(argv[5],"server")) + mode = TEST_MODE_SERVER; + ipstr = argv[6]; + port = atoi(argv[7]); + + + std::string s_operation = argv[ 8]; // n_count, n_count, n_count + n_count = atoi(argv[ 9]); // 10, 100, 1000, ... + delay = atoi(argv[10]); // 100 (in ms) + + if(s_operation == "n_times") + operation = TEST_OP_N_TIMES; + if(s_operation == "n_bytes") + operation = TEST_OP_N_BYTES; + if(s_operation == "n_seconds") + operation = TEST_OP_N_SECONDS; + + // Perform test + if((err = do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay)) == PASSED) + fprintf(stderr, "PASSED\n"); + else + fprintf(stderr, "FAILED\n"); + return err; + } + + /****************************************************************************/ + /* COMPREHENSIVE */ + /****************************************************************************/ + + // ./unit zt2 c7cd7c9e1b0f52a2 comprehensive client ipv4 ipv6 9009 + // ./unit zt2 c7cd7c9e1b0f52a2 comprehensive server ipv4 ipv6 9009 + + // COMPREHENSIVE + // Tests ALL API calls + if(stype == "comprehensive") + { + // Parse args + type = TEST_TYPE_SIMPLE; + if(!strcmp(argv[4],"client")) + mode = TEST_MODE_CLIENT; + if(!strcmp(argv[4],"server")) + mode = TEST_MODE_SERVER; + ipstr = argv[5]; + ipstr6 = argv[6]; + port = atoi(argv[7]); + + /* Each host must operate as the counterpoint to the other, thus, each mode + * will call the same test helper functions in different orders + * Additionally, the test will use the preset paremeters below for the test: + */ + + int test = 0; + printf("comprehensive\n"); + printf("test = %d\n", test); + test = !test; + printf("test = %d\n", test); + + delay = 0; + n_count = 10; + type = TEST_TYPE_SIMPLE; + operation = TEST_OP_N_TIMES; + + // IPV4 + protocol = 4; + // perform first test arrangement + do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay); + sleep(1); + do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay); + sleep(1); + // swtich modes + if(mode == TEST_MODE_SERVER) + mode = TEST_MODE_CLIENT; + else if(mode == TEST_MODE_CLIENT) + mode = TEST_MODE_SERVER; + // perform second test arrangement + do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay); + sleep(1); + do_test(path, nwid, type, protocol, mode, ipstr, port, operation, n_count, delay); + + // IPV6 + protocol = 6; + // perform first test arrangement + do_test(path, nwid, type, protocol, mode, ipstr6, port, operation, n_count, delay); + sleep(1); + do_test(path, nwid, type, protocol, mode, ipstr6, port, operation, n_count, delay); + sleep(1); + // swtich modes + if(mode == TEST_MODE_SERVER) + mode = TEST_MODE_CLIENT; + else if(mode == TEST_MODE_CLIENT) + mode = TEST_MODE_SERVER; + // perform second test arrangement + do_test(path, nwid, type, protocol, mode, ipstr6, port, operation, n_count, delay); + sleep(1); + do_test(path, nwid, type, protocol, mode, ipstr6, port, operation, n_count, delay); + + + /* + ipv4_tcp_client_test + ipv6_tcp_client_test + ipv4_tcp_server_test + ipv6_tcp_server_test + ipv4_tcp_client_sustained_test + ipv6_tcp_client_sustained_test + ipv4_tcp_server_sustained_test + ipv6_tcp_server_sustained_test + */ + } + + + /****************************************************************************/ + /* RANDOM */ + /****************************************************************************/ + + // RANDOM + // performs random API calls with plausible (and random) arguments/data + if(stype == "random") + { + random_api_test(); + } + + while(1) + sleep(1); + return 0; +} \ No newline at end of file