diff --git a/test/selftest.cpp b/test/selftest.cpp index 431bc85..48cb707 100644 --- a/test/selftest.cpp +++ b/test/selftest.cpp @@ -299,11 +299,10 @@ void str2addr(std::string ipstr, int port, int ipv, struct sockaddr *saddr) { if (ipv == 4) { struct sockaddr_in *in4 = (struct sockaddr_in*)saddr; - in4->sin_port = htons(port); in4->sin_addr.s_addr = inet_addr(ipstr.c_str()); in4->sin_family = AF_INET; - } - if (ipv == 6) { + in4->sin_port = htons(port); + } if (ipv == 6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)saddr; inet_pton(AF_INET6, ipstr.c_str(), &(in6->sin6_addr)); in6->sin6_flowinfo = 0; @@ -319,18 +318,74 @@ void RECORD_RESULTS(bool passed, char *details, std::vector *result if (passed == PASSED) { DEBUG_TEST("%s", ok_str); results->push_back(std::string(ok_str) + " " + std::string(details)); - } - else { + } else { DEBUG_ERROR("%s", fail_str); results->push_back(std::string(fail_str) + " " + std::string(details)); - } - if (EXIT_ON_FAIL && !passed) { + } if (EXIT_ON_FAIL && !passed) { fprintf(stderr, "%s\n", results->at(results->size()-1).c_str()); exit(0); } memset(details, 0, DETAILS_STR_LEN); } +void wait_until_everyone_is_ready(struct sockaddr *local_addr, struct sockaddr *remote_addr, int start_port) +{ + /* try to connect to (and listen for) other selftest instances on the network. + When one is found, send some sort of synchronization message and allow test to + begin */ + int err; + struct sockaddr_in client; + socklen_t client_addrlen = sizeof(sockaddr_in); + bool connected = false; + int accepted_fd; + // listen socket setup + int listen_fd; + if ((listen_fd = SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + exit(0); + } if ((err = BIND(listen_fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in)) < 0)) { + perror("bind"); + exit(0); + } if ((err = LISTEN(listen_fd, 0)) < 0) { + perror("listen"); + exit(0); + } if ((err = FCNTL(listen_fd, F_SETFL, O_NONBLOCK) < 0)) { + perror("fcntl"); + exit(0); + } + // connect socket setup + int conn_fd; + if ((conn_fd = SOCKET(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + exit(0); + } if ((err = FCNTL(conn_fd, F_SETFL, O_NONBLOCK) < 0)) { + perror("fcntl"); + exit(0); + } + while(connected == false) { + if ((err = CONNECT(conn_fd, (const struct sockaddr *)remote_addr, sizeof(*remote_addr))) < 0) { + if (errno == EISCONN) { + connected = true; + } + } + else { + connected = true; + } + if (connected == false) { + struct sockaddr_in client; + socklen_t client_addrlen = sizeof(sockaddr_in); + if ((accepted_fd = ACCEPT(listen_fd, (struct sockaddr *)&client, &client_addrlen)) < 0) { + DEBUG_TEST("errno = %d", errno);} + else { + connected = true; + } + } + sleep(1); + } + close(listen_fd); + close(conn_fd); + close(accepted_fd); +} /****************************************************************************/ @@ -419,14 +474,11 @@ void tcp_select_server(TCP_UNIT_TEST_SIG_4) } } } - DEBUG_TEST("complete"); sleep(ARTIFICIAL_SOCKET_LINGER); err = CLOSE(fd); sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); - exit(0); - } void tcp_select_client(TCP_UNIT_TEST_SIG_4) @@ -498,30 +550,19 @@ void tcp_select_client(TCP_UNIT_TEST_SIG_4) } } } - DEBUG_TEST("complete"); sleep(ARTIFICIAL_SOCKET_LINGER); err = CLOSE(fd); sprintf(details, "%s, err=%d, r=%d, w=%d", testname.c_str(), err, r, w); *passed = (w == len && r == len && !err) && !strcmp(rbuf, msg.c_str()); - exit(0); - } - - - /****************************************************************************/ /* SIMPLE */ /****************************************************************************/ - - - - // TCP -// TEST-1 void tcp_client_4(TCP_UNIT_TEST_SIG_4) { std::string testname = "tcp_client_4"; @@ -569,7 +610,6 @@ void tcp_client_4(TCP_UNIT_TEST_SIG_4) -// TEST-2 void tcp_server_4(TCP_UNIT_TEST_SIG_4) { std::string testname = "tcp_server_4"; @@ -630,7 +670,6 @@ void tcp_server_4(TCP_UNIT_TEST_SIG_4) -// TEST-3 void tcp_client_6(TCP_UNIT_TEST_SIG_6) { std::string testname = "tcp_client_6"; @@ -678,8 +717,6 @@ void tcp_client_6(TCP_UNIT_TEST_SIG_6) - -// TEST-4 void tcp_server_6(TCP_UNIT_TEST_SIG_6) { std::string testname = "tcp_server_6"; @@ -745,7 +782,6 @@ void tcp_server_6(TCP_UNIT_TEST_SIG_6) // UDP -// TEST-5 void udp_client_4(UDP_UNIT_TEST_SIG_4) { std::string testname = "udp_client_4"; @@ -802,7 +838,6 @@ void udp_client_4(UDP_UNIT_TEST_SIG_4) -// TEST-6 void udp_server_4(UDP_UNIT_TEST_SIG_4) { std::string testname = "udp_server_4"; @@ -862,9 +897,23 @@ void udp_server_4(UDP_UNIT_TEST_SIG_4) +int zts_bind_test(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + int err = -1; + DEBUG_EXTRA("fd=%d", fd); + DEBUG_INFO("addrp=%p", addr); + DEBUG_INFO("addrlen=%d", addrlen); + DEBUG_INFO("sa_family======%d", addr->sa_family); + struct sockaddr_storage ss; + memcpy(&ss, addr, addrlen); + DEBUG_INFO("ss->sa_family=%d", ss.ss_family); + //fix_addr_socket_family((struct sockaddr*)&ss); + //ss.ss_family=AF_INET6; + //DEBUG_INFO("ss->sa_family=%d", ss.ss_family); + //err = lwip_bind(fd, (struct sockaddr*)&ss, addrlen); + exit(0); +} - -// TEST-7 void udp_client_6(UDP_UNIT_TEST_SIG_6) { std::string testname = "udp_client_6"; @@ -887,14 +936,14 @@ void udp_client_6(UDP_UNIT_TEST_SIG_6) *passed = false; return; } + DEBUG_TEST("[1] binding and sending UDP packets until I get a single response..."); - if ((err = BIND(fd, (struct sockaddr *)local_addr, sizeof(struct sockaddr_in6)) < 0)) { - DEBUG_ERROR("error binding to interface (%d)", err); + if ((err = BIND(fd, (struct sockaddr*)local_addr, sizeof(struct sockaddr_in6)) < 0)) { + DEBUG_ERROR("error binding to interface (err=%d, errno=%d)", err, errno); perror("bind"); *passed = false; return; } - // start sending UDP packets in the hopes that at least one will be picked up by the server struct sockaddr_storage saddr; while (true) { @@ -923,8 +972,6 @@ void udp_client_6(UDP_UNIT_TEST_SIG_6) - -// TEST-8 void udp_server_6(UDP_UNIT_TEST_SIG_6) { std::string testname = "udp_server_6"; @@ -2618,6 +2665,14 @@ void bind_to_localhost_test(int port) #endif // __SELFTEST__ +int trigger_address_sanitizer() +{ + // Deliberately create a bad read to trigger address sanitizer + int stack_array[100]; + stack_array[1] = 0; + return stack_array[1 + 100]; // BOOM +} + /****************************************************************************/ /* main(), calls test_driver(...) */ /****************************************************************************/ @@ -2629,7 +2684,6 @@ int main(int argc , char *argv[]) fprintf(stderr, "e.g. : selftest 3 test/test.conf alice to bob\n"); return 1; } - int num_repeats = atoi(argv[1]); std::string path = argv[2]; std::string from = argv[3]; @@ -2694,16 +2748,11 @@ int main(int argc , char *argv[]) fprintf(stderr, "\tremote_ipstr = %s\n", remote_ipstr.c_str()); fprintf(stderr, "\tremote_ipstr6 = %s\n", remote_ipstr6.c_str()); fprintf(stderr, "\tremote_echo_ipv4 = %s\n", remote_echo_ipv4.c_str()); - fprintf(stderr, "\tme = %s\n", me.c_str()); - #if defined(__SELFTEST__) - long int selftest_start_time = get_now_ts(); - subtest_expected_duration = 5; - if (me != "dummy") { // used for testing ZT service wrapper API (before, during, and after coming online) // set start time here since we need to wait for both libzt instances to be online - DEBUG_TEST("Waiting for libzt to come online...\n"); + DEBUG_TEST("app-thread, waiting for libzt to come online...\n"); zts_startjoin(path.c_str(), nwid.c_str()); char device_id[ZTO_ID_LEN]; zts_get_id(device_id); @@ -2714,20 +2763,19 @@ int main(int argc , char *argv[]) if (mode == TEST_MODE_CLIENT) { DEBUG_TEST("Ready. Contacting selftest program on first host.\n\n"); } - - // What follows is a long-form of zts_start(): - /* - zts_start(path.c_str()); - printf("waiting for service to start...\n"); - while (zts_running() == false) - sleep(1); - printf("joining network...\n"); - zts_join(nwid.c_str()); - printf("waiting for address assignment...\n"); - while (zts_has_address(nwid.c_str()) == false) - sleep(1); - */ } + + // SYNCHRONIZE test start times between multiple instances of the selftest on the network + ipv = 4; + int negotiation_port = start_port + 1000; + port = negotiation_port; + str2addr(local_ipstr, port, ipv, (struct sockaddr *)&local_addr); + str2addr(remote_ipstr, port, ipv, (struct sockaddr *)&remote_addr); + wait_until_everyone_is_ready((struct sockaddr *)&local_addr, (struct sockaddr *)&remote_addr, start_port); + DEBUG_TEST("both instances of selftest have started. beginning tests..."); + + long int selftest_start_time = get_now_ts(); + subtest_expected_duration = 5; #endif // __SELFTEST__ for (int i=0; i