72a66ce4ca58b0a4930ba18f4b0a9f7c26b615fe
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_hdlc_lite / encoder_test.cc
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_hdlc_lite/encoder.h"
16
17 #include <algorithm>
18 #include <array>
19 #include <cstddef>
20
21 #include "gtest/gtest.h"
22 #include "pw_bytes/array.h"
23 #include "pw_hdlc_lite_private/protocol.h"
24 #include "pw_stream/memory_stream.h"
25
26 using std::byte;
27
28 namespace pw::hdlc_lite {
29 namespace {
30
31 constexpr uint8_t kAddress = 0x7B;  // 123
32 constexpr byte kControl = byte{0};
33
34 class WriteInfoFrame : public ::testing::Test {
35  protected:
36   WriteInfoFrame() : writer_(buffer_) {}
37
38   stream::MemoryWriter writer_;
39   std::array<byte, 32> buffer_;
40 };
41
42 #define EXPECT_ENCODER_WROTE(...)                                           \
43   do {                                                                      \
44     constexpr auto expected_data = (__VA_ARGS__);                           \
45     EXPECT_EQ(writer_.bytes_written(), expected_data.size());               \
46     EXPECT_EQ(                                                              \
47         std::memcmp(                                                        \
48             writer_.data(), expected_data.data(), writer_.bytes_written()), \
49         0);                                                                 \
50   } while (0)
51
52 TEST_F(WriteInfoFrame, EmptyPayload) {
53   ASSERT_EQ(Status::Ok(),
54             WriteInformationFrame(kAddress, std::span<byte>(), writer_));
55   EXPECT_ENCODER_WROTE(
56       bytes::Concat(kFlag, kAddress, kControl, uint32_t{0x8D12B2C2}, kFlag));
57 }
58
59 TEST_F(WriteInfoFrame, OneBytePayload) {
60   ASSERT_EQ(Status::Ok(),
61             WriteInformationFrame(kAddress, bytes::String("A"), writer_));
62   EXPECT_ENCODER_WROTE(bytes::Concat(
63       kFlag, kAddress, kControl, 'A', uint32_t{0xA63E2FA5}, kFlag));
64 }
65
66 TEST_F(WriteInfoFrame, OneBytePayload_Escape0x7d) {
67   ASSERT_EQ(Status::Ok(),
68             WriteInformationFrame(kAddress, bytes::Array<0x7d>(), writer_));
69   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
70                                      kAddress,
71                                      kControl,
72                                      kEscape,
73                                      byte{0x7d} ^ byte{0x20},
74                                      uint32_t{0x89515322},
75                                      kFlag));
76 }
77
78 TEST_F(WriteInfoFrame, OneBytePayload_Escape0x7E) {
79   ASSERT_EQ(Status::Ok(),
80             WriteInformationFrame(kAddress, bytes::Array<0x7e>(), writer_));
81   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
82                                      kAddress,
83                                      kControl,
84                                      kEscape,
85                                      byte{0x7e} ^ byte{0x20},
86                                      uint32_t{0x10580298},
87                                      kFlag));
88 }
89
90 TEST_F(WriteInfoFrame, AddressNeedsEscaping) {
91   ASSERT_EQ(Status::Ok(),
92             WriteInformationFrame(0x7d, bytes::String("A"), writer_));
93   EXPECT_ENCODER_WROTE(bytes::Concat(
94       kFlag, kEscape, byte{0x5d}, kControl, 'A', uint32_t{0xA2B35317}, kFlag));
95 }
96
97 TEST_F(WriteInfoFrame, Crc32NeedsEscaping) {
98   ASSERT_EQ(Status::Ok(),
99             WriteInformationFrame(kAddress, bytes::String("abcdefg"), writer_));
100
101   // The CRC-32 is 0x38B9FC7E, so the 0x7E must be escaped.
102   constexpr auto expected_crc32 = bytes::Array<0x7d, 0x5e, 0xfc, 0xb9, 0x38>();
103   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
104                                      kAddress,
105                                      kControl,
106                                      bytes::String("abcdefg"),
107                                      expected_crc32,
108                                      kFlag));
109 }
110
111 TEST_F(WriteInfoFrame, MultiplePayloads) {
112   ASSERT_EQ(Status::Ok(),
113             WriteInformationFrame(kAddress, bytes::String("ABC"), writer_));
114   ASSERT_EQ(Status::Ok(),
115             WriteInformationFrame(kAddress, bytes::String("DEF"), writer_));
116   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
117                                      kAddress,
118                                      kControl,
119                                      bytes::String("ABC"),
120                                      uint32_t{0x14E2FC99},
121                                      kFlag,
122                                      kFlag,
123                                      kAddress,
124                                      kControl,
125                                      bytes::String("DEF"),
126                                      uint32_t{0x2D025C3A},
127                                      kFlag));
128 }
129
130 TEST_F(WriteInfoFrame, PayloadWithNoEscapes) {
131   ASSERT_EQ(Status::Ok(),
132             WriteInformationFrame(
133                 kAddress, bytes::String("123456789012345678901234"), writer_));
134
135   // Fill the memory writer's buffer.
136   ASSERT_EQ(writer_.bytes_written(), buffer_.size());
137
138   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
139                                      kAddress,
140                                      kControl,
141                                      bytes::String("123456789012345678901234"),
142                                      uint32_t{0x50AA35EC},
143                                      kFlag));
144 }
145
146 TEST_F(WriteInfoFrame, PayloadWithMultipleEscapes) {
147   ASSERT_EQ(Status::Ok(),
148             WriteInformationFrame(
149                 kAddress,
150                 bytes::Array<0x7E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x7E>(),
151                 writer_));
152   EXPECT_ENCODER_WROTE(bytes::Concat(
153       kFlag,
154       kAddress,
155       kControl,
156       bytes::
157           Array<0x7D, 0x5E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x5D, 0x7D, 0x5E>(),
158       uint32_t{0x1B8D505E},
159       kFlag));
160 }
161
162 TEST_F(WriteInfoFrame, WriterError) {
163   constexpr auto data = bytes::Initialized<sizeof(buffer_)>(0x7e);
164
165   EXPECT_EQ(Status::ResourceExhausted(),
166             WriteInformationFrame(kAddress, data, writer_));
167 }
168
169 }  // namespace
170 }  // namespace pw::hdlc_lite