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