commit 80d6f2920e28ccbc8dc0eb767bf22b4ae9ad0123
parent beb3a5fe1526d58b92596fec235c4c41e2698850
Author: David Goulet <dgoulet@torproject.org>
Date: Wed, 18 Dec 2024 11:28:59 -0500
test: Add HS cache OOM cleanup test
Part of #40996
Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat:
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c
@@ -68,7 +68,7 @@ store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
}
/** Query our cache and return the entry or NULL if not found. */
-static hs_cache_dir_descriptor_t *
+STATIC hs_cache_dir_descriptor_t *
lookup_v3_desc_as_dir(const uint8_t *key)
{
tor_assert(key);
@@ -1258,3 +1258,17 @@ hs_cache_increment_allocation(size_t n)
}
}
}
+
+#ifdef TOR_UNIT_TESTS
+
+/** Test only: Set the downloaded counter value of a HSDir cache entry. */
+void
+dir_set_downloaded(const ed25519_public_key_t *pk, uint64_t value)
+{
+ hs_cache_dir_descriptor_t *entry = lookup_v3_desc_as_dir(pk->pubkey);
+ if (entry) {
+ entry->n_downloaded = value;
+ }
+}
+
+#endif /* TOR_UNIT_TESTS */
diff --git a/src/feature/hs/hs_cache.h b/src/feature/hs/hs_cache.h
@@ -153,10 +153,15 @@ STATIC size_t cache_clean_v3_as_dir(time_t now, time_t global_cutoff);
STATIC size_t cache_clean_v3_by_downloaded_as_dir(const uint64_t target,
const size_t min_remove_bytes,
uint64_t *next_lowest);
+STATIC hs_cache_dir_descriptor_t *lookup_v3_desc_as_dir(const uint8_t *key);
STATIC hs_cache_client_descriptor_t *
lookup_v3_desc_as_client(const uint8_t *key);
+#ifdef TOR_UNIT_TESTS
+void dir_set_downloaded(const ed25519_public_key_t *pk, uint64_t value);
+#endif /* TOR_UNIT_TESTS */
+
#endif /* defined(HS_CACHE_PRIVATE) */
#endif /* !defined(TOR_HS_CACHE_H) */
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
@@ -224,6 +224,61 @@ test_clean_as_dir(void *arg)
tor_free(desc1_str);
}
+static void
+test_clean_oom_as_dir(void *arg)
+{
+ size_t ret;
+ char *desc1_str = NULL, *desc2_str = NULL;
+ hs_descriptor_t *desc1 = NULL, *desc2 = NULL;
+ ed25519_keypair_t signing_kp1, signing_kp2;
+
+ (void) arg;
+
+ init_test();
+
+ /* Generate two valid descriptors. */
+ ret = ed25519_keypair_generate(&signing_kp1, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = ed25519_keypair_generate(&signing_kp2, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1);
+ tt_assert(desc1);
+ desc2 = hs_helper_build_hs_desc_with_ip(&signing_kp2);
+ tt_assert(desc2);
+ ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_cache_store_as_dir(desc1_str);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_desc_encode_descriptor(desc2, &signing_kp2, NULL, &desc2_str);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_cache_store_as_dir(desc2_str);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Set the downloaded count to 42 for the second one. */
+ dir_set_downloaded(&desc2->plaintext_data.blinded_pubkey, 42);
+ const hs_cache_dir_descriptor_t *entry =
+ lookup_v3_desc_as_dir(desc2->plaintext_data.blinded_pubkey.pubkey);
+ tt_u64_op(entry->n_downloaded, OP_EQ, 42);
+
+ /* Spin the OOM cleanup for only 1 descriptor (very low amount of bytes). We
+ * expect desc1 to be cleaned up because its downloaded counter is 0. */
+ size_t removed = hs_cache_handle_oom(1);
+ tt_size_op(removed, OP_GT, 0);
+
+ /* Desc1 is gone. */
+ entry = lookup_v3_desc_as_dir(desc1->plaintext_data.blinded_pubkey.pubkey);
+ tt_assert(!entry);
+ /* Desc2 is still there. */
+ entry = lookup_v3_desc_as_dir(desc2->plaintext_data.blinded_pubkey.pubkey);
+ tt_assert(entry);
+
+ done:
+ hs_descriptor_free(desc1);
+ hs_descriptor_free(desc2);
+ tor_free(desc1_str);
+ tor_free(desc2_str);
+}
+
/* Test helper: Fetch an HS descriptor from an HSDir (for the hidden service
with <b>blinded_key</b>. Return the received descriptor string. */
static char *
@@ -705,6 +760,8 @@ struct testcase_t hs_cache[] = {
NULL, NULL },
{ "clean_as_dir", test_clean_as_dir, TT_FORK,
NULL, NULL },
+ { "clean_oom_as_dir", test_clean_oom_as_dir, TT_FORK,
+ NULL, NULL },
{ "hsdir_revision_counter_check", test_hsdir_revision_counter_check, TT_FORK,
NULL, NULL },
{ "upload_and_download_hs_desc", test_upload_and_download_hs_desc, TT_FORK,