Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [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 | |
| 15 | #include "pw_rpc/internal/packet.h" |
| 16 | |
| 17 | #include "gtest/gtest.h" |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 18 | #include "pw_bytes/array.h" |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 19 | #include "pw_protobuf/wire_format.h" |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 20 | |
| 21 | namespace pw::rpc::internal { |
| 22 | namespace { |
| 23 | |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 24 | using protobuf::FieldKey; |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 25 | using std::byte; |
| 26 | |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 27 | constexpr auto kPayload = bytes::Array<0x82, 0x02, 0xff, 0xff>(); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 28 | |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 29 | constexpr auto kEncoded = bytes::Array< |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 30 | // Payload |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 31 | uint32_t(FieldKey(5, protobuf::WireType::kDelimited)), |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 32 | 0x04, |
| 33 | 0x82, |
| 34 | 0x02, |
| 35 | 0xff, |
| 36 | 0xff, |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 37 | |
| 38 | // Packet type |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 39 | uint32_t(FieldKey(1, protobuf::WireType::kVarint)), |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 40 | 1, // RESPONSE |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 41 | |
| 42 | // Channel ID |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 43 | uint32_t(FieldKey(2, protobuf::WireType::kVarint)), |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 44 | 1, |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 45 | |
| 46 | // Service ID |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 47 | uint32_t(FieldKey(3, protobuf::WireType::kFixed32)), |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 48 | 42, |
| 49 | 0, |
| 50 | 0, |
| 51 | 0, |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 52 | |
| 53 | // Method ID |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 54 | uint32_t(FieldKey(4, protobuf::WireType::kFixed32)), |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 55 | 100, |
| 56 | 0, |
| 57 | 0, |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 58 | 0, |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 59 | |
Wyatt Hepler | 5ba8064 | 2021-06-18 12:56:17 -0700 | [diff] [blame] | 60 | // Status (not encoded if it is zero) |
Alexei Frolov | 5ebf8ad | 2021-09-02 16:55:15 -0700 | [diff] [blame] | 61 | // FieldKey(6, protobuf::WireType::kVarint), |
Wyatt Hepler | 5ba8064 | 2021-06-18 12:56:17 -0700 | [diff] [blame] | 62 | // 0x00 |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 63 | |
| 64 | // Call ID |
| 65 | uint32_t(FieldKey(7, protobuf::WireType::kVarint)), |
| 66 | 7>(); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 67 | |
Wyatt Hepler | ba43a3c | 2020-08-13 12:45:25 -0700 | [diff] [blame] | 68 | // Test that a default-constructed packet sets its members to the default |
Wyatt Hepler | 8664c66 | 2020-08-12 18:40:48 -0700 | [diff] [blame] | 69 | // protobuf values. |
| 70 | static_assert(Packet().type() == PacketType{}); |
| 71 | static_assert(Packet().channel_id() == 0); |
| 72 | static_assert(Packet().service_id() == 0); |
| 73 | static_assert(Packet().method_id() == 0); |
| 74 | static_assert(Packet().status() == static_cast<Status::Code>(0)); |
| 75 | static_assert(Packet().payload().empty()); |
| 76 | |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 77 | TEST(Packet, Encode) { |
| 78 | byte buffer[64]; |
| 79 | |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 80 | Packet packet(PacketType::RESPONSE, 1, 42, 100, 7, kPayload); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 81 | |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 82 | auto result = packet.Encode(buffer); |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 83 | ASSERT_EQ(OkStatus(), result.status()); |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 84 | ASSERT_EQ(kEncoded.size(), result.value().size()); |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 85 | EXPECT_EQ(std::memcmp(kEncoded.data(), buffer, kEncoded.size()), 0); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 86 | } |
| 87 | |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 88 | TEST(Packet, Encode_BufferTooSmall) { |
| 89 | byte buffer[2]; |
| 90 | |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 91 | Packet packet(PacketType::RESPONSE, 1, 42, 100, 0, kPayload); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 92 | |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 93 | auto result = packet.Encode(buffer); |
| 94 | EXPECT_EQ(Status::ResourceExhausted(), result.status()); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | TEST(Packet, Decode_ValidPacket) { |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 98 | auto result = Packet::FromBuffer(kEncoded); |
| 99 | ASSERT_TRUE(result.ok()); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 100 | |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 101 | auto& packet = result.value(); |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 102 | EXPECT_EQ(PacketType::RESPONSE, packet.type()); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 103 | EXPECT_EQ(1u, packet.channel_id()); |
| 104 | EXPECT_EQ(42u, packet.service_id()); |
| 105 | EXPECT_EQ(100u, packet.method_id()); |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 106 | EXPECT_EQ(7u, packet.call_id()); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 107 | ASSERT_EQ(sizeof(kPayload), packet.payload().size()); |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 108 | EXPECT_EQ( |
| 109 | 0, |
| 110 | std::memcmp(packet.payload().data(), kPayload.data(), kPayload.size())); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 111 | } |
| 112 | |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 113 | TEST(Packet, Decode_InvalidPacket) { |
| 114 | byte bad_data[] = {byte{0xFF}, byte{0x00}, byte{0x00}, byte{0xFF}}; |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 115 | EXPECT_EQ(Status::DataLoss(), Packet::FromBuffer(bad_data).status()); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 116 | } |
| 117 | |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 118 | TEST(Packet, EncodeDecode) { |
| 119 | constexpr byte payload[]{byte(0x00), byte(0x01), byte(0x02), byte(0x03)}; |
| 120 | |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 121 | Packet packet; |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 122 | packet.set_channel_id(12); |
| 123 | packet.set_service_id(0xdeadbeef); |
| 124 | packet.set_method_id(0x03a82921); |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 125 | packet.set_call_id(33); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 126 | packet.set_payload(payload); |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 127 | packet.set_status(Status::Unavailable()); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 128 | |
| 129 | byte buffer[128]; |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 130 | Result result = packet.Encode(buffer); |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 131 | ASSERT_EQ(result.status(), OkStatus()); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 132 | |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 133 | std::span<byte> packet_data(buffer, result.value().size()); |
| 134 | auto decode_result = Packet::FromBuffer(packet_data); |
| 135 | ASSERT_TRUE(decode_result.ok()); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 136 | |
Alexei Frolov | 3f2d008 | 2020-10-04 22:30:39 -0700 | [diff] [blame] | 137 | auto& decoded = decode_result.value(); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 138 | EXPECT_EQ(decoded.type(), packet.type()); |
| 139 | EXPECT_EQ(decoded.channel_id(), packet.channel_id()); |
| 140 | EXPECT_EQ(decoded.service_id(), packet.service_id()); |
| 141 | EXPECT_EQ(decoded.method_id(), packet.method_id()); |
Alexei Frolov | 86e05de | 2021-10-19 16:52:31 -0700 | [diff] [blame] | 142 | EXPECT_EQ(decoded.call_id(), packet.call_id()); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 143 | ASSERT_EQ(decoded.payload().size(), packet.payload().size()); |
| 144 | EXPECT_EQ(std::memcmp(decoded.payload().data(), |
| 145 | packet.payload().data(), |
| 146 | packet.payload().size()), |
| 147 | 0); |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 148 | EXPECT_EQ(decoded.status(), Status::Unavailable()); |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 149 | } |
| 150 | |
Wyatt Hepler | 671946e | 2020-06-09 14:39:33 -0700 | [diff] [blame] | 151 | constexpr size_t kReservedSize = 2 /* type */ + 2 /* channel */ + |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 152 | 5 /* service */ + 5 /* method */ + |
Wyatt Hepler | 671946e | 2020-06-09 14:39:33 -0700 | [diff] [blame] | 153 | 2 /* payload key */ + 2 /* status */; |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 154 | |
| 155 | TEST(Packet, PayloadUsableSpace_ExactFit) { |
Wyatt Hepler | 671946e | 2020-06-09 14:39:33 -0700 | [diff] [blame] | 156 | EXPECT_EQ(kReservedSize, |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 157 | Packet(PacketType::RESPONSE, 1, 42, 100).MinEncodedSizeBytes()); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 158 | } |
| 159 | |
| 160 | TEST(Packet, PayloadUsableSpace_LargerVarints) { |
Wyatt Hepler | 0f26235 | 2020-07-29 09:51:27 -0700 | [diff] [blame] | 161 | EXPECT_EQ( |
| 162 | kReservedSize + 2 /* channel */, // service and method are Fixed32 |
| 163 | Packet(PacketType::RESPONSE, 17000, 200, 200).MinEncodedSizeBytes()); |
Wyatt Hepler | 142616c | 2020-06-01 10:16:04 -0700 | [diff] [blame] | 164 | } |
| 165 | |
Alexei Frolov | 5d6d392 | 2020-05-08 13:57:02 -0700 | [diff] [blame] | 166 | } // namespace |
| 167 | } // namespace pw::rpc::internal |