mirror of https://github.com/oxen-io/lokinet
More unit tests of dht internals
parent
3f320009d7
commit
1f95f1e78f
@ -0,0 +1 @@
|
||||
#include <dht/mock_context.hpp>
|
@ -0,0 +1,46 @@
|
||||
#ifndef TEST_LLARP_MOCK_CONTEXT
|
||||
#define TEST_LLARP_MOCK_CONTEXT
|
||||
|
||||
#include <dht/context.hpp>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace test
|
||||
{
|
||||
struct MockContext final : public dht::AbstractContext
|
||||
{
|
||||
MOCK_METHOD2(LookupRouter, bool(const RouterID&, RouterLookupHandler));
|
||||
|
||||
MOCK_METHOD6(LookupIntroSetRecursive,
|
||||
void(const service::Address&, const dht::Key_t&, uint64_t,
|
||||
const dht::Key_t&, uint64_t,
|
||||
service::IntroSetLookupHandler));
|
||||
|
||||
MOCK_METHOD5(LookupIntroSetIterative,
|
||||
void(const service::Address&, const dht::Key_t&, uint64_t,
|
||||
const dht::Key_t&, service::IntroSetLookupHandler));
|
||||
|
||||
MOCK_METHOD3(
|
||||
FindRandomIntroSetsWithTagExcluding,
|
||||
std::set< service::IntroSet >(const service::Tag&, size_t,
|
||||
const std::set< service::IntroSet >&));
|
||||
|
||||
MOCK_METHOD3(DHTSendTo, void(const RouterID&, dht::IMessage*, bool));
|
||||
|
||||
MOCK_CONST_METHOD0(Now, llarp_time_t());
|
||||
|
||||
MOCK_CONST_METHOD0(Crypto, llarp::Crypto*());
|
||||
|
||||
MOCK_CONST_METHOD0(GetRouter, llarp::Router*());
|
||||
|
||||
MOCK_CONST_METHOD0(OurKey, const dht::Key_t&());
|
||||
|
||||
MOCK_CONST_METHOD0(Nodes, dht::Bucket< dht::RCNode >*());
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,105 @@
|
||||
#include <dht/explorenetworkjob.hpp>
|
||||
|
||||
#include <dht/messages/findrouter.hpp>
|
||||
#include <dht/mock_context.hpp>
|
||||
#include <test_util.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace llarp;
|
||||
using namespace ::testing;
|
||||
|
||||
using test::makeBuf;
|
||||
|
||||
struct TestDhtExploreNetworkJob : public ::testing::Test
|
||||
{
|
||||
RouterID peer;
|
||||
test::MockContext context;
|
||||
dht::ExploreNetworkJob exploreNetworkJob;
|
||||
|
||||
TestDhtExploreNetworkJob()
|
||||
: peer(makeBuf< RouterID >(0x01)), exploreNetworkJob(peer, &context)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, validate)
|
||||
{
|
||||
const RouterID other = makeBuf< RouterID >(0x02);
|
||||
ASSERT_TRUE(exploreNetworkJob.Validate(other));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, get_next_peer)
|
||||
{
|
||||
dht::Key_t key = makeBuf< dht::Key_t >(0x02);
|
||||
std::set< dht::Key_t > exclude;
|
||||
ASSERT_FALSE(exploreNetworkJob.GetNextPeer(key, exclude));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, do_next)
|
||||
{
|
||||
const dht::Key_t key = makeBuf< dht::Key_t >(0x02);
|
||||
ASSERT_NO_THROW(exploreNetworkJob.DoNextRequest(key));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, start)
|
||||
{
|
||||
// Verify input arguments are passed correctly.
|
||||
// The actual logic is inside the `dht::AbstractContext` implementation.
|
||||
|
||||
const auto txKey = makeBuf< dht::Key_t >(0x02);
|
||||
uint64_t txId = 4;
|
||||
|
||||
dht::TXOwner txOwner(txKey, txId);
|
||||
|
||||
// clang-format off
|
||||
EXPECT_CALL(context, DHTSendTo(
|
||||
Eq(txKey.as_array()),
|
||||
WhenDynamicCastTo< dht::FindRouterMessage* >(NotNull()),
|
||||
true)
|
||||
).Times(1);
|
||||
// clang-format off
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.Start(txOwner));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, send_reply)
|
||||
{
|
||||
// Concerns:
|
||||
// - Empty collection
|
||||
// - Lookup router fails (returns false)
|
||||
// - Number of calls matches collection size
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
EXPECT_CALL(context, LookupRouter(_, _)).Times(0);
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x00));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x01));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x02));
|
||||
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
EXPECT_CALL(context, LookupRouter(Ne(makeBuf<RouterID>(0x01)), _)).Times(2).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(context, LookupRouter(Eq(makeBuf<RouterID>(0x01)), _)).WillOnce(Return(false));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x00));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x01));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x02));
|
||||
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
EXPECT_CALL(context, LookupRouter(_, _)).Times(3).WillRepeatedly(Return(true));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
#include <dht/tx.hpp>
|
||||
|
||||
#include <test_util.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace llarp;
|
||||
using namespace ::testing;
|
||||
|
||||
using llarp::test::makeBuf;
|
||||
|
||||
// Mock implementation of TX.
|
||||
struct TestTx final : public dht::TX< dht::Key_t, std::string >
|
||||
{
|
||||
TestTx(const dht::TXOwner& asker, const dht::Key_t& k,
|
||||
dht::AbstractContext* p)
|
||||
: dht::TX< dht::Key_t, std::string >(asker, k, p)
|
||||
{
|
||||
}
|
||||
|
||||
MOCK_CONST_METHOD1(Validate, bool(const std::string&));
|
||||
|
||||
MOCK_METHOD1(Start, void(const dht::TXOwner&));
|
||||
|
||||
MOCK_METHOD2(GetNextPeer, bool(dht::Key_t&, const std::set< dht::Key_t >&));
|
||||
|
||||
MOCK_METHOD1(DoNextRequest, void(const dht::Key_t&));
|
||||
|
||||
MOCK_METHOD0(SendReply, void());
|
||||
};
|
||||
|
||||
struct TestDhtTx : public Test
|
||||
{
|
||||
dht::TXOwner asker;
|
||||
dht::Key_t key;
|
||||
TestTx tx;
|
||||
|
||||
TestDhtTx() : tx(asker, key, nullptr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestDhtTx, on_found)
|
||||
{
|
||||
// Concerns
|
||||
// - Validate returns true
|
||||
// - Repeated call on success
|
||||
// - Validate returns false
|
||||
// - Repeated call on failure
|
||||
// - Repeated call on success after failure
|
||||
|
||||
const auto key = makeBuf< dht::Key_t >(0x00);
|
||||
std::string val("good value");
|
||||
|
||||
// Validate returns true
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(val)).WillOnce(Return(true));
|
||||
|
||||
tx.OnFound(key, val);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(val));
|
||||
}
|
||||
|
||||
// Repeated call on success
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(val)).WillOnce(Return(true));
|
||||
tx.OnFound(key, val);
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(val));
|
||||
}
|
||||
|
||||
const auto key1 = makeBuf< dht::Key_t >(0x01);
|
||||
std::string badVal("bad value");
|
||||
|
||||
// Validate returns false
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(false));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Not(Contains(badVal)));
|
||||
}
|
||||
|
||||
// Repeated call on failure
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(false));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Not(Contains(badVal)));
|
||||
}
|
||||
|
||||
// Repeated call on success after failure
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(true));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(badVal));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDhtTx, ask_next_peer)
|
||||
{
|
||||
// Concerns:
|
||||
// - GetNextPeer fails
|
||||
// - Next Peer is not closer
|
||||
// - next ptr is null
|
||||
// - next ptr is not null
|
||||
|
||||
const auto key0 = makeBuf< dht::Key_t >(0x00);
|
||||
const auto key1 = makeBuf< dht::Key_t >(0x01);
|
||||
const auto key2 = makeBuf< dht::Key_t >(0x02);
|
||||
|
||||
{
|
||||
// GetNextPeer fails
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _)).WillOnce(Return(false));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(0);
|
||||
|
||||
ASSERT_FALSE(tx.AskNextPeer(key0, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key0));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// Next Peer is not closer
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _))
|
||||
.WillOnce(DoAll(SetArgReferee< 0 >(key1), Return(true)));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(0);
|
||||
|
||||
ASSERT_FALSE(tx.AskNextPeer(key0, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key0));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// next ptr is null
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _))
|
||||
.WillOnce(DoAll(SetArgReferee< 0 >(key1), Return(true)));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(1);
|
||||
|
||||
ASSERT_TRUE(tx.AskNextPeer(key2, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key2));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// next ptr is not null
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _)).Times(0);
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(1);
|
||||
|
||||
auto ptr = std::make_unique< dht::Key_t >(key1);
|
||||
ASSERT_TRUE(tx.AskNextPeer(key2, ptr));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key2));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue