diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/t_clean.c | 48 | ||||
| -rw-r--r-- | tests/t_vector.c | 61 |
2 files changed, 78 insertions, 31 deletions
diff --git a/tests/t_clean.c b/tests/t_clean.c index 0237cc6..ce17bc3 100644 --- a/tests/t_clean.c +++ b/tests/t_clean.c | |||
| @@ -33,6 +33,20 @@ static void announce(struct ot_workstruct *ws, ot_hash *hash, uint8_t last_octet | |||
| 33 | add_peer_to_torrent_and_return_peers(FLAG_TCP, ws, 0); | 33 | add_peer_to_torrent_and_return_peers(FLAG_TCP, ws, 0); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | /* A distinct v4 peer addressed by two octets, to build swarms past 256 */ | ||
| 37 | static size_t announce_wide(struct ot_workstruct *ws, ot_hash *hash, unsigned int which, size_t amount) { | ||
| 38 | static const uint8_t v4mapped[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; | ||
| 39 | |||
| 40 | ws->reply = ws->outbuf; | ||
| 41 | memset(&ws->peer, 0, sizeof(ws->peer)); | ||
| 42 | memcpy(&ws->peer, v4mapped, sizeof(v4mapped)); | ||
| 43 | ((uint8_t *)&ws->peer)[14] = (uint8_t)(which >> 8); | ||
| 44 | ((uint8_t *)&ws->peer)[15] = (uint8_t)which; | ||
| 45 | OT_SETPORT(&ws->peer, &(uint16_t){6881}); | ||
| 46 | ws->hash = hash; | ||
| 47 | return add_peer_to_torrent_and_return_peers(FLAG_TCP, ws, amount); | ||
| 48 | } | ||
| 49 | |||
| 36 | static size_t peers_in(ot_hash *hash) { | 50 | static size_t peers_in(ot_hash *hash) { |
| 37 | char reply[1024]; | 51 | char reply[1024]; |
| 38 | size_t len = return_udp_scrape_for_torrent(*hash, reply); | 52 | size_t len = return_udp_scrape_for_torrent(*hash, reply); |
| @@ -157,6 +171,39 @@ static void case_empty_torrent_timeout_bounds_a_counter_only_torrent(void) { | |||
| 157 | workstruct_deinit(&ws); | 171 | workstruct_deinit(&ws); |
| 158 | } | 172 | } |
| 159 | 173 | ||
| 174 | static void case_a_bucketed_swarm_survives_clean_and_serves(void) { | ||
| 175 | struct ot_workstruct ws; | ||
| 176 | ot_hash hash; | ||
| 177 | ot_torrent *torrent; | ||
| 178 | unsigned int i; | ||
| 179 | const unsigned int n = 600; /* past OT_PEER_BUCKET_MINCOUNT (512) */ | ||
| 180 | |||
| 181 | test_case("a swarm large enough to be bucketed cleans, splits and serves without loss"); | ||
| 182 | memset(hash, 0x34, sizeof(hash)); | ||
| 183 | CHECK_INT(workstruct_init(&ws, G_INBUF_SIZE), 0); | ||
| 184 | |||
| 185 | for (i = 0; i < n; ++i) | ||
| 186 | announce_wide(&ws, &hash, i, 0); | ||
| 187 | CHECK_INT(peers_in(&hash), n); | ||
| 188 | |||
| 189 | torrent = torrent_of(&hash); | ||
| 190 | CHECK(torrent != NULL); | ||
| 191 | CHECK(torrent->peer_list != NULL); | ||
| 192 | |||
| 193 | /* A clean with a minute elapsed splits the flat vector into buckets */ | ||
| 194 | step_clock_back(torrent, -1); | ||
| 195 | CHECK_INT(clean_single_torrent(torrent), 0); | ||
| 196 | CHECK(torrent->peer_list != NULL); | ||
| 197 | CHECK_INT(OT_VECTOR_HASBUCKETS(&torrent->peer_list->peers4), 1); | ||
| 198 | CHECK_INT(peers_in(&hash), n); | ||
| 199 | |||
| 200 | /* Serve a selection back, which walks the bucket list */ | ||
| 201 | CHECK(announce_wide(&ws, &hash, 1, 200) > 0); | ||
| 202 | CHECK_INT(peers_in(&hash), n); | ||
| 203 | |||
| 204 | workstruct_deinit(&ws); | ||
| 205 | } | ||
| 206 | |||
| 160 | void test_clean(void) { | 207 | void test_clean(void) { |
| 161 | sigset_t hup; | 208 | sigset_t hup; |
| 162 | 209 | ||
| @@ -170,5 +217,6 @@ void test_clean(void) { | |||
| 170 | case_a_clock_that_went_back_keeps_the_swarm(); | 217 | case_a_clock_that_went_back_keeps_the_swarm(); |
| 171 | case_an_idle_swarm_still_ages_out(); | 218 | case_an_idle_swarm_still_ages_out(); |
| 172 | case_empty_torrent_timeout_bounds_a_counter_only_torrent(); | 219 | case_empty_torrent_timeout_bounds_a_counter_only_torrent(); |
| 220 | case_a_bucketed_swarm_survives_clean_and_serves(); | ||
| 173 | trackerlogic_deinit(); | 221 | trackerlogic_deinit(); |
| 174 | } | 222 | } |
diff --git a/tests/t_vector.c b/tests/t_vector.c index f0a9bf7..42ce31a 100644 --- a/tests/t_vector.c +++ b/tests/t_vector.c | |||
| @@ -200,17 +200,16 @@ static void case_insert_compare_prefix(void) { | |||
| 200 | into the first address byte, so the peers are distinct but arrive in no | 200 | into the first address byte, so the peers are distinct but arrive in no |
| 201 | particular order: a list generated in ascending order would come back | 201 | particular order: a list generated in ascending order would come back |
| 202 | sorted whether or not vector_redistribute_buckets sorted it. */ | 202 | sorted whether or not vector_redistribute_buckets sorted it. */ |
| 203 | static void build_flat_peerlist(ot_peerlist *peer_list, size_t count) { | 203 | static void build_flat_vector(ot_vector *peers, size_t count) { |
| 204 | size_t i; | 204 | size_t i; |
| 205 | 205 | ||
| 206 | memset(peer_list, 0, sizeof(*peer_list)); | 206 | memset(peers, 0, sizeof(*peers)); |
| 207 | peer_list->peers.data = malloc(count * OT_PEER_SIZE4); | 207 | peers->data = malloc(count * OT_PEER_SIZE4); |
| 208 | peer_list->peers.size = count; | 208 | peers->size = count; |
| 209 | peer_list->peers.space = count; | 209 | peers->space = count; |
| 210 | peer_list->peer_count = count; | ||
| 211 | 210 | ||
| 212 | for (i = 0; i < count; ++i) { | 211 | for (i = 0; i < count; ++i) { |
| 213 | uint8_t *peer = (uint8_t *)peer_list->peers.data + i * OT_PEER_SIZE4; | 212 | uint8_t *peer = (uint8_t *)peers->data + i * OT_PEER_SIZE4; |
| 214 | 213 | ||
| 215 | memset(peer, 0, OT_PEER_SIZE4); | 214 | memset(peer, 0, OT_PEER_SIZE4); |
| 216 | peer[0] = (uint8_t)i; | 215 | peer[0] = (uint8_t)i; |
| @@ -222,19 +221,19 @@ static void build_flat_peerlist(ot_peerlist *peer_list, size_t count) { | |||
| 222 | 221 | ||
| 223 | static void case_redistribute_holds_every_peer(void) { | 222 | static void case_redistribute_holds_every_peer(void) { |
| 224 | const size_t count = 513; | 223 | const size_t count = 513; |
| 225 | ot_peerlist peer_list; | 224 | ot_vector peers; |
| 226 | size_t bucket, total_size = 0, empty = 0, largest = 0; | 225 | size_t bucket, total_size = 0, empty = 0, largest = 0; |
| 227 | ot_vector *buckets; | 226 | ot_vector *buckets; |
| 228 | 227 | ||
| 229 | test_case("a peer list past the threshold is split into buckets"); | 228 | test_case("a peer list past the threshold is split into buckets"); |
| 230 | build_flat_peerlist(&peer_list, count); | 229 | build_flat_vector(&peers, count); |
| 231 | CHECK(peer_list.peers.data != NULL); | 230 | CHECK(peers.data != NULL); |
| 232 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | 231 | vector_redistribute_buckets(&peers, OT_PEER_SIZE4, count); |
| 233 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 1); | 232 | CHECK_INT(OT_VECTOR_HASBUCKETS(&peers), 1); |
| 234 | CHECK_INT(peer_list.peers.size, 16); | 233 | CHECK_INT(peers.size, 16); |
| 235 | 234 | ||
| 236 | buckets = peer_list.peers.data; | 235 | buckets = peers.data; |
| 237 | for (bucket = 0; bucket < peer_list.peers.size; ++bucket) { | 236 | for (bucket = 0; bucket < peers.size; ++bucket) { |
| 238 | total_size += buckets[bucket].size; | 237 | total_size += buckets[bucket].size; |
| 239 | if (!buckets[bucket].size) | 238 | if (!buckets[bucket].size) |
| 240 | ++empty; | 239 | ++empty; |
| @@ -252,23 +251,23 @@ static void case_redistribute_holds_every_peer(void) { | |||
| 252 | CHECK_INT(empty, 0); | 251 | CHECK_INT(empty, 0); |
| 253 | CHECK(largest < count / 2); | 252 | CHECK(largest < count / 2); |
| 254 | 253 | ||
| 255 | vector_clean_list(peer_list.peers.data, peer_list.peers.size); | 254 | vector_clean_list(peers.data, peers.size); |
| 256 | } | 255 | } |
| 257 | 256 | ||
| 258 | static void case_redistribute_sorts_each_bucket(void) { | 257 | static void case_redistribute_sorts_each_bucket(void) { |
| 259 | const size_t count = 1000; | 258 | const size_t count = 1000; |
| 260 | ot_peerlist peer_list; | 259 | ot_vector peers; |
| 261 | size_t bucket, i, out_of_order = 0; | 260 | size_t bucket, i, out_of_order = 0; |
| 262 | ot_vector *buckets; | 261 | ot_vector *buckets; |
| 263 | 262 | ||
| 264 | test_case("every bucket comes back sorted, so bsearch can be used on it"); | 263 | test_case("every bucket comes back sorted, so bsearch can be used on it"); |
| 265 | build_flat_peerlist(&peer_list, count); | 264 | build_flat_vector(&peers, count); |
| 266 | CHECK(peer_list.peers.data != NULL); | 265 | CHECK(peers.data != NULL); |
| 267 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | 266 | vector_redistribute_buckets(&peers, OT_PEER_SIZE4, count); |
| 268 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 1); | 267 | CHECK_INT(OT_VECTOR_HASBUCKETS(&peers), 1); |
| 269 | 268 | ||
| 270 | buckets = peer_list.peers.data; | 269 | buckets = peers.data; |
| 271 | for (bucket = 0; bucket < peer_list.peers.size; ++bucket) | 270 | for (bucket = 0; bucket < peers.size; ++bucket) |
| 272 | for (i = 1; i < buckets[bucket].size; ++i) { | 271 | for (i = 1; i < buckets[bucket].size; ++i) { |
| 273 | const uint8_t *prev = (uint8_t *)buckets[bucket].data + (i - 1) * OT_PEER_SIZE4; | 272 | const uint8_t *prev = (uint8_t *)buckets[bucket].data + (i - 1) * OT_PEER_SIZE4; |
| 274 | const uint8_t *next = (uint8_t *)buckets[bucket].data + i * OT_PEER_SIZE4; | 273 | const uint8_t *next = (uint8_t *)buckets[bucket].data + i * OT_PEER_SIZE4; |
| @@ -278,19 +277,19 @@ static void case_redistribute_sorts_each_bucket(void) { | |||
| 278 | } | 277 | } |
| 279 | CHECK_INT(out_of_order, 0); | 278 | CHECK_INT(out_of_order, 0); |
| 280 | 279 | ||
| 281 | vector_clean_list(peer_list.peers.data, peer_list.peers.size); | 280 | vector_clean_list(peers.data, peers.size); |
| 282 | } | 281 | } |
| 283 | 282 | ||
| 284 | static void case_redistribute_below_threshold(void) { | 283 | static void case_redistribute_below_threshold(void) { |
| 285 | ot_peerlist peer_list; | 284 | ot_vector peers; |
| 286 | 285 | ||
| 287 | test_case("a small peer list is left flat"); | 286 | test_case("a small peer list is left flat"); |
| 288 | build_flat_peerlist(&peer_list, 100); | 287 | build_flat_vector(&peers, 100); |
| 289 | CHECK(peer_list.peers.data != NULL); | 288 | CHECK(peers.data != NULL); |
| 290 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | 289 | vector_redistribute_buckets(&peers, OT_PEER_SIZE4, 100); |
| 291 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 0); | 290 | CHECK_INT(OT_VECTOR_HASBUCKETS(&peers), 0); |
| 292 | CHECK_INT(peer_list.peers.size, 100); | 291 | CHECK_INT(peers.size, 100); |
| 293 | free(peer_list.peers.data); | 292 | free(peers.data); |
| 294 | } | 293 | } |
| 295 | 294 | ||
| 296 | void test_vector(void) { | 295 | void test_vector(void) { |
