blob: bfde81f9de63261826fcd9ef280086da91de4dd7 [file] [log] [blame]
// Copyright 2019 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 "src/connectivity/overnet/lib/links/stream_link.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/connectivity/overnet/lib/environment/trace_cout.h"
#include "src/connectivity/overnet/lib/testing/flags.h"
#include "src/connectivity/overnet/lib/testing/test_timer.h"
using testing::_;
using testing::Mock;
using testing::Property;
using testing::SaveArg;
using testing::StrictMock;
namespace overnet {
namespace stream_link_test {
constexpr auto kTestMSS = 2048;
class MockStreamHandler : public Router::StreamHandler {
public:
MOCK_METHOD3(HandleMessage, void(SeqNum, TimeStamp, Slice));
void RouterClose(Callback<void> quiesced) override {}
};
class MockStreamLink {
public:
MOCK_METHOD2(Emit, void(Slice, std::function<void(Status)>));
LinkPtr<StreamLink> MakeLink(Router* router, NodeId peer, uint32_t mss) {
static uint64_t next_label = 1;
class PacketLinkImpl final : public StreamLink {
public:
PacketLinkImpl(MockStreamLink* mock, Router* router, NodeId peer,
uint32_t mss)
: StreamLink(router, peer, mss, next_label++), mock_(mock) {}
void Emit(Slice packet, Callback<Status> done) {
auto cb = std::make_shared<Callback<Status>>(std::move(done));
mock_->Emit(std::move(packet),
[cb](const Status& status) { (*cb)(status); });
}
private:
MockStreamLink* mock_;
};
return overnet::MakeLink<PacketLinkImpl>(this, router, peer, mss);
}
};
class TestEnvironment {
public:
TestTimer* timer() { return &timer_; }
private:
TestTimer timer_;
TraceCout renderer_{&timer_};
ScopedRenderer scoped_renderer{&renderer_};
ScopedSeverity scoped_severity_{FLAGS_verbose ? Severity::DEBUG
: Severity::INFO};
};
TEST(StreamLink, NoOp) {
TestEnvironment env;
StrictMock<MockStreamLink> mock_link;
Router router(env.timer(), NodeId(1), true);
router.RegisterLink(mock_link.MakeLink(&router, NodeId(2), kTestMSS));
}
TEST(StreamLink, SendOne) {
TestEnvironment env;
StrictMock<MockStreamLink> mock_link;
auto verify_all = [&]() {
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_link));
};
Router router(env.timer(), NodeId(1), true);
router.RegisterLink(mock_link.MakeLink(&router, NodeId(2), kTestMSS));
while (!router.HasRouteTo(NodeId(2))) {
router.BlockUntilNoBackgroundUpdatesProcessing();
env.timer()->StepUntilNextEvent();
}
Slice emitted;
std::function<void(Status)> done_emit;
EXPECT_CALL(mock_link, Emit(_, _))
.WillOnce(DoAll(SaveArg<0>(&emitted), SaveArg<1>(&done_emit)));
router.Forward(Message{
std::move(RoutableMessage(NodeId(1)).AddDestination(
NodeId(2), StreamId(1), SeqNum(1, 1))),
ForwardingPayloadFactory(Slice::FromContainer({7, 8, 9})),
env.timer()->Now(),
});
verify_all();
done_emit(Status::Ok());
EXPECT_EQ(Slice::FromContainer({6, 0, 1, 1, 7, 8, 9}), emitted);
}
TEST(StreamLink, RecvOne) {
TestEnvironment env;
StrictMock<MockStreamLink> mock_link;
StrictMock<MockStreamHandler> mock_stream_handler;
Router router(env.timer(), NodeId(2), true);
auto link_unique = mock_link.MakeLink(&router, NodeId(1), kTestMSS);
auto* link = link_unique.get();
router.RegisterLink(std::move(link_unique));
while (!router.HasRouteTo(NodeId(2))) {
router.BlockUntilNoBackgroundUpdatesProcessing();
env.timer()->StepUntilNextEvent();
}
EXPECT_TRUE(
router.RegisterStream(NodeId(1), StreamId(1), &mock_stream_handler)
.is_ok());
EXPECT_CALL(mock_stream_handler, HandleMessage(_, _, _));
link->Process(env.timer()->Now(),
Slice::FromContainer({6, 0, 1, 1, 7, 8, 9}));
}
} // namespace stream_link_test
} // namespace overnet