|
20 | 20 |
|
21 | 21 | #include <assert.h> |
22 | 22 | #include <stdlib.h> |
| 23 | +#include <string.h> |
23 | 24 |
|
24 | 25 | #include "atom_table.h" |
25 | 26 | #include "utils.h" |
@@ -479,13 +480,69 @@ void test_atom_table(void) |
479 | 480 | atom_table_destroy(table); |
480 | 481 | } |
481 | 482 |
|
| 483 | +static void test_atom_table_bulk_grow(void) |
| 484 | +{ |
| 485 | + struct AtomTable *table = atom_table_new(); |
| 486 | + |
| 487 | + const int batches = 40; |
| 488 | + const int per_batch = 17; |
| 489 | + int next_id = 0; |
| 490 | + |
| 491 | + // Bulk atom_table_ensure_atoms does not copy the atom bytes: the stored keys |
| 492 | + // point into the supplied buffer (modules keep their binary alive). Use a |
| 493 | + // single buffer that outlives the table for all batches. |
| 494 | + uint8_t *buf = malloc(batches * per_batch * 64); |
| 495 | + assert(buf != NULL); |
| 496 | + uint8_t *p = buf; |
| 497 | + |
| 498 | + for (int b = 0; b < batches; b++) { |
| 499 | + uint8_t *batch_start = p; |
| 500 | + char name[64]; |
| 501 | + for (int i = 0; i < per_batch; i++) { |
| 502 | + int len = snprintf(name, sizeof(name), "bulk_atom_%d", next_id++); |
| 503 | + *p++ = (uint8_t) len; |
| 504 | + memcpy(p, name, len); |
| 505 | + p += len; |
| 506 | + } |
| 507 | + atom_index_t translate[per_batch]; |
| 508 | + enum AtomTableEnsureAtomResult r |
| 509 | + = atom_table_ensure_atoms(table, batch_start, per_batch, translate, 0); |
| 510 | + assert(r == AtomTableEnsureAtomOk); |
| 511 | + } |
| 512 | + |
| 513 | + int total = batches * per_batch; |
| 514 | + assert((int) atom_table_count(table) == total); |
| 515 | + |
| 516 | + // Every atom must still be retrievable both by index and by name. |
| 517 | + for (int id = 0; id < total; id++) { |
| 518 | + char name[64]; |
| 519 | + int len = snprintf(name, sizeof(name), "bulk_atom_%d", id); |
| 520 | + |
| 521 | + size_t got_len; |
| 522 | + const uint8_t *got = atom_table_get_atom_string(table, id, &got_len); |
| 523 | + assert(got != NULL); |
| 524 | + assert((int) got_len == len); |
| 525 | + assert(memcmp(got, name, len) == 0); |
| 526 | + |
| 527 | + atom_index_t found; |
| 528 | + enum AtomTableEnsureAtomResult r = atom_table_ensure_atom( |
| 529 | + table, (const uint8_t *) name, len, AtomTableAlreadyExisting, &found); |
| 530 | + assert(r == AtomTableEnsureAtomOk); |
| 531 | + assert((int) found == id); |
| 532 | + } |
| 533 | + |
| 534 | + atom_table_destroy(table); |
| 535 | + free(buf); |
| 536 | +} |
| 537 | + |
482 | 538 | int main(int argc, char **argv) |
483 | 539 | { |
484 | 540 | UNUSED(argc); |
485 | 541 | UNUSED(argv); |
486 | 542 |
|
487 | 543 | test_valueshashtable(); |
488 | 544 | test_atom_table(); |
| 545 | + test_atom_table_bulk_grow(); |
489 | 546 |
|
490 | 547 | return EXIT_SUCCESS; |
491 | 548 | } |
0 commit comments