aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Michael Jurkoic <mjjurkoic@gmail.com>2024-05-03 01:15:38 -0500
committerLibravatar Michael Jurkoic <mjjurkoic@gmail.com>2024-05-03 01:15:38 -0500
commitae458b29b7c5f9124e6cc4499bed60c865d7badd (patch)
treef6d24013a30beaf1b42b3143626082848ba429a9
parent1291f9b045adfea3279cc26531b5d13164ca1bd8 (diff)
Add unit test for queryRelays with callbacks
-rw-r--r--include/nostr.hpp6
-rw-r--r--src/nostr_service.cpp3
-rw-r--r--test/nostr_service_test.cpp105
3 files changed, 108 insertions, 6 deletions
diff --git a/include/nostr.hpp b/include/nostr.hpp
index a59bd33..5e7dbfe 100644
--- a/include/nostr.hpp
+++ b/include/nostr.hpp
@@ -191,8 +191,12 @@ public:
/**
* @brief Queries all open relay connections for events matching the given set of filters.
* @param filters The filters to use for the query.
- * @param responseHandler A callable object that will be invoked each time the client receives
+ * @param eventHandler A callable object that will be invoked each time the client receives
* an event matching the filters.
+ * @param eoseHandler A callable object that will be invoked when the relay sends an EOSE
+ * message.
+ * @param closeHandler A callable object that will be invoked when the relay sends a CLOSE
+ * message.
* @returns The ID of the subscription created for the query.
* @remark By providing a response handler, the caller assumes responsibility for handling all
* events returned from the relay for the given filters. The service will not store the
diff --git a/src/nostr_service.cpp b/src/nostr_service.cpp
index a1adbbb..a1f475c 100644
--- a/src/nostr_service.cpp
+++ b/src/nostr_service.cpp
@@ -273,9 +273,6 @@ string NostrService::queryRelays(
for (const string relay : this->_activeRelays)
{
this->_subscriptions[relay].push_back(subscriptionId);
-
- promise<tuple<string, bool>> requestPromise;
- requestFutures.push_back(move(requestPromise.get_future()));
future<tuple<string, bool>> requestFuture = async(
[this, &relay, &request, &eventHandler, &eoseHandler, &closeHandler]()
{
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_test.cpp
index e80406e..b2f6876 100644
--- a/test/nostr_service_test.cpp
+++ b/test/nostr_service_test.cpp
@@ -16,8 +16,10 @@ using std::lock_guard;
using std::make_shared;
using std::make_unique;
using std::mutex;
+using std::promise;
using std::shared_ptr;
using std::string;
+using std::thread;
using std::tuple;
using std::unordered_map;
using std::vector;
@@ -741,7 +743,6 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
vector<shared_ptr<nostr::Event>> signedTestEvents;
for (nostr::Event testEvent : testEvents)
{
- std::cout << "TEST: Signing event" << std::endl;
auto signedEvent = make_shared<nostr::Event>(testEvent);
signer->sign(signedEvent);
@@ -759,7 +760,6 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
string uri,
function<void(const string&)> messageHandler)
{
- std::cout << "TEST: Sending message: " << message << std::endl;
json messageArr = json::parse(message);
string subscriptionId = messageArr.at(1);
@@ -798,5 +798,106 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
}
};
+TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
+{
+ mutex connectionStatusMutex;
+ auto connectionStatus = make_shared<unordered_map<string, bool>>();
+ connectionStatus->insert({ defaultTestRelays[0], false });
+ connectionStatus->insert({ defaultTestRelays[1], 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,
+ defaultTestRelays);
+ nostrService->openRelayConnections();
+
+ auto testEvents = getMultipleTextNoteTestEvents();
+ vector<shared_ptr<nostr::Event>> signedTestEvents;
+ for (nostr::Event testEvent : testEvents)
+ {
+ 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);
+ }
+
+ EXPECT_CALL(*mockClient, send(_, _, _))
+ .Times(2)
+ .WillRepeatedly(Invoke([&testEvents, &signer](
+ string message,
+ string uri,
+ function<void(const string&)> messageHandler)
+ {
+ json messageArr = json::parse(message);
+ string subscriptionId = messageArr.at(1);
+
+ for (auto event : testEvents)
+ {
+ auto sendableEvent = make_shared<nostr::Event>(event);
+ signer->sign(sendableEvent);
+ json jarr = json::array({ "EVENT", subscriptionId, sendableEvent->serialize() });
+ messageHandler(jarr.dump());
+ }
+
+ json jarr = json::array({ "EOSE", subscriptionId });
+ messageHandler(jarr.dump());
+
+ return make_tuple(uri, true);
+ }));
+
+ auto filters = make_shared<nostr::Filters>(getKind0And1TestFilters());
+ promise<void> eoseReceivedPromise;
+ auto eoseReceivedFuture = eoseReceivedPromise.get_future();
+ int eoseCount = 0;
+
+ string generatedSubscriptionId = nostrService->queryRelays(
+ filters,
+ [&generatedSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::Event> event)
+ {
+ ASSERT_STREQ(subscriptionId.c_str(), generatedSubscriptionId.c_str());
+ ASSERT_NE(
+ find_if(
+ signedTestEvents.begin(),
+ signedTestEvents.end(),
+ [&event](shared_ptr<nostr::Event> testEvent)
+ {
+ return *testEvent == *event;
+ }),
+ signedTestEvents.end());
+ },
+ [&generatedSubscriptionId, &eoseReceivedPromise, &eoseCount]
+ (const string& subscriptionId)
+ {
+ std::cout << "EOSE received for subscription ID: " << subscriptionId << std::endl;
+ ASSERT_STREQ(subscriptionId.c_str(), generatedSubscriptionId.c_str());
+
+ if (++eoseCount == 2)
+ {
+ eoseReceivedPromise.set_value();
+ }
+ },
+ [](const string&, const string&) {});
+
+ eoseReceivedFuture.wait();
+};
+
// TODO: Add unit tests for closing subscriptions.
} // namespace nostr_test