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