diff --git a/include/ck_hs.h b/include/ck_hs.h index 91f990b..564e9b6 100644 --- a/include/ck_hs.h +++ b/include/ck_hs.h @@ -108,6 +108,8 @@ typedef struct ck_hs_iterator ck_hs_iterator_t; /* Convenience wrapper to table hash function. */ #define CK_HS_HASH(T, F, K) F((K), (T)->seed) +typedef void *ck_hs_apply_fn_t(void *, void *); +bool ck_hs_apply(ck_hs_t *, unsigned long, const void *, ck_hs_apply_fn_t *, void *); void ck_hs_iterator_init(ck_hs_iterator_t *); bool ck_hs_next(ck_hs_t *, ck_hs_iterator_t *, void **); bool ck_hs_move(ck_hs_t *, ck_hs_t *, ck_hs_hash_cb_t *, diff --git a/regressions/ck_hs/validate/serial.c b/regressions/ck_hs/validate/serial.c index 93a375b..ed3002a 100644 --- a/regressions/ck_hs/validate/serial.c +++ b/regressions/ck_hs/validate/serial.c @@ -85,6 +85,39 @@ hs_compare(const void *previous, const void *compare) return strcmp(previous, compare) == 0; } +static void * +test_ip(void *key, void *closure) +{ + const char *a = key; + const char *b = closure; + + if (strcmp(a, b) != 0) + ck_error("Mismatch: %s != %s\n", a, b); + + return closure; +} + +static void * +test_negative(void *key, void *closure) +{ + + (void)closure; + if (key != NULL) + ck_error("ERROR: Apply callback expects NULL argument instead of [%s]\n", key); + + return NULL; +} + +static void * +test_unique(void *key, void *closure) +{ + + if (key != NULL) + ck_error("ERROR: Apply callback expects NULL argument instead of [%s]\n", key); + + return closure; +} + static void run_test(unsigned int is, unsigned int ad) { @@ -104,12 +137,19 @@ run_test(unsigned int is, unsigned int ad) continue; } - if (ck_hs_put_unique(&hs[j], h, test[i]) == false) - ck_error("ERROR [%zu]: Failed to insert unique (%s)\n", j, test[i]); + if (i & 1) { + if (ck_hs_put_unique(&hs[j], h, test[i]) == false) + ck_error("ERROR [%zu]: Failed to insert unique (%s)\n", j, test[i]); + } else if (ck_hs_apply(&hs[j], h, test[i], test_unique, (char *)test[i]) == false) { + ck_error("ERROR: Failed to apply for insertion.\n"); + } if (ck_hs_remove(&hs[j], h, test[i]) == false) ck_error("ERROR [%zu]: Failed to remove unique (%s)\n", j, test[i]); + if (ck_hs_apply(&hs[j], h, test[i], test_negative, (char *)test[i]) == false) + ck_error("ERROR: Failed to apply.\n"); + break; } @@ -214,8 +254,16 @@ run_test(unsigned int is, unsigned int ad) } if (strcmp(r, test[i]) != 0) { - ck_error("ERROR [%u]: Invalid &hs[j]: %s != %s\n", (char *)r, test[i], is); + ck_error("ERROR [%u]: Invalid &hs[j]: %s != %s\n", is, test[i], (char *)r); } + + /* Attempt in-place mutation. */ + if (ck_hs_apply(&hs[j], h, test[i], test_ip, (void *)test[i]) == false) + ck_error("ERROR [%u]: Failed to apply: %s != %s\n", is, (char *)r, test[i]); + + d = ck_hs_get(&hs[j], h, test[i]) != NULL; + if (d == false) + ck_error("ERROR [%u]: Expected [%s] to exist.\n", is, test[i]); } if (j == size - 1)