diff options
author | buttercat1791 <mjjurkoic@gmail.com> | 2024-05-07 09:07:25 -0500 |
---|---|---|
committer | buttercat1791 <mjjurkoic@gmail.com> | 2024-05-07 09:07:25 -0500 |
commit | 14ba707c600f13012b3b7f441541f9a6db8ddb8a (patch) | |
tree | be59ac35575f8a6e98e6af4473ba08493469fc38 /test | |
parent | 80885e4f6b83a3a63b9a74640a13a66cc27d7933 (diff) |
Update and test methods for closing subscriptions
Diffstat (limited to 'test')
-rw-r--r-- | test/nostr_service_test.cpp | 195 |
1 files changed, 176 insertions, 19 deletions
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_test.cpp index 460be73..0f0d439 100644 --- a/test/nostr_service_test.cpp +++ b/test/nostr_service_test.cpp @@ -804,6 +804,9 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE) }), signedTestEvents.end()); } + + auto subscriptions = nostrService->subscriptions(); + ASSERT_TRUE(subscriptions.empty()); }; TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents) @@ -907,20 +910,8 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents) // Check that the service is keeping track of its active subscriptions. auto subscriptions = nostrService->subscriptions(); - for (string uri : nostrService->activeRelays()) - { - ASSERT_NO_THROW(subscriptions.at(uri)); - ASSERT_EQ(subscriptions.at(uri).size(), 1); - ASSERT_NE( - find_if( - subscriptions[uri].begin(), - subscriptions[uri].end(), - [&generatedSubscriptionId](const string& subscriptionId) - { - return subscriptionId == generatedSubscriptionId; - }), - subscriptions[uri].end()); - } + ASSERT_NO_THROW(subscriptions.at(generatedSubscriptionId)); + ASSERT_EQ(subscriptions.at(generatedSubscriptionId).size(), 2); EXPECT_CALL(*mockClient, send(HasSubstr("CLOSE"), _)) .Times(2) @@ -929,15 +920,181 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents) return make_tuple(uri, true); })); - nostrService->closeSubscription(generatedSubscriptionId); + auto [successes, failures] = nostrService->closeSubscription(generatedSubscriptionId); + + ASSERT_TRUE(failures.empty()); // Check that the service has forgotten about the subscriptions after closing them. subscriptions = nostrService->subscriptions(); - for (string uri : nostrService->activeRelays()) + ASSERT_TRUE(subscriptions.empty()); +}; + +TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll) +{ + // Mock connections. + mutex connectionStatusMutex; + auto connectionStatus = make_shared<unordered_map<string, bool>>(); + vector<string> testRelays = { "wss://theforest.nostr1.com" }; + connectionStatus->insert({ testRelays[0], false }); + + EXPECT_CALL(*mockClient, isConnected(_)) + .WillRepeatedly(Invoke([connectionStatus, &connectionStatusMutex](string uri) + { + lock_guard<mutex> lock(connectionStatusMutex); + bool status = connectionStatus->at(uri); + if (status == false) + { + connectionStatus->at(uri) = true; + } + return status; + })); + + auto signer = make_unique<FakeSigner>(); + auto nostrService = make_unique<nostr::NostrService>( + testAppender, + mockClient, + fakeSigner, + testRelays); + nostrService->openRelayConnections(); + + // Mock relay responses. + auto testEvents = getMultipleTextNoteTestEvents(); + vector<shared_ptr<nostr::Event>> signedTestEvents; + for (nostr::Event testEvent : testEvents) { - ASSERT_EQ(subscriptions.at(uri).size(), 0); + auto signedEvent = make_shared<nostr::Event>(testEvent); + signer->sign(signedEvent); + + auto serializedEvent = signedEvent->serialize(); + auto deserializedEvent = nostr::Event::fromString(serializedEvent); + + signedEvent = make_shared<nostr::Event>(deserializedEvent); + signedTestEvents.push_back(signedEvent); } -}; -// TODO: Add unit tests for closing subscriptions. + vector<string> subscriptionIds; + EXPECT_CALL(*mockClient, send(HasSubstr("REQ"), _, _)) + .Times(2) + .WillOnce(Invoke([&testEvents, &signer, &subscriptionIds]( + string message, + string uri, + function<void(const string&)> messageHandler) + { + json messageArr = json::parse(message); + subscriptionIds.push_back(messageArr.at(1)); + + for (auto event : testEvents) + { + auto sendableEvent = make_shared<nostr::Event>(event); + signer->sign(sendableEvent); + json jarr = json::array({ "EVENT", subscriptionIds.at(0), sendableEvent->serialize() }); + messageHandler(jarr.dump()); + } + + json jarr = json::array({ "EOSE", subscriptionIds.at(0), }); + messageHandler(jarr.dump()); + + return make_tuple(uri, true); + })) + .WillOnce(Invoke([&testEvents, &signer, &subscriptionIds]( + string message, + string uri, + function<void(const string&)> messageHandler) + { + json messageArr = json::parse(message); + subscriptionIds.push_back(messageArr.at(1)); + + for (auto event : testEvents) + { + auto sendableEvent = make_shared<nostr::Event>(event); + signer->sign(sendableEvent); + json jarr = json::array({ "EVENT", subscriptionIds.at(1), sendableEvent->serialize() }); + messageHandler(jarr.dump()); + } + + json jarr = json::array({ "EOSE", subscriptionIds.at(1), }); + messageHandler(jarr.dump()); + + return make_tuple(uri, true); + })); + + // Send queries. + auto shortFormFilters = make_shared<nostr::Filters>(getKind0And1TestFilters()); + auto longFormFilters = make_shared<nostr::Filters>(getKind30023TestFilters()); + promise<void> shortFormPromise; + promise<void> longFormPromise; + auto shortFormFuture = shortFormPromise.get_future(); + auto longFormFuture = longFormPromise.get_future(); + + string shortFormSubscriptionId = nostrService->queryRelays( + shortFormFilters, + [&shortFormSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::Event> event) + { + ASSERT_STREQ(subscriptionId.c_str(), shortFormSubscriptionId.c_str()); + ASSERT_NE( + find_if( + signedTestEvents.begin(), + signedTestEvents.end(), + [&event](shared_ptr<nostr::Event> testEvent) + { + return *testEvent == *event; + }), + signedTestEvents.end()); + }, + [&shortFormSubscriptionId, &shortFormPromise] + (const string& subscriptionId) + { + ASSERT_STREQ(subscriptionId.c_str(), shortFormSubscriptionId.c_str()); + shortFormPromise.set_value(); + }, + [](const string&, const string&) {}); + string longFormSubscriptionId = nostrService->queryRelays( + shortFormFilters, + [&longFormSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::Event> event) + { + ASSERT_STREQ(subscriptionId.c_str(), longFormSubscriptionId.c_str()); + ASSERT_NE( + find_if( + signedTestEvents.begin(), + signedTestEvents.end(), + [&event](shared_ptr<nostr::Event> testEvent) + { + return *testEvent == *event; + }), + signedTestEvents.end()); + }, + [&longFormSubscriptionId, &longFormPromise] + (const string& subscriptionId) + { + ASSERT_STREQ(subscriptionId.c_str(), longFormSubscriptionId.c_str()); + longFormPromise.set_value(); + }, + [](const string&, const string&) {}); + + shortFormFuture.wait(); + longFormFuture.wait(); + + // Check that the service has opened a subscription for each query. + auto subscriptions = nostrService->subscriptions(); + ASSERT_NO_THROW(subscriptions.at(shortFormSubscriptionId)); + ASSERT_EQ(subscriptions.at(shortFormSubscriptionId).size(), 1); + ASSERT_NO_THROW(subscriptions.at(longFormSubscriptionId)); + ASSERT_EQ(subscriptions.at(longFormSubscriptionId).size(), 1); + + // Mock the relay response for closing subscriptions. + EXPECT_CALL(*mockClient, send(HasSubstr("CLOSE"), _)) + .Times(2) + .WillRepeatedly(Invoke([](string message, string uri) + { + return make_tuple(uri, true); + })); + + // Close all subscriptions maintained by the service. + auto remainingSubscriptions = nostrService->closeSubscriptions(); + ASSERT_TRUE(remainingSubscriptions.empty()); + + // Check that all subscriptions have been closed. + subscriptions = nostrService->subscriptions(); + ASSERT_TRUE(subscriptions.empty()); +}; } // namespace nostr_test |