diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 13:00:17 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 13:00:17 +0100 |
| commit | 632960a33eb8d23925b2bbef24d5065de7280aef (patch) | |
| tree | 37805cf0e22bb1c56a4b5eac22727004b0a0d245 /tests | |
| parent | 17dbb4ccbff1259da86ce6a602cbcd8f49ecfbf5 (diff) | |
Clean up peer re-distribution between single bucket vectors and bucket lists, add tests
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/t_vector.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/tests/t_vector.c b/tests/t_vector.c index fee336b..a8186b2 100644 --- a/tests/t_vector.c +++ b/tests/t_vector.c | |||
| @@ -4,10 +4,12 @@ | |||
| 4 | $id$ */ | 4 | $id$ */ |
| 5 | 5 | ||
| 6 | /* System */ | 6 | /* System */ |
| 7 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | 8 | #include <stdlib.h> |
| 8 | #include <string.h> | 9 | #include <string.h> |
| 9 | 10 | ||
| 10 | /* Opentracker */ | 11 | /* Opentracker */ |
| 12 | #include "ot_vector.h" | ||
| 11 | #include "trackerlogic.h" | 13 | #include "trackerlogic.h" |
| 12 | #include "test.h" | 14 | #include "test.h" |
| 13 | 15 | ||
| @@ -149,6 +151,105 @@ static void case_insert_compare_prefix(void) { | |||
| 149 | free(vector.data); | 151 | free(vector.data); |
| 150 | } | 152 | } |
| 151 | 153 | ||
| 154 | /* ------------------------------------------------- bucket redistribution */ | ||
| 155 | |||
| 156 | /* A flat peer list of count distinct v4 peers. The low byte of the index goes | ||
| 157 | into the first address byte, so the peers are distinct but arrive in no | ||
| 158 | particular order: a list generated in ascending order would come back | ||
| 159 | sorted whether or not vector_redistribute_buckets sorted it. */ | ||
| 160 | static void build_flat_peerlist(ot_peerlist *peer_list, size_t count) { | ||
| 161 | size_t i; | ||
| 162 | |||
| 163 | memset(peer_list, 0, sizeof(*peer_list)); | ||
| 164 | peer_list->peers.data = malloc(count * OT_PEER_SIZE4); | ||
| 165 | peer_list->peers.size = count; | ||
| 166 | peer_list->peers.space = count; | ||
| 167 | peer_list->peer_count = count; | ||
| 168 | |||
| 169 | for (i = 0; i < count; ++i) { | ||
| 170 | uint8_t *peer = (uint8_t *)peer_list->peers.data + i * OT_PEER_SIZE4; | ||
| 171 | |||
| 172 | memset(peer, 0, OT_PEER_SIZE4); | ||
| 173 | peer[0] = (uint8_t)i; | ||
| 174 | peer[1] = (uint8_t)(i >> 8); | ||
| 175 | peer[2] = (uint8_t)(i >> 16); | ||
| 176 | peer[3] = 1; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static void case_redistribute_holds_every_peer(void) { | ||
| 181 | const size_t count = 513; | ||
| 182 | ot_peerlist peer_list; | ||
| 183 | size_t bucket, total_size = 0, empty = 0, largest = 0; | ||
| 184 | ot_vector *buckets; | ||
| 185 | |||
| 186 | test_case("a peer list past the threshold is split into buckets"); | ||
| 187 | build_flat_peerlist(&peer_list, count); | ||
| 188 | CHECK(peer_list.peers.data != NULL); | ||
| 189 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | ||
| 190 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 1); | ||
| 191 | CHECK_INT(peer_list.peers.size, 16); | ||
| 192 | |||
| 193 | buckets = peer_list.peers.data; | ||
| 194 | for (bucket = 0; bucket < peer_list.peers.size; ++bucket) { | ||
| 195 | total_size += buckets[bucket].size; | ||
| 196 | if (!buckets[bucket].size) | ||
| 197 | ++empty; | ||
| 198 | if (buckets[bucket].size > largest) | ||
| 199 | largest = buckets[bucket].size; | ||
| 200 | } | ||
| 201 | |||
| 202 | test_case("no peer is lost on the way"); | ||
| 203 | CHECK_INT(total_size, count); | ||
| 204 | |||
| 205 | /* The point of the exercise is that a lookup only searches one bucket, so | ||
| 206 | a hash that piled everything into one would defeat it. The input and the | ||
| 207 | hash are both fixed, so this is not a matter of luck. */ | ||
| 208 | test_case("and they are spread over the buckets rather than piled up"); | ||
| 209 | CHECK_INT(empty, 0); | ||
| 210 | CHECK(largest < count / 2); | ||
| 211 | |||
| 212 | vector_clean_list(peer_list.peers.data, peer_list.peers.size); | ||
| 213 | } | ||
| 214 | |||
| 215 | static void case_redistribute_sorts_each_bucket(void) { | ||
| 216 | const size_t count = 1000; | ||
| 217 | ot_peerlist peer_list; | ||
| 218 | size_t bucket, i, out_of_order = 0; | ||
| 219 | ot_vector *buckets; | ||
| 220 | |||
| 221 | test_case("every bucket comes back sorted, so bsearch can be used on it"); | ||
| 222 | build_flat_peerlist(&peer_list, count); | ||
| 223 | CHECK(peer_list.peers.data != NULL); | ||
| 224 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | ||
| 225 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 1); | ||
| 226 | |||
| 227 | buckets = peer_list.peers.data; | ||
| 228 | for (bucket = 0; bucket < peer_list.peers.size; ++bucket) | ||
| 229 | for (i = 1; i < buckets[bucket].size; ++i) { | ||
| 230 | const uint8_t *prev = (uint8_t *)buckets[bucket].data + (i - 1) * OT_PEER_SIZE4; | ||
| 231 | const uint8_t *next = (uint8_t *)buckets[bucket].data + i * OT_PEER_SIZE4; | ||
| 232 | |||
| 233 | if (memcmp(prev, next, OT_PEER_COMPARE_SIZE4) >= 0) | ||
| 234 | ++out_of_order; | ||
| 235 | } | ||
| 236 | CHECK_INT(out_of_order, 0); | ||
| 237 | |||
| 238 | vector_clean_list(peer_list.peers.data, peer_list.peers.size); | ||
| 239 | } | ||
| 240 | |||
| 241 | static void case_redistribute_below_threshold(void) { | ||
| 242 | ot_peerlist peer_list; | ||
| 243 | |||
| 244 | test_case("a small peer list is left flat"); | ||
| 245 | build_flat_peerlist(&peer_list, 100); | ||
| 246 | CHECK(peer_list.peers.data != NULL); | ||
| 247 | vector_redistribute_buckets(&peer_list, OT_PEER_SIZE4); | ||
| 248 | CHECK_INT(OT_PEERLIST_HASBUCKETS(&peer_list), 0); | ||
| 249 | CHECK_INT(peer_list.peers.size, 100); | ||
| 250 | free(peer_list.peers.data); | ||
| 251 | } | ||
| 252 | |||
| 152 | void test_vector(void) { | 253 | void test_vector(void) { |
| 153 | case_search_finds_member(); | 254 | case_search_finds_member(); |
| 154 | case_search_finds_first_and_last(); | 255 | case_search_finds_first_and_last(); |
| @@ -158,4 +259,7 @@ void test_vector(void) { | |||
| 158 | case_insert_keeps_order(); | 259 | case_insert_keeps_order(); |
| 159 | case_insert_finds_existing(); | 260 | case_insert_finds_existing(); |
| 160 | case_insert_compare_prefix(); | 261 | case_insert_compare_prefix(); |
| 262 | case_redistribute_holds_every_peer(); | ||
| 263 | case_redistribute_sorts_each_bucket(); | ||
| 264 | case_redistribute_below_threshold(); | ||
| 161 | } | 265 | } |
