From d14759eadffd91c7bbe7609cc9f336460be1027c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrille=20B=C3=A9raud?= Date: Sat, 26 Sep 2026 13:03:40 -0400 Subject: [PATCH] tests: cover values missed by a failed push subscription A push subscription that fails (typically while the device has no network) is retried by restartListeners() on the next connectivity change. The values stored on the key meanwhile were never received, so the retry must ask the proxy for them, i.e. not be sent as a refresh. Co-authored-by: Copilot (Claude Opus 5.5) <223556219+Copilot@users.noreply.github.com> --- tests/test_dhtproxy_client.cpp | 44 ++++++++++++++++++++++++++++++++++ tests/test_dhtproxy_client.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/tests/test_dhtproxy_client.cpp b/tests/test_dhtproxy_client.cpp index bbbac899..c5500c87 100644 --- a/tests/test_dhtproxy_client.cpp +++ b/tests/test_dhtproxy_client.cpp @@ -90,4 +90,48 @@ DhtProxyClientTester::testSetPushNotificationTokenResubscribesWithNewToken() #endif } +void +DhtProxyClientTester::testRestartListenersFetchesValuesAfterFailedSubscribe() +{ +#ifdef OPENDHT_PUSH_NOTIFICATIONS + DhtProxyClient client({}, {}, [] {}, "http://127.0.0.1:8080", "OpenDHT-Test", "client-id", "push-token"); + + auto addListener = [&](const InfoHash& key, bool ok) -> DhtProxyClient::Listener& { + auto& search = client.searches_[key]; + auto [it, inserted] = search.listeners.emplace(std::piecewise_construct, + std::forward_as_tuple(1), + std::forward_as_tuple(ValueCallback( + [](const std::vector>&, bool) { return true; }))); + CPPUNIT_ASSERT(inserted); + auto& listener = it->second; + listener.opstate = std::make_shared(); + listener.opstate->ok = ok; + listener.cb = [](const std::vector>&, bool, system_clock::time_point) { + return true; + }; + return listener; + }; + + // The subscription of this listener failed (e.g. no network): values stored on the + // key since then were never received. + auto failedKey = InfoHash::get("proxy-client-failed-subscribe"); + auto& failed = addListener(failedKey, false); + auto healthyKey = InfoHash::get("proxy-client-healthy-subscribe"); + auto& healthy = addListener(healthyKey, true); + + client.restartListeners({}); + + CPPUNIT_ASSERT(failed.request); + CPPUNIT_ASSERT_EQUAL(std::string("/key/") + failedKey.toString(), + std::string(failed.request->header_.request_target())); + CPPUNIT_ASSERT(failed.request->body_.find("push-token") != std::string::npos); + // Without "refresh", the server answers with the values it stores for the key. + CPPUNIT_ASSERT(failed.request->body_.find("\"refresh\"") == std::string::npos); + + CPPUNIT_ASSERT(!healthy.request); +#else + CPPUNIT_ASSERT(true); +#endif +} + } // namespace test \ No newline at end of file diff --git a/tests/test_dhtproxy_client.h b/tests/test_dhtproxy_client.h index 73d1928c..ddbbd608 100644 --- a/tests/test_dhtproxy_client.h +++ b/tests/test_dhtproxy_client.h @@ -12,11 +12,13 @@ class DhtProxyClientTester : public CppUnit::TestFixture CPPUNIT_TEST_SUITE(DhtProxyClientTester); CPPUNIT_TEST(testResubscribeUsesKeyRoute); CPPUNIT_TEST(testSetPushNotificationTokenResubscribesWithNewToken); + CPPUNIT_TEST(testRestartListenersFetchesValuesAfterFailedSubscribe); CPPUNIT_TEST_SUITE_END(); public: void testResubscribeUsesKeyRoute(); void testSetPushNotificationTokenResubscribesWithNewToken(); + void testRestartListenersFetchesValuesAfterFailedSubscribe(); }; } // namespace test \ No newline at end of file