-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added tests for addto_lists function
- Loading branch information
Showing
2 changed files
with
357 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,349 @@ | ||
#ifdef HAVE_CONFIG_H | ||
#include "config.h" | ||
#endif | ||
|
||
#include <sys/param.h> | ||
#include <time.h> | ||
|
||
#include "../toxcore/tox.h" | ||
#include "../toxcore/DHT.c" | ||
|
||
#include "helpers.h" | ||
|
||
#define swap(x,y) do \ | ||
{ unsigned char swap_temp[sizeof(x) == sizeof(y) ? (signed)sizeof(x) : -1]; \ | ||
memcpy(swap_temp,&y,sizeof(x)); \ | ||
memcpy(&y,&x, sizeof(x)); \ | ||
memcpy(&x,swap_temp,sizeof(x)); \ | ||
} while(0) | ||
|
||
|
||
void mark_bad(IPPTsPng *ipptp) | ||
{ | ||
ipptp->timestamp = unix_time() - 2 * BAD_NODE_TIMEOUT; | ||
ipptp->hardening.routes_requests_ok = 0; | ||
ipptp->hardening.send_nodes_ok = 0; | ||
ipptp->hardening.testing_requests = 0; | ||
} | ||
|
||
void mark_possible_bad(IPPTsPng *ipptp) | ||
{ | ||
ipptp->timestamp = unix_time(); | ||
ipptp->hardening.routes_requests_ok = 0; | ||
ipptp->hardening.send_nodes_ok = 0; | ||
ipptp->hardening.testing_requests = 0; | ||
} | ||
|
||
void mark_good(IPPTsPng *ipptp) | ||
{ | ||
ipptp->timestamp = unix_time(); | ||
ipptp->hardening.routes_requests_ok = (HARDENING_ALL_OK >> 0) & 1; | ||
ipptp->hardening.send_nodes_ok = (HARDENING_ALL_OK >> 1) & 1; | ||
ipptp->hardening.testing_requests = (HARDENING_ALL_OK >> 2) & 1; | ||
} | ||
|
||
void mark_all_good(Client_data *list, uint32_t length, uint8_t ipv6) | ||
{ | ||
int i; | ||
for (i = 0; i < length; ++i) { | ||
if (ipv6) | ||
mark_good(&list[i].assoc6); | ||
else | ||
mark_good(&list[i].assoc4); | ||
} | ||
} | ||
|
||
/* Returns 1 if client_id has a furthest distance to comp_client_id | ||
than all client_id's in the list */ | ||
uint8_t is_furthest(const uint8_t *comp_client_id, Client_data *list, uint32_t length, const uint8_t *client_id) | ||
{ | ||
int i; | ||
for (i = 0; i < length; ++i) | ||
if (id_closest(comp_client_id, client_id, list[i].client_id) == 1) | ||
return 0; | ||
return 1; | ||
} | ||
|
||
int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id) | ||
{ | ||
int i; | ||
for (i = 0; i < length; ++i) | ||
if (id_equal(client_id, list[i].client_id)) | ||
return i; | ||
return -1; | ||
} | ||
|
||
void test_addto_lists_update(DHT *dht, | ||
Client_data *list, | ||
uint32_t length, | ||
IP_Port *ip_port) | ||
{ | ||
int used, test = rand() % length, test1 = rand() % (length / 2), test2 = rand() % (length / 2) + length / 2; | ||
uint8_t test_id[CLIENT_ID_SIZE]; | ||
IP_Port test_ipp; | ||
uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; | ||
|
||
ipport_copy(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port); | ||
|
||
// check id update for existing ip_port | ||
randombytes(test_id, sizeof(test_id)); | ||
used = addto_lists(dht, test_ipp, test_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
ck_assert_msg(client_in_list(list, length, test_id) == test, "Client id is not in the list"); | ||
ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port), "Client IP_Port is incorrect"); | ||
|
||
// check ip_port update for existing id | ||
test_ipp.port = rand() % TOX_PORT_DEFAULT; | ||
used = addto_lists(dht, test_ipp, test_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
ck_assert_msg(client_in_list(list, length, test_id) == test, "Client id is not in the list"); | ||
ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port), "Client IP_Port is incorrect"); | ||
|
||
// check ip_port update for existing id and ip_port (... port ... id ...) | ||
ipport_copy(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port); | ||
id_copy(test_id, list[test2].client_id); | ||
if (ipv6) list[test2].assoc6.ip_port.port = -1; else list[test2].assoc4.ip_port.port = -1; | ||
used = addto_lists(dht, test_ipp, test_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
ck_assert_msg(client_in_list(list, length, test_id) == test2, "Client id is not in the list"); | ||
ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port), "Client IP_Port is incorrect"); | ||
|
||
// check ip_port update for existing id and ip_port (... id ... port ...) | ||
ipport_copy(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port); | ||
id_copy(test_id, list[test1].client_id); | ||
if (ipv6) list[test1].assoc6.ip_port.port = -1; else list[test1].assoc4.ip_port.port = -1; | ||
used = addto_lists(dht, test_ipp, test_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
ck_assert_msg(client_in_list(list, length, test_id) == test1, "Client id is not in the list"); | ||
ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port), "Client IP_Port is incorrect"); | ||
} | ||
|
||
void test_addto_lists_bad(DHT *dht, | ||
Client_data *list, | ||
uint32_t length, | ||
IP_Port *ip_port) | ||
{ | ||
// check "bad" clients replacement | ||
uint8_t client_id[CLIENT_ID_SIZE], test_id1[CLIENT_ID_SIZE], test_id2[CLIENT_ID_SIZE], test_id3[CLIENT_ID_SIZE]; | ||
int test1, test2, test3; | ||
uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; | ||
|
||
randombytes(client_id, sizeof(client_id)); | ||
mark_all_good(list, length, ipv6); | ||
|
||
test1 = rand() % (length / 3); | ||
test2 = rand() % (length / 3) + length / 3; | ||
test3 = rand() % (length / 3) + 2 * length / 3; | ||
ck_assert_msg(!(test1 == test2 || test1 == test3 || test2 == test3), "Wrong test indices are chosen"); | ||
|
||
id_copy((uint8_t*)&test_id1, list[test1].client_id); | ||
id_copy((uint8_t*)&test_id2, list[test2].client_id); | ||
id_copy((uint8_t*)&test_id3, list[test3].client_id); | ||
|
||
// mark nodes as "bad" | ||
if (ipv6) { | ||
mark_bad(&list[test1].assoc6); | ||
mark_bad(&list[test2].assoc6); | ||
mark_bad(&list[test3].assoc6); | ||
} else { | ||
mark_bad(&list[test1].assoc4); | ||
mark_bad(&list[test2].assoc4); | ||
mark_bad(&list[test3].assoc4); | ||
} | ||
|
||
ip_port->port += 1; | ||
int used = addto_lists(dht, *ip_port, client_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
|
||
ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Client id is not in the list"); | ||
ck_assert_msg(id_equal(client_id, list[test1].client_id), "Wrong bad client removed"); | ||
ck_assert_msg(id_equal(test_id2, list[test2].client_id), "Wrong bad client removed"); | ||
ck_assert_msg(id_equal(test_id3, list[test3].client_id), "Wrong bad client removed"); | ||
} | ||
|
||
void test_addto_lists_possible_bad(DHT *dht, | ||
Client_data *list, | ||
uint32_t length, | ||
IP_Port *ip_port, | ||
const uint8_t *comp_client_id) | ||
{ | ||
// check "possibly bad" clients replacement | ||
uint8_t client_id[CLIENT_ID_SIZE], test_id1[CLIENT_ID_SIZE], test_id2[CLIENT_ID_SIZE], test_id3[CLIENT_ID_SIZE]; | ||
int test1, test2, test3; | ||
uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; | ||
|
||
randombytes(client_id, sizeof(client_id)); | ||
mark_all_good(list, length, ipv6); | ||
|
||
test1 = rand() % (length / 3); | ||
test2 = rand() % (length / 3) + length / 3; | ||
test3 = rand() % (length / 3) + 2 * length / 3; | ||
ck_assert_msg(!(test1 == test2 || test1 == test3 || test2 == test3), "Wrong test indices are chosen"); | ||
|
||
id_copy((uint8_t*)&test_id1, list[test1].client_id); | ||
id_copy((uint8_t*)&test_id2, list[test2].client_id); | ||
id_copy((uint8_t*)&test_id3, list[test3].client_id); | ||
|
||
// mark nodes as "possibly bad" | ||
if (ipv6) { | ||
mark_possible_bad(&list[test1].assoc6); | ||
mark_possible_bad(&list[test2].assoc6); | ||
mark_possible_bad(&list[test3].assoc6); | ||
} else { | ||
mark_possible_bad(&list[test1].assoc4); | ||
mark_possible_bad(&list[test2].assoc4); | ||
mark_possible_bad(&list[test3].assoc4); | ||
} | ||
|
||
ip_port->port += 1; | ||
int used = addto_lists(dht, *ip_port, client_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
|
||
ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Client id is not in the list"); | ||
|
||
int inlist_id1 = client_in_list(list, length, test_id1) >= 0; | ||
int inlist_id2 = client_in_list(list, length, test_id2) >= 0; | ||
int inlist_id3 = client_in_list(list, length, test_id3) >= 0; | ||
|
||
ck_assert_msg(inlist_id1 + inlist_id2 + inlist_id3 == 2, "Wrong client removed"); | ||
|
||
if (!inlist_id1) { | ||
ck_assert_msg(id_closest(comp_client_id, test_id2, test_id1) == 1, "Id has been removed but is closer to than another one"); | ||
ck_assert_msg(id_closest(comp_client_id, test_id3, test_id1) == 1, "Id has been removed but is closer to than another one"); | ||
} else if (!inlist_id2) { | ||
ck_assert_msg(id_closest(comp_client_id, test_id1, test_id2) == 1, "Id has been removed but is closer to than another one"); | ||
ck_assert_msg(id_closest(comp_client_id, test_id3, test_id2) == 1, "Id has been removed but is closer to than another one"); | ||
} else if (!inlist_id3) { | ||
ck_assert_msg(id_closest(comp_client_id, test_id1, test_id3) == 1, "Id has been removed but is closer to than another one"); | ||
ck_assert_msg(id_closest(comp_client_id, test_id2, test_id3) == 1, "Id has been removed but is closer to than another one"); | ||
} | ||
} | ||
|
||
void test_addto_lists_good(DHT *dht, | ||
Client_data *list, | ||
uint32_t length, | ||
IP_Port *ip_port, | ||
const uint8_t *comp_client_id) | ||
{ | ||
uint8_t client_id[CLIENT_ID_SIZE]; | ||
uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; | ||
|
||
mark_all_good(list, length, ipv6); | ||
|
||
// check "good" client id replacement | ||
do { | ||
randombytes(client_id, sizeof(client_id)); | ||
} while (is_furthest(comp_client_id, list, length, client_id)); | ||
ip_port->port += 1; | ||
addto_lists(dht, *ip_port, client_id); | ||
ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Good client id is not in the list"); | ||
|
||
// check "good" client id skip | ||
do { | ||
randombytes(client_id, sizeof(client_id)); | ||
} while (!is_furthest(comp_client_id, list, length, client_id)); | ||
|
||
ip_port->port += 1; | ||
addto_lists(dht, *ip_port, client_id); | ||
ck_assert_msg(client_in_list(list, length, client_id) == -1, "Good client id is in the list"); | ||
} | ||
|
||
void test_addto_lists(IP ip) | ||
{ | ||
Networking_Core* net = new_networking(ip, TOX_PORT_DEFAULT); | ||
ck_assert_msg(net != 0, "Failed to create Networking_Core"); | ||
|
||
DHT* dht = new_DHT(net); | ||
ck_assert_msg(dht != 0, "Failed to create DHT"); | ||
|
||
IP_Port ip_port = { .ip = ip, .port = TOX_PORT_DEFAULT }; | ||
uint8_t client_id[CLIENT_ID_SIZE]; | ||
int i; | ||
|
||
// check lists filling | ||
for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) { | ||
randombytes(client_id, sizeof(client_id)); | ||
int used = addto_lists(dht, ip_port, client_id); | ||
ck_assert_msg(used == dht->num_friends + 1, "Wrong number of added clients with existing ip_port"); | ||
} | ||
|
||
for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) { | ||
ip_port.port += 1; | ||
int used = addto_lists(dht, ip_port, client_id); | ||
ck_assert_msg(used == dht->num_friends + 1, "Wrong number of added clients with existing client_id"); | ||
} | ||
|
||
for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) { | ||
ip_port.port += 1; | ||
randombytes(client_id, sizeof(client_id)); | ||
int used = addto_lists(dht, ip_port, client_id); | ||
ck_assert_msg(used >= 1, "Wrong number of added clients"); | ||
} | ||
|
||
/*check: Current behavior if there are two clients with the same id is | ||
* to replace the first ip by the second. */ | ||
test_addto_lists_update(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port); | ||
for (i = 0; i < dht->num_friends; ++i) | ||
test_addto_lists_update(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port); | ||
|
||
// check "bad" entries | ||
test_addto_lists_bad(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port); | ||
for (i = 0; i < dht->num_friends; ++i) | ||
test_addto_lists_bad(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port); | ||
|
||
// check "possibly bad" entries | ||
test_addto_lists_possible_bad(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port, dht->self_public_key); | ||
// for (i = 0; i < dht->num_friends; ++i) | ||
// test_addto_lists_possible_bad(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port, dht->friends_list[i].client_id); | ||
|
||
// check "good" entries | ||
test_addto_lists_good(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port, dht->self_public_key); | ||
for (i = 0; i < dht->num_friends; ++i) | ||
test_addto_lists_good(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port, dht->friends_list[i].client_id); | ||
|
||
kill_DHT(dht); | ||
kill_networking(net); | ||
} | ||
|
||
START_TEST(test_addto_lists_ipv4) | ||
{ | ||
IP ip; | ||
ip_init(&ip, 0); | ||
test_addto_lists(ip); | ||
|
||
} | ||
END_TEST | ||
|
||
START_TEST(test_addto_lists_ipv6) | ||
{ | ||
IP ip; | ||
ip_init(&ip, 1); | ||
test_addto_lists(ip); | ||
|
||
} | ||
END_TEST | ||
|
||
Suite *dht_suite(void) | ||
{ | ||
Suite *s = suite_create("DHT"); | ||
|
||
DEFTESTCASE(addto_lists_ipv4); | ||
DEFTESTCASE(addto_lists_ipv6); | ||
return s; | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
srand((unsigned int) time(NULL)); | ||
|
||
Suite *dht = dht_suite(); | ||
SRunner *test_runner = srunner_create(dht); | ||
|
||
int number_failed = 0; | ||
srunner_run_all(test_runner, CK_NORMAL); | ||
number_failed = srunner_ntests_failed(test_runner); | ||
|
||
srunner_free(test_runner); | ||
|
||
return number_failed; | ||
} |