xref: /aosp_15_r20/external/pigweed/pw_router/static_router_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_router/static_router.h"
16 
17 #include "pw_assert/check.h"
18 #include "pw_router/egress_function.h"
19 #include "pw_unit_test/framework.h"
20 
21 namespace pw::router {
22 namespace {
23 
24 struct BasicPacket {
25   static constexpr uint32_t kMagic = 0x8badf00d;
26 
BasicPacketpw::router::__anone2f307ac0111::BasicPacket27   constexpr BasicPacket(uint32_t addr, uint64_t data)
28       : magic(kMagic), address(addr), priority(0), payload(data) {}
29 
BasicPacketpw::router::__anone2f307ac0111::BasicPacket30   constexpr BasicPacket(uint32_t addr, uint32_t prio, uint64_t data)
31       : magic(kMagic), address(addr), priority(prio), payload(data) {}
32 
datapw::router::__anone2f307ac0111::BasicPacket33   ConstByteSpan data() const { return as_bytes(span(this, 1)); }
34 
35   uint32_t magic;
36   uint32_t address;
37   uint32_t priority;
38   uint64_t payload;
39 };
40 
41 class BasicPacketParser : public PacketParser {
42  public:
BasicPacketParser()43   constexpr BasicPacketParser() : packet_(nullptr) {}
44 
Parse(pw::ConstByteSpan packet)45   bool Parse(pw::ConstByteSpan packet) final {
46     packet_ = reinterpret_cast<const BasicPacket*>(packet.data());
47     return packet_->magic == BasicPacket::kMagic;
48   }
49 
GetDestinationAddress() const50   std::optional<uint32_t> GetDestinationAddress() const final {
51     PW_DCHECK_NOTNULL(packet_);
52     return packet_->address;
53   }
54 
priority() const55   uint32_t priority() const {
56     PW_DCHECK_NOTNULL(packet_);
57     return packet_->priority;
58   }
59 
60  private:
61   const BasicPacket* packet_;
62 };
63 
__anone2f307ac0202(ConstByteSpan, const PacketParser&) 64 EgressFunction GoodEgress(+[](ConstByteSpan, const PacketParser&) {
65   return OkStatus();
66 });
__anone2f307ac0302(ConstByteSpan, const PacketParser&) 67 EgressFunction BadEgress(+[](ConstByteSpan, const PacketParser&) {
68   return Status::ResourceExhausted();
69 });
70 
TEST(StaticRouter,RoutePacket_RoutesToAnEgress)71 TEST(StaticRouter, RoutePacket_RoutesToAnEgress) {
72   BasicPacketParser parser;
73   constexpr StaticRouter::Route routes[] = {{1, GoodEgress}, {2, BadEgress}};
74   StaticRouter router(routes);
75 
76   EXPECT_EQ(router.RoutePacket(BasicPacket(1, 0xdddd).data(), parser),
77             OkStatus());
78   EXPECT_EQ(router.RoutePacket(BasicPacket(2, 0xdddd).data(), parser),
79             Status::Unavailable());
80 }
81 
TEST(StaticRouter,RoutePacket_ForwardsPacketParser)82 TEST(StaticRouter, RoutePacket_ForwardsPacketParser) {
83   uint32_t parser_priority = 0xffffffff;
84 
85   EgressFunction parser_egress(
86       [&parser_priority](ConstByteSpan, const PacketParser& parser) {
87         const BasicPacketParser& basic_parser =
88             static_cast<const BasicPacketParser&>(parser);
89         parser_priority = basic_parser.priority();
90         return OkStatus();
91       });
92 
93   StaticRouter::Route routes[] = {{1, parser_egress}};
94   StaticRouter router(routes);
95   BasicPacketParser parser;
96 
97   EXPECT_EQ(router.RoutePacket(BasicPacket(1, 71, 0xdddd).data(), parser),
98             OkStatus());
99   EXPECT_EQ(parser_priority, 71u);
100 }
101 
TEST(StaticRouter,RoutePacket_ReturnsParserError)102 TEST(StaticRouter, RoutePacket_ReturnsParserError) {
103   BasicPacketParser parser;
104   constexpr StaticRouter::Route routes[] = {{1, GoodEgress}, {2, BadEgress}};
105   StaticRouter router(routes);
106 
107   BasicPacket bad_magic(1, 0xdddd);
108   bad_magic.magic = 0x1badda7a;
109   EXPECT_EQ(router.RoutePacket(bad_magic.data(), parser), Status::DataLoss());
110 }
111 
TEST(StaticRouter,RoutePacket_ReturnsNotFoundOnInvalidRoute)112 TEST(StaticRouter, RoutePacket_ReturnsNotFoundOnInvalidRoute) {
113   BasicPacketParser parser;
114   constexpr StaticRouter::Route routes[] = {{1, GoodEgress}, {2, BadEgress}};
115   StaticRouter router(routes);
116 
117   EXPECT_EQ(router.RoutePacket(BasicPacket(42, 0xdddd).data(), parser),
118             Status::NotFound());
119 }
120 
TEST(StaticRouter,RoutePacket_TracksNumberOfDrops)121 TEST(StaticRouter, RoutePacket_TracksNumberOfDrops) {
122   BasicPacketParser parser;
123   constexpr StaticRouter::Route routes[] = {{1, GoodEgress}, {2, BadEgress}};
124   StaticRouter router(routes);
125 
126   // Good
127   EXPECT_EQ(router.RoutePacket(BasicPacket(1, 0xdddd).data(), parser),
128             OkStatus());
129 
130   // Egress error
131   EXPECT_EQ(router.RoutePacket(BasicPacket(2, 0xdddd).data(), parser),
132             Status::Unavailable());
133 
134   // Parser error
135   BasicPacket bad_magic(1, 0xdddd);
136   bad_magic.magic = 0x1badda7a;
137   EXPECT_EQ(router.RoutePacket(bad_magic.data(), parser), Status::DataLoss());
138 
139   // Good
140   EXPECT_EQ(router.RoutePacket(BasicPacket(1, 0xdddd).data(), parser),
141             OkStatus());
142 
143   // Bad route
144   EXPECT_EQ(router.RoutePacket(BasicPacket(42, 0xdddd).data(), parser),
145             Status::NotFound());
146 
147   EXPECT_EQ(router.dropped_packets(), 3u);
148 }
149 
150 }  // namespace
151 }  // namespace pw::router
152