• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gtest/gtest.h"
36 #include "pw_bytes/array.h"
37 #include "pw_stream/memory_stream.h"
38 
39 using std::byte;
40 
41 namespace pw::hdlc {
42 namespace {
43 
44 constexpr byte kFlag = byte{0x7E};
45 constexpr uint8_t kAddress = 0x7b;  // 123
46 constexpr uint8_t kEncodedAddress = (kAddress << 1) | 1;
47 constexpr byte kControl = byte{0x3};  // UI-frame control sequence.
48 
49 // Size of the in-memory buffer to use for this test.
50 constexpr size_t kSinkBufferSize = 15;
51 
52 TEST(RpcChannelOutput, 1BytePayload) {
53   std::array<byte, kSinkBufferSize> channel_output_buffer;
54   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
55 
56   RpcChannelOutput output(
57       memory_writer, channel_output_buffer, kAddress, "RpcChannelOutput");
58 
59   constexpr byte test_data = byte{'A'};
60   auto buffer = output.AcquireBuffer();
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(),
67             output.SendAndReleaseBuffer(buffer.first(sizeof(test_data))));
68 
69   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
70   EXPECT_EQ(
71       std::memcmp(
72           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
73       0);
74 }
75 
TEST(RpcChannelOutput,EscapingPayloadTest)76 TEST(RpcChannelOutput, EscapingPayloadTest) {
77   std::array<byte, kSinkBufferSize> channel_output_buffer;
78   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
79 
80   RpcChannelOutput output(
81       memory_writer, channel_output_buffer, kAddress, "RpcChannelOutput");
82 
83   constexpr auto test_data = bytes::Array<0x7D>();
84   auto buffer = output.AcquireBuffer();
85   std::memcpy(buffer.data(), test_data.data(), test_data.size());
86 
87   constexpr auto expected = bytes::Concat(kFlag,
88                                           kEncodedAddress,
89                                           kControl,
90                                           byte{0x7d},
91                                           byte{0x7d} ^ byte{0x20},
92                                           uint32_t{0x4a53e205},
93                                           kFlag);
94   EXPECT_EQ(OkStatus(),
95             output.SendAndReleaseBuffer(buffer.first(test_data.size())));
96 
97   ASSERT_EQ(memory_writer.bytes_written(), 10u);
98   EXPECT_EQ(
99       std::memcmp(
100           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
101       0);
102 }
103 
104 TEST(RpcChannelOutputBuffer, 1BytePayload) {
105   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
106 
107   RpcChannelOutputBuffer<kSinkBufferSize> output(
108       memory_writer, kAddress, "RpcChannelOutput");
109 
110   constexpr byte test_data = byte{'A'};
111   auto buffer = output.AcquireBuffer();
112   std::memcpy(buffer.data(), &test_data, sizeof(test_data));
113 
114   constexpr auto expected = bytes::Concat(
115       kFlag, kEncodedAddress, kControl, 'A', uint32_t{0x653c9e82}, kFlag);
116 
117   EXPECT_EQ(OkStatus(),
118             output.SendAndReleaseBuffer(buffer.first(sizeof(test_data))));
119 
120   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
121   EXPECT_EQ(
122       std::memcmp(
123           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
124       0);
125 }
126 
TEST(RpcChannelOutputBuffer,MultibyteAddress)127 TEST(RpcChannelOutputBuffer, MultibyteAddress) {
128   stream::MemoryWriterBuffer<kSinkBufferSize> memory_writer;
129 
130   RpcChannelOutputBuffer<kSinkBufferSize> output(
131       memory_writer, 0x3fff, "RpcChannelOutput");
132 
133   constexpr byte test_data = byte{'A'};
134   auto buffer = output.AcquireBuffer();
135   std::memcpy(buffer.data(), &test_data, sizeof(test_data));
136 
137   constexpr auto expected = bytes::Concat(kFlag,
138                                           bytes::String("\xfe\xff"),
139                                           kControl,
140                                           'A',
141                                           uint32_t{0xd393a8a0},
142                                           kFlag);
143 
144   EXPECT_EQ(OkStatus(),
145             output.SendAndReleaseBuffer(buffer.first(sizeof(test_data))));
146 
147   ASSERT_EQ(memory_writer.bytes_written(), expected.size());
148   EXPECT_EQ(
149       std::memcmp(
150           memory_writer.data(), expected.data(), memory_writer.bytes_written()),
151       0);
152 }
153 
154 }  // namespace
155 }  // namespace pw::hdlc
156