From 5cecdd7dbac1f5ea07116204de693fe5a3893123 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 23 Dec 2024 09:19:07 +1030 Subject: [PATCH] common: add test for htable churn. I wanted to make sure we didn't have a bug in our htable routine, so I wrote this test. We don't, but leave it in. Signed-off-by: Rusty Russell --- common/test/Makefile | 4 + common/test/run-htable.c | 194 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 common/test/run-htable.c diff --git a/common/test/Makefile b/common/test/Makefile index d251eaa76..2775efeb2 100644 --- a/common/test/Makefile +++ b/common/test/Makefile @@ -121,4 +121,8 @@ common/test/run-trace: \ common/trace.o \ wire/fromwire.o \ wire/towire.o + +common/test/run-htable: \ + common/pseudorand.o + check-units: $(COMMON_TEST_PROGRAMS:%=unittest/%) diff --git a/common/test/run-htable.c b/common/test/run-htable.c new file mode 100644 index 000000000..e3f0d8476 --- /dev/null +++ b/common/test/run-htable.c @@ -0,0 +1,194 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } +/* Generated stub for amount_feerate */ + bool amount_feerate(u32 *feerate UNNEEDED, struct amount_sat fee UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_feerate called!\n"); abort(); } +/* Generated stub for amount_sat */ +struct amount_sat amount_sat(u64 satoshis UNNEEDED) +{ fprintf(stderr, "amount_sat called!\n"); abort(); } +/* Generated stub for amount_sat_add */ + bool amount_sat_add(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_add called!\n"); abort(); } +/* Generated stub for amount_sat_eq */ +bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } +/* Generated stub for amount_sat_sub */ + bool amount_sat_sub(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } +/* Generated stub for fromwire */ +const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) +{ fprintf(stderr, "fromwire called!\n"); abort(); } +/* Generated stub for fromwire_bool */ +bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bool called!\n"); abort(); } +/* Generated stub for fromwire_fail */ +void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_fail called!\n"); abort(); } +/* Generated stub for fromwire_secp256k1_ecdsa_signature */ +void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for fromwire_sha256 */ +void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); } +/* Generated stub for fromwire_tal_arrn */ +u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED, + const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); } +/* Generated stub for fromwire_u32 */ +u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); } +/* Generated stub for fromwire_u64 */ +u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); } +/* Generated stub for fromwire_u8 */ +u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); } +/* Generated stub for fromwire_u8_array */ +void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); } +/* Generated stub for towire */ +void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) +{ fprintf(stderr, "towire called!\n"); abort(); } +/* Generated stub for towire_bool */ +void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) +{ fprintf(stderr, "towire_bool called!\n"); abort(); } +/* Generated stub for towire_secp256k1_ecdsa_signature */ +void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED, + const secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for towire_sha256 */ +void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "towire_sha256 called!\n"); abort(); } +/* Generated stub for towire_u32 */ +void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED) +{ fprintf(stderr, "towire_u32 called!\n"); abort(); } +/* Generated stub for towire_u64 */ +void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED) +{ fprintf(stderr, "towire_u64 called!\n"); abort(); } +/* Generated stub for towire_u8 */ +void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED) +{ fprintf(stderr, "towire_u8 called!\n"); abort(); } +/* Generated stub for towire_u8_array */ +void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "towire_u8_array called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +struct example { + u32 val; + u32 val2; + struct example *ptr; +}; + +static struct siphash_seed seed; + +static u64 example_key(const struct example *e) +{ + return (u64)e->val << 32 | e->val2; +} +static bool example_eq_key(const struct example *e, u64 key) +{ + return example_key(e) == key ; +} +static size_t example_key_hash(u64 key) +{ + return siphash24(&seed, &key, sizeof(key)); +} +HTABLE_DEFINE_TYPE(struct example, example_key, example_key_hash, example_eq_key, + example_htable); + +static struct example *new_example(const tal_t *ctx, size_t i) +{ + struct example *e = tal(ctx, struct example); + e->val = i; + e->val2 = siphash24(&seed, &i, sizeof(i)); + return e; +} + +static void check_htable(struct example_htable *htable, + struct example *arr[], + size_t num_arr) +{ + for (size_t i = 0; i < num_arr; i++) { + if (arr[i]) + assert(example_htable_get(htable, example_key(arr[i])) == arr[i]); + } +} + +int main(int argc, char *argv[]) +{ + struct example *arr[3500]; + struct example_htable *htable; + size_t i; + + common_setup(argv[0]); + + seed = *siphash_seed(); + if (argc > 1) + seed.u.u64[0] = atoll(argv[1]); + if (argc > 2) + seed.u.u64[1] = atoll(argv[2]); + + printf("Seed = %"PRIu64"/%"PRIu64"\n", + seed.u.u64[0], seed.u.u64[1]); + + + /* Randomly add or delete, check itegrity */ + i = 0; + while (i < 10000) { + htable = tal(tmpctx, struct example_htable); + example_htable_init(htable); + memset(arr, 0, sizeof(arr)); + check_htable(htable, arr, ARRAY_SIZE(arr)); + + while (example_htable_count(htable) < 900) { + size_t rand = siphash24(&seed, &i, sizeof(i)) % ARRAY_SIZE(arr); + if (arr[rand]) { + example_htable_del(htable, arr[rand]); + arr[rand] = NULL; + } else { + arr[rand] = new_example(htable, rand); + example_htable_add(htable, arr[rand]); + } + check_htable(htable, arr, ARRAY_SIZE(arr)); + i++; + } + printf("%zu - %zu\n", i, example_htable_count(htable)); + htable_check(&htable->raw, "check"); + } + common_shutdown(); + return 0; +}