Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_hdlc / 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/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/internal/encoder.h"
24 #include "pw_hdlc_private/protocol.h"
25 #include "pw_stream/memory_stream.h"
26
27 using std::byte;
28
29 namespace pw::hdlc {
30 namespace {
31
32 constexpr uint8_t kAddress = 0x7B;  // 123
33
34 #define EXPECT_ENCODER_WROTE(...)                                           \
35   do {                                                                      \
36     constexpr auto expected_data = (__VA_ARGS__);                           \
37     EXPECT_EQ(writer_.bytes_written(), expected_data.size());               \
38     EXPECT_EQ(                                                              \
39         std::memcmp(                                                        \
40             writer_.data(), expected_data.data(), writer_.bytes_written()), \
41         0);                                                                 \
42   } while (0)
43
44 class WriteUnnumberedFrame : public ::testing::Test {
45  protected:
46   WriteUnnumberedFrame() : writer_(buffer_) {}
47
48   stream::MemoryWriter writer_;
49   std::array<byte, 32> buffer_;
50 };
51
52 constexpr byte kUnnumberedControl = byte{0x3};
53
54 TEST_F(WriteUnnumberedFrame, EmptyPayload) {
55   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, std::span<byte>(), writer_));
56   EXPECT_ENCODER_WROTE(bytes::Concat(
57       kFlag, kAddress, kUnnumberedControl, uint32_t{0x141BE378}, kFlag));
58 }
59
60 TEST_F(WriteUnnumberedFrame, OneBytePayload) {
61   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("A"), writer_));
62   EXPECT_ENCODER_WROTE(bytes::Concat(
63       kFlag, kAddress, kUnnumberedControl, 'A', uint32_t{0x8D137C66}, kFlag));
64 }
65
66 TEST_F(WriteUnnumberedFrame, OneBytePayload_Escape0x7d) {
67   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::Array<0x7d>(), writer_));
68   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
69                                      kAddress,
70                                      kUnnumberedControl,
71                                      kEscape,
72                                      byte{0x7d} ^ byte{0x20},
73                                      uint32_t{0xA27C00E1},
74                                      kFlag));
75 }
76
77 TEST_F(WriteUnnumberedFrame, OneBytePayload_Escape0x7E) {
78   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::Array<0x7e>(), writer_));
79   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
80                                      kAddress,
81                                      kUnnumberedControl,
82                                      kEscape,
83                                      byte{0x7e} ^ byte{0x20},
84                                      uint32_t{0x3B75515B},
85                                      kFlag));
86 }
87
88 TEST_F(WriteUnnumberedFrame, AddressNeedsEscaping) {
89   ASSERT_EQ(OkStatus(), WriteUIFrame(0x7d, bytes::String("A"), writer_));
90   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
91                                      kEscape,
92                                      byte{0x5d},
93                                      kUnnumberedControl,
94                                      'A',
95                                      uint32_t{0x899E00D4},
96                                      kFlag));
97 }
98
99 TEST_F(WriteUnnumberedFrame, Crc32NeedsEscaping) {
100   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("a"), writer_));
101
102   // The CRC-32 is 0xB67D5CAE, so the 0x7D must be escaped.
103   constexpr auto expected_crc32 = bytes::Array<0xae, 0x5c, 0x7d, 0x5d, 0xb6>();
104   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
105                                      kAddress,
106                                      kUnnumberedControl,
107                                      bytes::String("a"),
108                                      expected_crc32,
109                                      kFlag));
110 }
111
112 TEST_F(WriteUnnumberedFrame, MultiplePayloads) {
113   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("ABC"), writer_));
114   ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("DEF"), writer_));
115   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
116                                      kAddress,
117                                      kUnnumberedControl,
118                                      bytes::String("ABC"),
119                                      uint32_t{0x06575377},
120                                      kFlag,
121                                      kFlag,
122                                      kAddress,
123                                      kUnnumberedControl,
124                                      bytes::String("DEF"),
125                                      uint32_t{0x3FB7F3D4},
126                                      kFlag));
127 }
128
129 TEST_F(WriteUnnumberedFrame, PayloadWithNoEscapes) {
130   ASSERT_EQ(
131       OkStatus(),
132       WriteUIFrame(kAddress, bytes::String("1995 toyota corolla"), writer_));
133
134   EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
135                                      kAddress,
136                                      kUnnumberedControl,
137                                      bytes::String("1995 toyota corolla"),
138                                      uint32_t{0x56560172},
139                                      kFlag));
140 }
141
142 TEST_F(WriteUnnumberedFrame, PayloadWithMultipleEscapes) {
143   ASSERT_EQ(
144       OkStatus(),
145       WriteUIFrame(kAddress,
146                    bytes::Array<0x7E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x7E>(),
147                    writer_));
148   EXPECT_ENCODER_WROTE(bytes::Concat(
149       kFlag,
150       kAddress,
151       kUnnumberedControl,
152       bytes::
153           Array<0x7D, 0x5E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x5D, 0x7D, 0x5E>(),
154       uint32_t{0x950257BD},
155       kFlag));
156 }
157
158 TEST_F(WriteUnnumberedFrame, PayloadTooLarge_WritesNothing) {
159   constexpr auto data = bytes::Initialized<sizeof(buffer_)>(0x7e);
160   EXPECT_EQ(Status::ResourceExhausted(), WriteUIFrame(kAddress, data, writer_));
161   EXPECT_EQ(0u, writer_.bytes_written());
162 }
163
164 class ErrorWriter : public stream::Writer {
165  private:
166   Status DoWrite(ConstByteSpan) override { return Status::Unimplemented(); }
167 };
168
169 TEST(WriteUnnumberedFrame, WriterError) {
170   ErrorWriter writer;
171   EXPECT_EQ(Status::Unimplemented(),
172             WriteUIFrame(kAddress, bytes::Array<0x01>(), writer));
173 }
174
175 }  // namespace
176
177 namespace internal {
178 namespace {
179
180 constexpr uint8_t kEscapeAddress = 0x7d;
181
182 TEST(Encoder, MaxEncodedSize_EmptyPayload) {
183   EXPECT_EQ(9u, Encoder::MaxEncodedSize(kAddress, {}));
184   EXPECT_EQ(10u, Encoder::MaxEncodedSize(kEscapeAddress, {}));
185 }
186
187 TEST(Encoder, MaxEncodedSize_PayloadWithoutEscapes) {
188   constexpr auto data = bytes::Array<0x00, 0x01, 0x02, 0x03>();
189   EXPECT_EQ(13u, Encoder::MaxEncodedSize(kAddress, data));
190   EXPECT_EQ(14u, Encoder::MaxEncodedSize(kEscapeAddress, data));
191 }
192
193 TEST(Encoder, MaxEncodedSize_PayloadWithOneEscape) {
194   constexpr auto data = bytes::Array<0x00, 0x01, 0x7e, 0x03>();
195   EXPECT_EQ(14u, Encoder::MaxEncodedSize(kAddress, data));
196   EXPECT_EQ(15u, Encoder::MaxEncodedSize(kEscapeAddress, data));
197 }
198
199 TEST(Encoder, MaxEncodedSize_PayloadWithAllEscapes) {
200   constexpr auto data = bytes::Initialized<8>(0x7e);
201   EXPECT_EQ(25u, Encoder::MaxEncodedSize(kAddress, data));
202   EXPECT_EQ(26u, Encoder::MaxEncodedSize(kEscapeAddress, data));
203 }
204
205 }  // namespace
206 }  // namespace internal
207 }  // namespace pw::hdlc