xref: /aosp_15_r20/external/pigweed/pw_rpc_transport/simple_framing_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 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_transport/simple_framing.h"
16 
17 #include <algorithm>
18 #include <array>
19 #include <random>
20 
21 #include "pw_bytes/span.h"
22 #include "pw_log/log.h"
23 #include "pw_status/status.h"
24 #include "pw_unit_test/framework.h"
25 
26 namespace pw::rpc {
27 namespace {
28 
29 constexpr size_t kMaxPacketSize = 256;
30 
31 struct TestParams {
32   size_t packet_size = 0;
33   size_t max_frame_size = 0;
34 };
35 
36 constexpr std::array<TestParams, 8> kTestCases = {
37     // Packet fits in one frame.
38     TestParams{.packet_size = 5, .max_frame_size = 100},
39     // Typical parameters for RPC packet and mailbox frame size.
40     TestParams{.packet_size = 100, .max_frame_size = 128},
41     // Smallest packet.
42     TestParams{.packet_size = 1, .max_frame_size = 16},
43     // Small packet, small frame.
44     TestParams{.packet_size = 16, .max_frame_size = 5},
45     // Odd-sized packet, small frame.
46     TestParams{.packet_size = 77, .max_frame_size = 16},
47     // Frame size and packet size off by one.
48     TestParams{.packet_size = 11, .max_frame_size = 10},
49     // Almost at the limit.
50     TestParams{.packet_size = kMaxPacketSize - 1,
51                .max_frame_size = kMaxPacketSize - 2},
52     // At the limit.
53     TestParams{.packet_size = kMaxPacketSize,
54                .max_frame_size = kMaxPacketSize}};
55 
MakePacket(ByteSpan dst_buffer)56 void MakePacket(ByteSpan dst_buffer) {
57   static uint32_t rg_seed = 0x123;
58   unsigned char c = 0;
59   for (auto& i : dst_buffer) {
60     i = std::byte{c++};
61   }
62   std::mt19937 rg(rg_seed++);
63   std::shuffle(dst_buffer.begin(), dst_buffer.end(), rg);
64 }
65 
CopyFrame(RpcFrame frame,std::vector<std::byte> & dst)66 void CopyFrame(RpcFrame frame, std::vector<std::byte>& dst) {
67   std::copy(frame.header.begin(), frame.header.end(), std::back_inserter(dst));
68   std::copy(
69       frame.payload.begin(), frame.payload.end(), std::back_inserter(dst));
70 }
71 
TEST(SimpleRpcFrameEncodeDecodeTest,EncodeThenDecode)72 TEST(SimpleRpcFrameEncodeDecodeTest, EncodeThenDecode) {
73   for (auto test_case : kTestCases) {
74     const size_t packet_size = test_case.packet_size;
75     const size_t max_frame_size = test_case.max_frame_size;
76     PW_LOG_INFO("EncodeThenDecode: packet_size = %d, max_frame_size = %d",
77                 static_cast<int>(packet_size),
78                 static_cast<int>(max_frame_size));
79 
80     std::vector<std::byte> src(packet_size);
81     MakePacket(src);
82 
83     std::vector<std::byte> encoded;
84     std::vector<std::byte> decoded;
85 
86     SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
87 
88     ASSERT_EQ(encoder.Encode(src,
89                              max_frame_size,
90                              [&encoded](RpcFrame& frame) {
91                                CopyFrame(frame, encoded);
92                                return OkStatus();
93                              }),
94               OkStatus());
95 
96     SimpleRpcPacketDecoder<kMaxPacketSize> decoder;
97 
98     ASSERT_EQ(decoder.Decode(encoded,
99                              [&decoded](ConstByteSpan packet) {
100                                std::copy(packet.begin(),
101                                          packet.end(),
102                                          std::back_inserter(decoded));
103                              }),
104               OkStatus());
105 
106     EXPECT_TRUE(std::equal(src.begin(), src.end(), decoded.begin()));
107   }
108 }
109 
TEST(SimpleRpcFrameEncodeDecodeTest,OneByteAtTimeDecoding)110 TEST(SimpleRpcFrameEncodeDecodeTest, OneByteAtTimeDecoding) {
111   for (auto test_case : kTestCases) {
112     const size_t packet_size = test_case.packet_size;
113     const size_t max_frame_size = test_case.max_frame_size;
114     PW_LOG_INFO("EncodeThenDecode: packet_size = %d, max_frame_size = %d",
115                 static_cast<int>(packet_size),
116                 static_cast<int>(max_frame_size));
117 
118     std::vector<std::byte> src(packet_size);
119     MakePacket(src);
120 
121     std::vector<std::byte> encoded;
122     std::vector<std::byte> decoded;
123 
124     SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
125 
126     ASSERT_EQ(encoder.Encode(src,
127                              max_frame_size,
128                              [&encoded](RpcFrame& frame) {
129                                CopyFrame(frame, encoded);
130                                return OkStatus();
131                              }),
132               OkStatus());
133 
134     SimpleRpcPacketDecoder<kMaxPacketSize> decoder;
135 
136     for (std::byte b : encoded) {
137       auto buffer_span = span(&b, 1);
138       ASSERT_EQ(decoder.Decode(buffer_span,
139                                [&decoded](ConstByteSpan packet) {
140                                  std::copy(packet.begin(),
141                                            packet.end(),
142                                            std::back_inserter(decoded));
143                                }),
144                 OkStatus());
145     }
146 
147     EXPECT_TRUE(std::equal(src.begin(), src.end(), decoded.begin()));
148   }
149 }
150 
TEST(SimpleRpcFrameTest,MissingFirstFrame)151 TEST(SimpleRpcFrameTest, MissingFirstFrame) {
152   // Sends two packets, the first packet is missing its first frame. The decoder
153   // ignores the remaining frames of the first packet but still picks up the
154   // second packet.
155   constexpr size_t kPacketSize = 77;
156   constexpr size_t kMaxFrameSize = 16;
157 
158   std::vector<std::byte> src1(kPacketSize);
159   MakePacket(src1);
160 
161   std::vector<std::byte> src2(kPacketSize);
162   MakePacket(src2);
163 
164   std::vector<std::byte> decoded;
165 
166   SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
167   struct EncodeState {
168     size_t frame_counter = 0;
169     std::vector<std::byte> encoded;
170   } state;
171 
172   ASSERT_EQ(encoder.Encode(src1,
173                            kMaxFrameSize,
174                            [&state](RpcFrame& frame) {
175                              state.frame_counter++;
176                              if (state.frame_counter > 1) {
177                                // Skip the first frame.
178                                CopyFrame(frame, state.encoded);
179                              }
180                              return OkStatus();
181                            }),
182             OkStatus());
183 
184   ASSERT_EQ(encoder.Encode(src2,
185                            kMaxFrameSize,
186                            [&state](RpcFrame& frame) {
187                              CopyFrame(frame, state.encoded);
188                              return OkStatus();
189                            }),
190             OkStatus());
191 
192   SimpleRpcPacketDecoder<kMaxPacketSize> decoder;
193 
194   ASSERT_EQ(decoder.Decode(state.encoded,
195                            [&decoded](ConstByteSpan packet) {
196                              std::copy(packet.begin(),
197                                        packet.end(),
198                                        std::back_inserter(decoded));
199                            }),
200             OkStatus());
201 
202   EXPECT_TRUE(std::equal(src2.begin(), src2.end(), decoded.begin()));
203 }
204 
TEST(SimpleRpcFrameTest,MissingInternalFrame)205 TEST(SimpleRpcFrameTest, MissingInternalFrame) {
206   // Sends two packets, the first packet is missing its second frame. The
207   // decoder ignores the remaining frames of the first packet and the second
208   // packet as well but eventually stumbles upon the frame header in the third
209   // packet and processes that packet.
210   constexpr size_t kPacketSize = 77;
211   constexpr size_t kMaxFrameSize = 16;
212 
213   std::vector<std::byte> src1(kPacketSize);
214   MakePacket(src1);
215 
216   std::vector<std::byte> src2(kPacketSize);
217   MakePacket(src2);
218 
219   std::vector<std::byte> src3(kPacketSize);
220   MakePacket(src3);
221 
222   std::vector<std::byte> decoded;
223 
224   SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
225   struct EncodeState {
226     size_t frame_counter = 0;
227     std::vector<std::byte> encoded;
228   } encode_state;
229 
230   ASSERT_EQ(encoder.Encode(src1,
231                            kMaxFrameSize,
232                            [&encode_state](RpcFrame& frame) {
233                              encode_state.frame_counter++;
234                              if (encode_state.frame_counter != 2) {
235                                // Skip the second frame.
236                                CopyFrame(frame, encode_state.encoded);
237                              }
238                              return OkStatus();
239                            }),
240             OkStatus());
241 
242   ASSERT_EQ(encoder.Encode(src2,
243                            kMaxFrameSize,
244                            [&encode_state](RpcFrame& frame) {
245                              CopyFrame(frame, encode_state.encoded);
246                              return OkStatus();
247                            }),
248             OkStatus());
249 
250   ASSERT_EQ(encoder.Encode(src3,
251                            kMaxFrameSize,
252                            [&encode_state](RpcFrame& frame) {
253                              CopyFrame(frame, encode_state.encoded);
254                              return OkStatus();
255                            }),
256             OkStatus());
257 
258   SimpleRpcPacketDecoder<kMaxPacketSize> decoder;
259 
260   // First packet is decoded but it doesn't have correct bytes, as one of its
261   // frames has never been received. Second packet is not received because its
262   // header has been consumed by the first packet. By that point the decoder
263   // knows that something is wrong and tries to recover as soon as it receives
264   // bytes that look as the valid header. So we eventually receive the third
265   // packet and it is correct.
266   struct DecodeState {
267     std::vector<std::byte> decoded1;
268     std::vector<std::byte> decoded2;
269     size_t packet_counter = 0;
270   } decode_state;
271 
272   ASSERT_EQ(
273       decoder.Decode(encode_state.encoded,
274                      [&decode_state](ConstByteSpan packet) {
275                        decode_state.packet_counter++;
276                        if (decode_state.packet_counter == 1) {
277                          std::copy(packet.begin(),
278                                    packet.end(),
279                                    std::back_inserter(decode_state.decoded1));
280                        }
281                        if (decode_state.packet_counter == 2) {
282                          std::copy(packet.begin(),
283                                    packet.end(),
284                                    std::back_inserter(decode_state.decoded2));
285                        }
286                      }),
287       OkStatus());
288 
289   EXPECT_EQ(decode_state.packet_counter, 2ul);
290 
291   EXPECT_EQ(decode_state.decoded1.size(), src1.size());
292   EXPECT_FALSE(
293       std::equal(src1.begin(), src1.end(), decode_state.decoded1.begin()));
294 
295   EXPECT_TRUE(
296       std::equal(src3.begin(), src3.end(), decode_state.decoded2.begin()));
297 }
298 
TEST(SimpleRpcPacketEncoder,PacketTooBig)299 TEST(SimpleRpcPacketEncoder, PacketTooBig) {
300   SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
301   constexpr size_t kMaxFrameSize = 100;
302   std::array<std::byte, kMaxPacketSize + 1> src{};
303 
304   EXPECT_EQ(
305       encoder.Encode(src, kMaxFrameSize, [](RpcFrame&) { return OkStatus(); }),
306       Status::FailedPrecondition());
307 }
308 
TEST(SimpleRpcPacketEncoder,MaxFrameSizeTooSmall)309 TEST(SimpleRpcPacketEncoder, MaxFrameSizeTooSmall) {
310   SimpleRpcPacketEncoder<kMaxPacketSize> encoder;
311   std::array<std::byte, kMaxPacketSize> src{};
312 
313   EXPECT_EQ(encoder.Encode(
314                 src, encoder.kHeaderSize, [](RpcFrame&) { return OkStatus(); }),
315             Status::FailedPrecondition());
316 
317   EXPECT_EQ(
318       encoder.Encode(
319           src, encoder.kHeaderSize + 1, [](RpcFrame&) { return OkStatus(); }),
320       OkStatus());
321 }
322 
TEST(SimpleRpcFrameTest,EncoderBufferLargerThanDecoderBuffer)323 TEST(SimpleRpcFrameTest, EncoderBufferLargerThanDecoderBuffer) {
324   constexpr size_t kLargePacketSize = 150;
325   constexpr size_t kSmallPacketSize = 120;
326   constexpr size_t kMaxFrameSize = 16;
327 
328   // Decoder isn't able to receive the whole packet because it needs to be
329   // buffered but the internal buffer is too small; the packet is thus
330   // discarded. The second packet is received without issues as it's small
331   // enough to fit in the decoder buffer.
332   constexpr size_t kEncoderMaxPacketSize = 256;
333   constexpr size_t kDecoderMaxPacketSize = 128;
334 
335   std::vector<std::byte> src1(kLargePacketSize);
336   MakePacket(src1);
337 
338   std::vector<std::byte> src2(kSmallPacketSize);
339   MakePacket(src1);
340 
341   std::vector<std::byte> encoded;
342   std::vector<std::byte> decoded;
343 
344   SimpleRpcPacketEncoder<kEncoderMaxPacketSize> encoder;
345 
346   ASSERT_EQ(encoder.Encode(src1,
347                            kMaxFrameSize,
348                            [&encoded](RpcFrame& frame) {
349                              CopyFrame(frame, encoded);
350                              return OkStatus();
351                            }),
352             OkStatus());
353 
354   ASSERT_EQ(encoder.Encode(src2,
355                            kMaxFrameSize,
356                            [&encoded](RpcFrame& frame) {
357                              CopyFrame(frame, encoded);
358                              return OkStatus();
359                            }),
360             OkStatus());
361 
362   SimpleRpcPacketDecoder<kDecoderMaxPacketSize> decoder;
363 
364   // We have to decode piecemeal here because otherwise the decoder can just
365   // pluck the packet from `encoded` without internally buffering it.
366   for (std::byte b : encoded) {
367     auto buffer_span = span(&b, 1);
368     ASSERT_EQ(decoder.Decode(buffer_span,
369                              [&decoded](ConstByteSpan packet) {
370                                std::copy(packet.begin(),
371                                          packet.end(),
372                                          std::back_inserter(decoded));
373                              }),
374               OkStatus());
375   }
376 
377   EXPECT_TRUE(std::equal(src2.begin(), src2.end(), decoded.begin()));
378 }
379 
380 }  // namespace
381 }  // namespace pw::rpc
382