blob: 91dfe3917568529f0ecb412749fbc596fa3a9597 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "packet_nub.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_timer.h"
using testing::_;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::SaveArg;
using testing::StrictMock;
namespace overnet {
namespace packet_nub_test {
using FakeAddress = uint32_t;
class MockPacketNub : public PacketNub<FakeAddress, 1024> {
public:
MockPacketNub(Timer* timer, NodeId node)
: PacketNub<FakeAddress, 1024>(timer, node), router_(timer, node, true) {}
MOCK_METHOD2(SendTo, void(FakeAddress, Slice));
MOCK_METHOD1(PublishMock, void(std::shared_ptr<overnet::Link>));
void Publish(std::unique_ptr<overnet::Link> link) override final {
PublishMock(std::shared_ptr<overnet::Link>(link.release()));
}
Router* GetRouter() override final { return &router_; }
private:
Router router_;
};
TEST(PacketNub, NoOp) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(1));
}
TEST(PacketNub, InitiateBiggerNodeId) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(1));
const auto kHello =
Slice::WithInitializer(MockPacketNub::kHelloSize, [](uint8_t* p) {
// Hello packet with the local node id
memset(p, 0, MockPacketNub::kHelloSize);
static const uint8_t prefix[] = {2, 1, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kHelloSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
});
EXPECT_CALL(nub, SendTo(123, kHello));
nub.Initiate(123, NodeId(2));
int remaining = 4;
EXPECT_CALL(nub, SendTo(123, kHello))
.Times(remaining)
.WillRepeatedly(InvokeWithoutArgs([&remaining]() { remaining--; }));
for (int i = 0; i < 100 && remaining > 0; i++) {
EXPECT_TRUE(timer.StepUntilNextEvent());
}
}
TEST(PacketNub, InitiateSmallerNodeId) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(2));
const auto kAnnounce =
Slice::WithInitializer(MockPacketNub::kCallMeMaybeSize, [](uint8_t* p) {
// Announce packet with the local node id
memset(p, 0, MockPacketNub::kCallMeMaybeSize);
static const uint8_t prefix[] = {1, 2, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kCallMeMaybeSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
});
EXPECT_CALL(nub, SendTo(123, kAnnounce));
nub.Initiate(123, NodeId(1));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
int remaining = 4;
EXPECT_CALL(nub, SendTo(123, kAnnounce))
.Times(remaining)
.WillRepeatedly(InvokeWithoutArgs([&remaining]() { remaining--; }));
for (int i = 0; i < 100 && remaining > 0; i++) {
EXPECT_TRUE(timer.StepUntilNextEvent());
}
}
TEST(PacketNub, ProcessHandshakeFromAnnounce) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(1));
EXPECT_CALL(
nub,
SendTo(123,
Slice::WithInitializer(MockPacketNub::kHelloSize, [](uint8_t* p) {
// Hello packet with the local node id
memset(p, 0, MockPacketNub::kHelloSize);
static const uint8_t prefix[] = {2, 1, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kHelloSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
})));
nub.Process(
timer.Now(), 123,
Slice::WithInitializer(MockPacketNub::kCallMeMaybeSize, [](uint8_t* p) {
// Announce packet with the local node id
memset(p, 0, MockPacketNub::kCallMeMaybeSize);
static const uint8_t prefix[] = {1, 2, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kCallMeMaybeSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
}));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
EXPECT_CALL(nub,
SendTo(123, Slice::FromContainer({0}) /* Connected packet */));
EXPECT_CALL(nub, PublishMock(_));
nub.Process(timer.Now(), 123,
Slice::FromContainer({3}) /* HelloAck packet */);
}
TEST(PacketNub, ProcessHandshakeFromHello) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(2));
EXPECT_CALL(nub,
SendTo(123, Slice::FromContainer({3} /* HelloAck packet */)));
nub.Process(timer.Now(), 123,
Slice::WithInitializer(MockPacketNub::kHelloSize, [](uint8_t* p) {
// Announce packet with the local node id
memset(p, 0, MockPacketNub::kHelloSize);
static const uint8_t prefix[] = {2, 1, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kHelloSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
}));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
EXPECT_CALL(nub, PublishMock(_));
nub.Process(timer.Now(), 123,
Slice::FromContainer({0}) /* Connected packet */);
}
TEST(PacketNub, ProcessHandshakeFromAnnounceAndVerifyLink) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(1));
EXPECT_CALL(
nub,
SendTo(123,
Slice::WithInitializer(MockPacketNub::kHelloSize, [](uint8_t* p) {
// Hello packet with the local node id
memset(p, 0, MockPacketNub::kHelloSize);
static const uint8_t prefix[] = {2, 1, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kHelloSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
})));
nub.Process(
timer.Now(), 123,
Slice::WithInitializer(MockPacketNub::kCallMeMaybeSize, [](uint8_t* p) {
// Announce packet with the local node id
memset(p, 0, MockPacketNub::kCallMeMaybeSize);
static const uint8_t prefix[] = {1, 2, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kCallMeMaybeSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
}));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
EXPECT_CALL(nub,
SendTo(123, Slice::FromContainer({0}) /* Connected packet */));
std::shared_ptr<Link> link;
EXPECT_CALL(nub, PublishMock(_)).WillOnce(SaveArg<0>(&link));
nub.Process(timer.Now(), 123,
Slice::FromContainer({3}) /* HelloAck packet */);
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
EXPECT_EQ(NodeId(1), link->GetLinkMetrics().from());
EXPECT_EQ(NodeId(2), link->GetLinkMetrics().to());
}
TEST(PacketNub, ProcessHandshakeFromHelloAndVerifyLink) {
TestTimer timer;
StrictMock<MockPacketNub> nub(&timer, NodeId(2));
EXPECT_CALL(nub,
SendTo(123, Slice::FromContainer({3} /* HelloAck packet */)));
nub.Process(timer.Now(), 123,
Slice::WithInitializer(MockPacketNub::kHelloSize, [](uint8_t* p) {
// Announce packet with the local node id
memset(p, 0, MockPacketNub::kHelloSize);
static const uint8_t prefix[] = {2, 1, 0, 0, 0, 0, 0, 0, 0};
static_assert(sizeof(prefix) <= MockPacketNub::kHelloSize,
"PacketNub::kHelloSize too small");
memcpy(p, prefix, sizeof(prefix));
}));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
std::shared_ptr<Link> link;
EXPECT_CALL(nub, PublishMock(_)).WillOnce(SaveArg<0>(&link));
EXPECT_CALL(nub,
SendTo(123, Slice::FromContainer({0}) /* Connected packet */));
nub.Process(timer.Now(), 123,
Slice::FromContainer({0}) /* Connected packet */);
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&nub));
EXPECT_EQ(NodeId(2), link->GetLinkMetrics().from());
EXPECT_EQ(NodeId(1), link->GetLinkMetrics().to());
}
} // namespace packet_nub_test
} // namespace overnet