blob: 643994e6de7490d957d71a59b8495722249d8ccd [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 "routing_header.h"
#include "gtest/gtest.h"
namespace overnet {
namespace routing_header_test {
typedef std::vector<uint8_t> BinVec;
template <class T>
BinVec Encode(const T& x) {
auto sz = x.wire_length();
BinVec out;
out.resize(sz);
x.Write(out.data());
return out;
}
template <class T>
BinVec EncodeVarint(const T& x) {
auto sz = x.wire_length();
BinVec out;
out.resize(sz);
x.Write(sz, out.data());
return out;
}
TEST(BaseTypes, NodeId) {
NodeId one(1);
NodeId two(2);
NodeId also_one(1);
EXPECT_EQ(one, also_one);
EXPECT_NE(one, two);
EXPECT_EQ((BinVec{1, 0, 0, 0, 0, 0, 0, 0}), Encode(one));
EXPECT_EQ((BinVec{2, 0, 0, 0, 0, 0, 0, 0}), Encode(two));
}
TEST(BaseTypes, StreamId) {
StreamId one(1);
StreamId two(2);
StreamId also_one(1);
EXPECT_EQ(one, also_one);
EXPECT_NE(one, two);
EXPECT_EQ((BinVec{1}), EncodeVarint(one));
EXPECT_EQ((BinVec{2}), EncodeVarint(two));
}
TEST(BaseTypes, SeqNum) {
SeqNum seq_1_1(1, 1);
EXPECT_EQ(1ull, seq_1_1.Reconstruct(1));
EXPECT_EQ((BinVec{1}), Encode(seq_1_1));
}
static void RoundTrip(const RoutingHeader& rh, NodeId sender, NodeId receiver) {
auto enc = Encode(RoutingHeader::Writer(&rh, sender, receiver));
const uint8_t* start = enc.data();
auto prs_status =
RoutingHeader::Parse(&start, start + enc.size(), receiver, sender);
EXPECT_TRUE(prs_status.is_ok()) << prs_status.AsStatus();
EXPECT_EQ(rh, *prs_status.get());
}
TEST(RoutingHeader, PayloadWrite1) {
auto rh = std::move(
RoutingHeader(NodeId(1), 3, ReliabilityAndOrdering::ReliableUnordered)
.AddDestination(NodeId(2), StreamId(1), SeqNum(1, 10)));
// encode locally
EXPECT_EQ((BinVec{// flags
(1 << 0) | (2 << 2) | (1 << 6),
// dests {
// [0] =
// stream_id
1,
// seqnum
1,
// }
// payload_length
3}),
Encode(RoutingHeader::Writer(&rh, NodeId(1), NodeId(2))));
RoundTrip(rh, NodeId(1), NodeId(2));
}
TEST(RoutingHeader, PayloadWrite2) {
auto rh = std::move(
RoutingHeader(NodeId(1), 3, ReliabilityAndOrdering::ReliableUnordered)
.AddDestination(NodeId(2), StreamId(1), SeqNum(1, 10)));
// encode along a different route
EXPECT_EQ((BinVec{// flags
(2 << 2) | (1 << 6),
// src
1, 0, 0, 0, 0, 0, 0, 0,
// dests {
// [0] =
// node
2, 0, 0, 0, 0, 0, 0, 0,
// stream_id
1,
// seqnum
1,
// }
// payload_length
3}),
Encode(RoutingHeader::Writer(&rh, NodeId(4), NodeId(2))));
RoundTrip(rh, NodeId(4), NodeId(2));
}
TEST(RoutingHeader, PayloadWrite3) {
auto rh = std::move(
RoutingHeader(NodeId(1), 3, ReliabilityAndOrdering::ReliableUnordered)
.AddDestination(NodeId(2), StreamId(1), SeqNum(1, 10))
.AddDestination(NodeId(3), StreamId(42), SeqNum(7, 10)));
EXPECT_EQ((BinVec{// flags
0x88, 0x01,
// src
1, 0, 0, 0, 0, 0, 0, 0,
// dests {
// [0] =
// node
2, 0, 0, 0, 0, 0, 0, 0,
// stream_id
1,
// seqnum
1,
// [1] =
// node
3, 0, 0, 0, 0, 0, 0, 0,
// stream_id
42,
// seqnum
7,
// }
// payload_length
3}),
Encode(RoutingHeader::Writer(&rh, NodeId(1), NodeId(2))));
RoundTrip(rh, NodeId(1), NodeId(2));
}
TEST(RoutingHeader, ControlWrite) {
auto rh =
std::move(RoutingHeader(NodeId(1), 3, RoutingHeader::CONTROL_MESSAGE)
.AddDestination(NodeId(2), StreamId(1), SeqNum(1, 10)));
// encode locally
EXPECT_EQ((BinVec{// flags
(1 << 0) | (1 << 1) | (1 << 6),
// dests {
// [0] =
// stream_id
1,
// seqnum
1,
// }
// payload_length
3}),
Encode(RoutingHeader::Writer(&rh, NodeId(1), NodeId(2))));
RoundTrip(rh, NodeId(1), NodeId(2));
}
} // namespace routing_header_test
} // namespace overnet