xref: /aosp_15_r20/external/pigweed/pw_hdlc/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 // Copyright 2020 The Pigweed Authors
16 //
17 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
18 // use this file except in compliance with the License. You may obtain a copy of
19 // the License at
20 //
21 //     https://www.apache.org/licenses/LICENSE-2.0
22 //
23 // Unless required by applicable law or agreed to in writing, software
24 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
25 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26 // License for the specific language governing permissions and limitations under
27 // the License.
28 
29 #include "pw_hdlc/rpc_channel.h"
30 
31 #include <algorithm>
32 #include <array>
33 #include <cstddef>
34 
35 #include "pw_bytes/array.h"
36 #include "pw_hdlc/encoded_size.h"
37 #include "pw_stream/memory_stream.h"
38 #include "pw_unit_test/framework.h"
39 
40 using std::byte;
41 
42 namespace pw::hdlc {
43 namespace {
44 
45 constexpr byte kFlag = byte{0x7E};
46 constexpr uint8_t kAddress = 0x7b;  // 123
47 constexpr uint8_t kEncodedAddress = (kAddress << 1) | 1;
48 constexpr byte kControl = byte{0x3};  // UI-frame control sequence.
49 
50 // Size of the in-memory buffer to use for this test. All tests send a one-byte
51 // payload.
52 constexpr size_t kSinkBufferSize = MaxEncodedFrameSize(1);
53 
54 TEST(RpcChannelOutput, 1BytePayload) {
55   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
56 
57   RpcChannelOutput output(memory_writer, kAddress, "RpcChannelOutput");
58 
59   constexpr byte test_data = byte{'A'};
60   std::array<std::byte, 128> buffer;
61   std::memcpy(buffer.data(), &test_data, sizeof(test_data));
62 
63   constexpr auto expected = bytes::Concat(
64       kFlag, kEncodedAddress, kControl, 'A', uint32_t{0x653c9e82}, kFlag);
65 
66   EXPECT_EQ(OkStatus(), output.Send(span(buffer).first(sizeof(test_data))));
67 
68   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
69   EXPECT_EQ(
70       std::memcmp(
71           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
72       0);
73 }
74 
TEST(RpcChannelOutput,EscapingPayloadTest)75 TEST(RpcChannelOutput, EscapingPayloadTest) {
76   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
77 
78   RpcChannelOutput output(memory_writer, kAddress, "RpcChannelOutput");
79 
80   constexpr auto test_data = bytes::Array<0x7D>();
81   std::array<std::byte, 128> buffer;
82   std::memcpy(buffer.data(), test_data.data(), test_data.size());
83 
84   constexpr auto expected = bytes::Concat(kFlag,
85                                           kEncodedAddress,
86                                           kControl,
87                                           byte{0x7d},
88                                           byte{0x7d} ^ byte{0x20},
89                                           uint32_t{0x4a53e205},
90                                           kFlag);
91   EXPECT_EQ(OkStatus(), output.Send(span(buffer).first(test_data.size())));
92 
93   ASSERT_EQ(memory_writer.bytes_written(), 10u);
94   EXPECT_EQ(
95       std::memcmp(
96           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
97       0);
98 }
99 
TEST(FixedMtuChannelOutput,CompileTest)100 TEST(FixedMtuChannelOutput, CompileTest) {
101   constexpr size_t kRequiredMtu =
102       MaxEncodedFrameSize(rpc::cfg::kEncodingBufferSizeBytes);
103   stream::MemoryWriterBuffer<kRequiredMtu> memory_writer;
104   [[maybe_unused]] FixedMtuChannelOutput<kRequiredMtu> channel_output(
105       memory_writer, kAddress, "RpcChannelOutput");
106   EXPECT_EQ(channel_output.MaxSafePayloadSize(), rpc::MaxSafePayloadSize());
107 }
108 
109 TEST(RpcChannelOutputBuffer, 1BytePayload) {
110   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
111 
112   RpcChannelOutput output(memory_writer, kAddress, "RpcChannelOutput");
113 
114   constexpr byte test_data = byte{'A'};
115   std::array<std::byte, 128> buffer;
116   std::memcpy(buffer.data(), &test_data, sizeof(test_data));
117 
118   constexpr auto expected = bytes::Concat(
119       kFlag, kEncodedAddress, kControl, 'A', uint32_t{0x653c9e82}, kFlag);
120 
121   EXPECT_EQ(OkStatus(), output.Send(span(buffer).first(sizeof(test_data))));
122 
123   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
124   EXPECT_EQ(
125       std::memcmp(
126           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
127       0);
128 }
129 
TEST(RpcChannelOutputBuffer,MultibyteAddress)130 TEST(RpcChannelOutputBuffer, MultibyteAddress) {
131   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
132 
133   RpcChannelOutput output(memory_writer, 0x3fff, "RpcChannelOutput");
134 
135   constexpr byte test_data = byte{'A'};
136   std::array<std::byte, 128> buffer;
137   std::memcpy(buffer.data(), &test_data, sizeof(test_data));
138 
139   constexpr auto expected = bytes::Concat(kFlag,
140                                           bytes::String("\xfe\xff"),
141                                           kControl,
142                                           'A',
143                                           uint32_t{0xd393a8a0},
144                                           kFlag);
145 
146   EXPECT_EQ(OkStatus(), output.Send(span(buffer).first(sizeof(test_data))));
147 
148   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
149   EXPECT_EQ(
150       std::memcmp(
151           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
152       0);
153 }
154 
155 }  // namespace
156 }  // namespace pw::hdlc
157