2019-01-22 23:50:26 +00:00
|
|
|
#include <dht/tx.hpp>
|
2019-02-11 17:14:43 +00:00
|
|
|
#include <service/tag.hpp>
|
2019-01-22 23:50:26 +00:00
|
|
|
#include <test_util.hpp>
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <gmock/gmock.h>
|
|
|
|
|
|
|
|
using namespace llarp;
|
|
|
|
using namespace ::testing;
|
|
|
|
|
|
|
|
using llarp::test::makeBuf;
|
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
using Val_t = llarp::service::Tag;
|
|
|
|
|
2019-01-22 23:50:26 +00:00
|
|
|
// Mock implementation of TX.
|
2019-02-11 17:14:43 +00:00
|
|
|
struct TestTx final : public dht::TX< dht::Key_t, Val_t >
|
2019-01-22 23:50:26 +00:00
|
|
|
{
|
|
|
|
TestTx(const dht::TXOwner& asker, const dht::Key_t& k,
|
|
|
|
dht::AbstractContext* p)
|
2019-02-11 17:14:43 +00:00
|
|
|
: dht::TX< dht::Key_t, Val_t >(asker, k, p)
|
2019-01-22 23:50:26 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
MOCK_CONST_METHOD1(Validate, bool(const Val_t&));
|
2019-01-22 23:50:26 +00:00
|
|
|
|
|
|
|
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);
|
2019-02-11 17:14:43 +00:00
|
|
|
Val_t val("good value");
|
2019-01-22 23:50:26 +00:00
|
|
|
|
|
|
|
// 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);
|
2019-02-11 17:14:43 +00:00
|
|
|
Val_t badVal("bad value");
|
2019-01-22 23:50:26 +00:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
}
|