shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 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 | |
Alexei Frolov | d3e5cb7 | 2021-01-08 13:08:45 -0800 | [diff] [blame] | 15 | #include "pw_hdlc/decoder.h" |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 16 | |
| 17 | #include <array> |
| 18 | #include <cstddef> |
| 19 | |
| 20 | #include "gtest/gtest.h" |
| 21 | #include "pw_bytes/array.h" |
Alexei Frolov | b9fda58 | 2021-03-13 18:02:52 -0800 | [diff] [blame] | 22 | #include "pw_hdlc/internal/protocol.h" |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 23 | |
Alexei Frolov | d3e5cb7 | 2021-01-08 13:08:45 -0800 | [diff] [blame] | 24 | namespace pw::hdlc { |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 25 | namespace { |
| 26 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 27 | using std::byte; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 28 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 29 | TEST(Frame, Fields) { |
Alexei Frolov | b9fda58 | 2021-03-13 18:02:52 -0800 | [diff] [blame] | 30 | static constexpr auto kFrameData = |
| 31 | bytes::String("\x05\xab\x42\x24\xf9\x54\xfb\x3d"); |
| 32 | auto result = Frame::Parse(kFrameData); |
| 33 | ASSERT_TRUE(result.ok()); |
| 34 | Frame& frame = result.value(); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 35 | |
Alexei Frolov | b9fda58 | 2021-03-13 18:02:52 -0800 | [diff] [blame] | 36 | EXPECT_EQ(frame.address(), 2u); |
| 37 | EXPECT_EQ(frame.control(), byte{0xab}); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 38 | |
Alexei Frolov | b9fda58 | 2021-03-13 18:02:52 -0800 | [diff] [blame] | 39 | EXPECT_EQ(frame.data().size(), 2u); |
| 40 | EXPECT_EQ(frame.data()[0], byte{0x42}); |
| 41 | EXPECT_EQ(frame.data()[1], byte{0x24}); |
| 42 | } |
| 43 | |
| 44 | TEST(Frame, MultibyteAddress) { |
| 45 | static constexpr auto kFrameData = |
| 46 | bytes::String("\x2c\xd9\x33\x01\x02\xaf\xc8\x77\x48"); |
| 47 | auto result = Frame::Parse(kFrameData); |
| 48 | ASSERT_TRUE(result.ok()); |
| 49 | Frame& frame = result.value(); |
| 50 | |
| 51 | EXPECT_EQ(frame.address(), 0b11011000010110u); |
| 52 | EXPECT_EQ(frame.control(), byte{0x33}); |
| 53 | |
| 54 | EXPECT_EQ(frame.data().size(), 2u); |
| 55 | EXPECT_EQ(frame.data()[0], byte{0x01}); |
| 56 | EXPECT_EQ(frame.data()[1], byte{0x02}); |
| 57 | } |
| 58 | |
| 59 | TEST(Frame, MultibyteAddressTooLong) { |
| 60 | // 11-byte encoded address. |
| 61 | constexpr auto kLongAddress = |
| 62 | bytes::String("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"); |
| 63 | static constexpr auto kFrameData = bytes::Concat( |
| 64 | kLongAddress, bytes::String("\x33\x01\x02\xaf\xc8\x77\x48")); |
| 65 | auto result = Frame::Parse(kFrameData); |
| 66 | EXPECT_EQ(result.status(), Status::DataLoss()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 67 | } |
| 68 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 69 | TEST(Decoder, Clear) { |
| 70 | DecoderBuffer<8> decoder; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 71 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 72 | // Process a partial packet |
| 73 | decoder.Process(bytes::String("~1234abcd"), |
| 74 | [](const Result<Frame>&) { FAIL(); }); |
| 75 | |
Alexei Frolov | 5039a81 | 2021-01-20 15:14:06 -0800 | [diff] [blame] | 76 | decoder.Clear(); |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 77 | Status status = Status::Unknown(); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 78 | |
| 79 | decoder.Process( |
| 80 | bytes::String("~1234\xa3\xe0\xe3\x9b~"), |
| 81 | [&status](const Result<Frame>& result) { status = result.status(); }); |
| 82 | |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 83 | EXPECT_EQ(OkStatus(), status); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 84 | } |
| 85 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 86 | TEST(Decoder, ExactFit) { |
| 87 | DecoderBuffer<8> decoder; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 88 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 89 | for (byte b : bytes::String("~1234\xa3\xe0\xe3\x9b")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 90 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 91 | } |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 92 | auto result = decoder.Process(kFlag); |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 93 | ASSERT_EQ(OkStatus(), result.status()); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 94 | ASSERT_EQ(result.value().data().size(), 2u); |
| 95 | ASSERT_EQ(result.value().data()[0], byte{'3'}); |
| 96 | ASSERT_EQ(result.value().data()[1], byte{'4'}); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 97 | } |
| 98 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 99 | TEST(Decoder, MinimumSizedBuffer) { |
| 100 | DecoderBuffer<6> decoder; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 101 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 102 | for (byte b : bytes::String("~12\xcd\x44\x53\x4f")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 103 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 104 | } |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 105 | |
| 106 | auto result = decoder.Process(kFlag); |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 107 | ASSERT_EQ(OkStatus(), result.status()); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 108 | EXPECT_EQ(result.value().data().size(), 0u); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 109 | } |
| 110 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 111 | TEST(Decoder, TooLargeForBuffer_ReportsResourceExhausted) { |
| 112 | DecoderBuffer<8> decoder; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 113 | |
Alexei Frolov | 5039a81 | 2021-01-20 15:14:06 -0800 | [diff] [blame] | 114 | for (byte b : bytes::String("~12345\x1c\x3a\xf5\xcb")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 115 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 116 | } |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 117 | EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status()); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 118 | |
Alexei Frolov | 5039a81 | 2021-01-20 15:14:06 -0800 | [diff] [blame] | 119 | for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 120 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 121 | } |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 122 | EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 123 | } |
| 124 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 125 | TEST(Decoder, TooLargeForBuffer_StaysWithinBufferBoundaries) { |
| 126 | std::array<byte, 16> buffer = bytes::Initialized<16>('?'); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 127 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 128 | Decoder decoder(std::span(buffer.data(), 8)); |
| 129 | |
Alexei Frolov | 5039a81 | 2021-01-20 15:14:06 -0800 | [diff] [blame] | 130 | for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 131 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 132 | } |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 133 | |
| 134 | for (size_t i = 8; i < buffer.size(); ++i) { |
| 135 | ASSERT_EQ(byte{'?'}, buffer[i]); |
| 136 | } |
| 137 | |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 138 | EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 139 | } |
| 140 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 141 | TEST(Decoder, TooLargeForBuffer_DecodesNextFrame) { |
| 142 | DecoderBuffer<8> decoder; |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 143 | |
Alexei Frolov | 5039a81 | 2021-01-20 15:14:06 -0800 | [diff] [blame] | 144 | for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 145 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 146 | } |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 147 | EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 148 | |
Wyatt Hepler | cdb0f4e | 2020-09-14 08:49:17 -0700 | [diff] [blame] | 149 | for (byte b : bytes::String("1234\xa3\xe0\xe3\x9b")) { |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 150 | EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 151 | } |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 152 | EXPECT_EQ(OkStatus(), decoder.Process(kFlag).status()); |
shaneajg | 063d0e0 | 2020-08-03 11:57:41 -0400 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | } // namespace |
Alexei Frolov | d3e5cb7 | 2021-01-08 13:08:45 -0800 | [diff] [blame] | 156 | } // namespace pw::hdlc |