xref: /aosp_15_r20/external/pigweed/pw_rpc/channel_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/channel.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <cstddef>
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/packet.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/test_utils.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
22*61c4878aSAndroid Build Coastguard Worker 
23*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc::internal {
24*61c4878aSAndroid Build Coastguard Worker namespace {
25*61c4878aSAndroid Build Coastguard Worker 
TEST(ChannelOutput,Name)26*61c4878aSAndroid Build Coastguard Worker TEST(ChannelOutput, Name) {
27*61c4878aSAndroid Build Coastguard Worker   class NameTester : public ChannelOutput {
28*61c4878aSAndroid Build Coastguard Worker    public:
29*61c4878aSAndroid Build Coastguard Worker     NameTester(const char* name) : ChannelOutput(name) {}
30*61c4878aSAndroid Build Coastguard Worker     Status Send(span<const std::byte>) override { return OkStatus(); }
31*61c4878aSAndroid Build Coastguard Worker   };
32*61c4878aSAndroid Build Coastguard Worker 
33*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ("hello_world", NameTester("hello_world").name());
34*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, NameTester(nullptr).name());
35*61c4878aSAndroid Build Coastguard Worker }
36*61c4878aSAndroid Build Coastguard Worker 
37*61c4878aSAndroid Build Coastguard Worker constexpr Packet kTestPacket(
38*61c4878aSAndroid Build Coastguard Worker     pwpb::PacketType::RESPONSE, 23, 42, 100, 0, {}, Status::NotFound());
39*61c4878aSAndroid Build Coastguard Worker const size_t kReservedSize = 2 /* type */ + 2 /* channel */ + 5 /* service */ +
40*61c4878aSAndroid Build Coastguard Worker                              5 /* method */ + 2 /* payload key */ +
41*61c4878aSAndroid Build Coastguard Worker                              2 /* status (if not OK) */;
42*61c4878aSAndroid Build Coastguard Worker 
43*61c4878aSAndroid Build Coastguard Worker enum class ChannelId {
44*61c4878aSAndroid Build Coastguard Worker   kOne = 1,
45*61c4878aSAndroid Build Coastguard Worker   kTwo = 2,
46*61c4878aSAndroid Build Coastguard Worker };
47*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,MaxSafePayload)48*61c4878aSAndroid Build Coastguard Worker TEST(Channel, MaxSafePayload) {
49*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kUint32Max = std::numeric_limits<uint32_t>::max();
50*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxPayloadSize = 64;
51*61c4878aSAndroid Build Coastguard Worker 
52*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kTestPayloadSize = MaxSafePayloadSize(kMaxPayloadSize);
53*61c4878aSAndroid Build Coastguard Worker 
54*61c4878aSAndroid Build Coastguard Worker   // Because it's impractical to test a payload that nears the limits of a
55*61c4878aSAndroid Build Coastguard Worker   // uint32 varint, calculate the difference when using a smaller payload.
56*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kPayloadSizeTestLimitations =
57*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(kUint32Max) - varint::EncodedSize(kTestPayloadSize);
58*61c4878aSAndroid Build Coastguard Worker 
59*61c4878aSAndroid Build Coastguard Worker   // The buffer to use for encoding the RPC packet.
60*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kMaxPayloadSize - kPayloadSizeTestLimitations> buffer;
61*61c4878aSAndroid Build Coastguard Worker 
62*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kTestPayloadSize> payload;
63*61c4878aSAndroid Build Coastguard Worker   for (size_t i = 0; i < payload.size(); i++) {
64*61c4878aSAndroid Build Coastguard Worker     payload[i] = std::byte(i % std::numeric_limits<uint8_t>::max());
65*61c4878aSAndroid Build Coastguard Worker   }
66*61c4878aSAndroid Build Coastguard Worker 
67*61c4878aSAndroid Build Coastguard Worker   Packet packet(pwpb::PacketType::SERVER_STREAM,
68*61c4878aSAndroid Build Coastguard Worker                 /*channel_id=*/kUint32Max,  // Varint, needs to be uint32_t max.
69*61c4878aSAndroid Build Coastguard Worker                 /*service_id=*/42,       // Fixed-width. Value doesn't matter.
70*61c4878aSAndroid Build Coastguard Worker                 /*method_id=*/100,       // Fixed-width. Value doesn't matter.
71*61c4878aSAndroid Build Coastguard Worker                 /*call_id=*/kUint32Max,  // Varint, needs to be uint32_t max.
72*61c4878aSAndroid Build Coastguard Worker                 payload,
73*61c4878aSAndroid Build Coastguard Worker                 Status::Unauthenticated());
74*61c4878aSAndroid Build Coastguard Worker 
75*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> result = packet.Encode(buffer);
76*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), result.status());
77*61c4878aSAndroid Build Coastguard Worker }
78*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,MaxSafePayload_OffByOne)79*61c4878aSAndroid Build Coastguard Worker TEST(Channel, MaxSafePayload_OffByOne) {
80*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kUint32Max = std::numeric_limits<uint32_t>::max();
81*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxPayloadSize = 64;
82*61c4878aSAndroid Build Coastguard Worker 
83*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kTestPayloadSize = MaxSafePayloadSize(kMaxPayloadSize);
84*61c4878aSAndroid Build Coastguard Worker 
85*61c4878aSAndroid Build Coastguard Worker   // Because it's impractical to test a payload that nears the limits of a
86*61c4878aSAndroid Build Coastguard Worker   // uint32 varint, calculate the difference when using a smaller payload.
87*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kPayloadSizeTestLimitations =
88*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(kUint32Max) - varint::EncodedSize(kTestPayloadSize);
89*61c4878aSAndroid Build Coastguard Worker 
90*61c4878aSAndroid Build Coastguard Worker   // The buffer to use for encoding the RPC packet.
91*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kMaxPayloadSize - kPayloadSizeTestLimitations - 1>
92*61c4878aSAndroid Build Coastguard Worker       buffer;
93*61c4878aSAndroid Build Coastguard Worker 
94*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kTestPayloadSize> payload;
95*61c4878aSAndroid Build Coastguard Worker   for (size_t i = 0; i < payload.size(); i++) {
96*61c4878aSAndroid Build Coastguard Worker     payload[i] = std::byte(i % std::numeric_limits<uint8_t>::max());
97*61c4878aSAndroid Build Coastguard Worker   }
98*61c4878aSAndroid Build Coastguard Worker 
99*61c4878aSAndroid Build Coastguard Worker   Packet packet(pwpb::PacketType::SERVER_STREAM,
100*61c4878aSAndroid Build Coastguard Worker                 /*channel_id=*/kUint32Max,  // Varint, needs to be uint32_t max.
101*61c4878aSAndroid Build Coastguard Worker                 /*service_id=*/42,       // Fixed-width. Value doesn't matter.
102*61c4878aSAndroid Build Coastguard Worker                 /*method_id=*/100,       // Fixed-width. Value doesn't matter.
103*61c4878aSAndroid Build Coastguard Worker                 /*call_id=*/kUint32Max,  // Varint, needs to be uint32_t max.
104*61c4878aSAndroid Build Coastguard Worker                 payload,
105*61c4878aSAndroid Build Coastguard Worker                 Status::Unauthenticated());
106*61c4878aSAndroid Build Coastguard Worker 
107*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> result = packet.Encode(buffer);
108*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(Status::ResourceExhausted(), result.status());
109*61c4878aSAndroid Build Coastguard Worker }
110*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,Create_FromEnum)111*61c4878aSAndroid Build Coastguard Worker TEST(Channel, Create_FromEnum) {
112*61c4878aSAndroid Build Coastguard Worker   constexpr rpc::Channel one = Channel::Create<ChannelId::kOne>(nullptr);
113*61c4878aSAndroid Build Coastguard Worker   constexpr rpc::Channel two = Channel::Create<ChannelId::kTwo>(nullptr);
114*61c4878aSAndroid Build Coastguard Worker   static_assert(one.id() == 1);
115*61c4878aSAndroid Build Coastguard Worker   static_assert(two.id() == 2);
116*61c4878aSAndroid Build Coastguard Worker }
117*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,TestPacket_ReservedSizeMatchesMinEncodedSizeBytes)118*61c4878aSAndroid Build Coastguard Worker TEST(Channel, TestPacket_ReservedSizeMatchesMinEncodedSizeBytes) {
119*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(kReservedSize, kTestPacket.MinEncodedSizeBytes());
120*61c4878aSAndroid Build Coastguard Worker }
121*61c4878aSAndroid Build Coastguard Worker 
TEST(ExtractChannelId,ValidPacket)122*61c4878aSAndroid Build Coastguard Worker TEST(ExtractChannelId, ValidPacket) {
123*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[64] = {};
124*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> result = kTestPacket.Encode(buffer);
125*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
126*61c4878aSAndroid Build Coastguard Worker 
127*61c4878aSAndroid Build Coastguard Worker   Result<uint32_t> channel_id = ExtractChannelId(*result);
128*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(channel_id.status(), OkStatus());
129*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*channel_id, 23u);
130*61c4878aSAndroid Build Coastguard Worker }
131*61c4878aSAndroid Build Coastguard Worker 
TEST(ExtractChannelId,InvalidPacket)132*61c4878aSAndroid Build Coastguard Worker TEST(ExtractChannelId, InvalidPacket) {
133*61c4878aSAndroid Build Coastguard Worker   constexpr std::byte buffer[64] = {std::byte{1}, std::byte{2}};
134*61c4878aSAndroid Build Coastguard Worker 
135*61c4878aSAndroid Build Coastguard Worker   Result<uint32_t> channel_id = ExtractChannelId(buffer);
136*61c4878aSAndroid Build Coastguard Worker 
137*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(channel_id.status(), Status::DataLoss());
138*61c4878aSAndroid Build Coastguard Worker }
139*61c4878aSAndroid Build Coastguard Worker 
TEST(ExtractChannelId,ChangeChannelIdToValidValue)140*61c4878aSAndroid Build Coastguard Worker TEST(ExtractChannelId, ChangeChannelIdToValidValue) {
141*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[64] = {};
142*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> result = kTestPacket.Encode(buffer);
143*61c4878aSAndroid Build Coastguard Worker   ByteSpan packet(buffer, result.value().size());
144*61c4878aSAndroid Build Coastguard Worker 
145*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 0), OkStatus());
146*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 0u);
147*61c4878aSAndroid Build Coastguard Worker 
148*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 1), OkStatus());
149*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 1u);
150*61c4878aSAndroid Build Coastguard Worker 
151*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 23), OkStatus());
152*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 23u);
153*61c4878aSAndroid Build Coastguard Worker 
154*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 127), OkStatus());
155*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 127u);
156*61c4878aSAndroid Build Coastguard Worker 
157*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId<0>(packet), OkStatus());
158*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 0u);
159*61c4878aSAndroid Build Coastguard Worker 
160*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId<1>(packet), OkStatus());
161*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 1u);
162*61c4878aSAndroid Build Coastguard Worker 
163*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId<23>(packet), OkStatus());
164*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 23u);
165*61c4878aSAndroid Build Coastguard Worker 
166*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId<127>(packet), OkStatus());
167*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ExtractChannelId(packet).value(), 127u);
168*61c4878aSAndroid Build Coastguard Worker }
169*61c4878aSAndroid Build Coastguard Worker 
TEST(ExtractChannelId,ChangeChannelIdTooLarge)170*61c4878aSAndroid Build Coastguard Worker TEST(ExtractChannelId, ChangeChannelIdTooLarge) {
171*61c4878aSAndroid Build Coastguard Worker   constexpr Packet kChannelIdTooLargePacket(
172*61c4878aSAndroid Build Coastguard Worker       pwpb::PacketType::RESPONSE, 128, 42, 100, 0, {}, Status::NotFound());
173*61c4878aSAndroid Build Coastguard Worker 
174*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[64] = {};
175*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> result = kChannelIdTooLargePacket.Encode(buffer);
176*61c4878aSAndroid Build Coastguard Worker   ByteSpan packet(buffer, result.value().size());
177*61c4878aSAndroid Build Coastguard Worker 
178*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 0), Status::OutOfRange());
179*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 1), Status::OutOfRange());
180*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 23), Status::OutOfRange());
181*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 127), Status::OutOfRange());
182*61c4878aSAndroid Build Coastguard Worker }
183*61c4878aSAndroid Build Coastguard Worker 
TEST(ExtractChannelId,ChangeChannelIdNoChannelFound)184*61c4878aSAndroid Build Coastguard Worker TEST(ExtractChannelId, ChangeChannelIdNoChannelFound) {
185*61c4878aSAndroid Build Coastguard Worker   std::byte packet[64] = {};
186*61c4878aSAndroid Build Coastguard Worker 
187*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 0), Status::DataLoss());
188*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 1), Status::DataLoss());
189*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 23), Status::DataLoss());
190*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(ChangeEncodedChannelId(packet, 127), Status::DataLoss());
191*61c4878aSAndroid Build Coastguard Worker }
192*61c4878aSAndroid Build Coastguard Worker 
193*61c4878aSAndroid Build Coastguard Worker }  // namespace
194*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc::internal
195