blob: 1edff7a33c6eb66b06206502366e48170c12f5ae [file] [log] [blame]
Alexei Frolov5d6d3922020-05-08 13:57:02 -07001// 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 Hepler0f262352020-07-29 09:51:27 -070018#include "pw_bytes/array.h"
Wyatt Hepler142616c2020-06-01 10:16:04 -070019#include "pw_protobuf/wire_format.h"
Alexei Frolov5d6d3922020-05-08 13:57:02 -070020
21namespace pw::rpc::internal {
22namespace {
23
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070024using protobuf::FieldKey;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070025using std::byte;
26
Wyatt Hepler0f262352020-07-29 09:51:27 -070027constexpr auto kPayload = bytes::Array<0x82, 0x02, 0xff, 0xff>();
Wyatt Hepler142616c2020-06-01 10:16:04 -070028
Wyatt Hepler0f262352020-07-29 09:51:27 -070029constexpr auto kEncoded = bytes::Array<
Wyatt Hepler142616c2020-06-01 10:16:04 -070030 // Payload
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070031 uint32_t(FieldKey(5, protobuf::WireType::kDelimited)),
Wyatt Hepler0f262352020-07-29 09:51:27 -070032 0x04,
33 0x82,
34 0x02,
35 0xff,
36 0xff,
Wyatt Hepler142616c2020-06-01 10:16:04 -070037
38 // Packet type
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070039 uint32_t(FieldKey(1, protobuf::WireType::kVarint)),
Wyatt Hepler0f262352020-07-29 09:51:27 -070040 1, // RESPONSE
Wyatt Hepler142616c2020-06-01 10:16:04 -070041
42 // Channel ID
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070043 uint32_t(FieldKey(2, protobuf::WireType::kVarint)),
Wyatt Hepler0f262352020-07-29 09:51:27 -070044 1,
Wyatt Hepler142616c2020-06-01 10:16:04 -070045
46 // Service ID
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070047 uint32_t(FieldKey(3, protobuf::WireType::kFixed32)),
Wyatt Hepler0f262352020-07-29 09:51:27 -070048 42,
49 0,
50 0,
51 0,
Wyatt Hepler142616c2020-06-01 10:16:04 -070052
53 // Method ID
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070054 uint32_t(FieldKey(4, protobuf::WireType::kFixed32)),
Wyatt Hepler0f262352020-07-29 09:51:27 -070055 100,
56 0,
57 0,
Alexei Frolov86e05de2021-10-19 16:52:31 -070058 0,
Wyatt Hepler142616c2020-06-01 10:16:04 -070059
Wyatt Hepler5ba80642021-06-18 12:56:17 -070060 // Status (not encoded if it is zero)
Alexei Frolov5ebf8ad2021-09-02 16:55:15 -070061 // FieldKey(6, protobuf::WireType::kVarint),
Wyatt Hepler5ba80642021-06-18 12:56:17 -070062 // 0x00
Alexei Frolov86e05de2021-10-19 16:52:31 -070063
64 // Call ID
65 uint32_t(FieldKey(7, protobuf::WireType::kVarint)),
66 7>();
Wyatt Hepler142616c2020-06-01 10:16:04 -070067
Wyatt Heplerba43a3c2020-08-13 12:45:25 -070068// Test that a default-constructed packet sets its members to the default
Wyatt Hepler8664c662020-08-12 18:40:48 -070069// protobuf values.
70static_assert(Packet().type() == PacketType{});
71static_assert(Packet().channel_id() == 0);
72static_assert(Packet().service_id() == 0);
73static_assert(Packet().method_id() == 0);
74static_assert(Packet().status() == static_cast<Status::Code>(0));
75static_assert(Packet().payload().empty());
76
Wyatt Hepler142616c2020-06-01 10:16:04 -070077TEST(Packet, Encode) {
78 byte buffer[64];
79
Alexei Frolov86e05de2021-10-19 16:52:31 -070080 Packet packet(PacketType::RESPONSE, 1, 42, 100, 7, kPayload);
Wyatt Hepler142616c2020-06-01 10:16:04 -070081
Alexei Frolov3f2d0082020-10-04 22:30:39 -070082 auto result = packet.Encode(buffer);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080083 ASSERT_EQ(OkStatus(), result.status());
Alexei Frolov3f2d0082020-10-04 22:30:39 -070084 ASSERT_EQ(kEncoded.size(), result.value().size());
Wyatt Hepler0f262352020-07-29 09:51:27 -070085 EXPECT_EQ(std::memcmp(kEncoded.data(), buffer, kEncoded.size()), 0);
Wyatt Hepler142616c2020-06-01 10:16:04 -070086}
87
Wyatt Hepler712d3672020-07-13 15:52:11 -070088TEST(Packet, Encode_BufferTooSmall) {
89 byte buffer[2];
90
Alexei Frolov86e05de2021-10-19 16:52:31 -070091 Packet packet(PacketType::RESPONSE, 1, 42, 100, 0, kPayload);
Wyatt Hepler712d3672020-07-13 15:52:11 -070092
Alexei Frolov3f2d0082020-10-04 22:30:39 -070093 auto result = packet.Encode(buffer);
94 EXPECT_EQ(Status::ResourceExhausted(), result.status());
Wyatt Hepler712d3672020-07-13 15:52:11 -070095}
96
97TEST(Packet, Decode_ValidPacket) {
Alexei Frolov3f2d0082020-10-04 22:30:39 -070098 auto result = Packet::FromBuffer(kEncoded);
99 ASSERT_TRUE(result.ok());
Wyatt Hepler142616c2020-06-01 10:16:04 -0700100
Alexei Frolov3f2d0082020-10-04 22:30:39 -0700101 auto& packet = result.value();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700102 EXPECT_EQ(PacketType::RESPONSE, packet.type());
Wyatt Hepler142616c2020-06-01 10:16:04 -0700103 EXPECT_EQ(1u, packet.channel_id());
104 EXPECT_EQ(42u, packet.service_id());
105 EXPECT_EQ(100u, packet.method_id());
Alexei Frolov86e05de2021-10-19 16:52:31 -0700106 EXPECT_EQ(7u, packet.call_id());
Wyatt Hepler142616c2020-06-01 10:16:04 -0700107 ASSERT_EQ(sizeof(kPayload), packet.payload().size());
Wyatt Hepler0f262352020-07-29 09:51:27 -0700108 EXPECT_EQ(
109 0,
110 std::memcmp(packet.payload().data(), kPayload.data(), kPayload.size()));
Wyatt Hepler142616c2020-06-01 10:16:04 -0700111}
112
Wyatt Hepler712d3672020-07-13 15:52:11 -0700113TEST(Packet, Decode_InvalidPacket) {
114 byte bad_data[] = {byte{0xFF}, byte{0x00}, byte{0x00}, byte{0xFF}};
Alexei Frolov3f2d0082020-10-04 22:30:39 -0700115 EXPECT_EQ(Status::DataLoss(), Packet::FromBuffer(bad_data).status());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700116}
117
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700118TEST(Packet, EncodeDecode) {
119 constexpr byte payload[]{byte(0x00), byte(0x01), byte(0x02), byte(0x03)};
120
Wyatt Hepler712d3672020-07-13 15:52:11 -0700121 Packet packet;
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700122 packet.set_channel_id(12);
123 packet.set_service_id(0xdeadbeef);
124 packet.set_method_id(0x03a82921);
Alexei Frolov86e05de2021-10-19 16:52:31 -0700125 packet.set_call_id(33);
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700126 packet.set_payload(payload);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700127 packet.set_status(Status::Unavailable());
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700128
129 byte buffer[128];
Alexei Frolov3f2d0082020-10-04 22:30:39 -0700130 Result result = packet.Encode(buffer);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800131 ASSERT_EQ(result.status(), OkStatus());
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700132
Alexei Frolov3f2d0082020-10-04 22:30:39 -0700133 std::span<byte> packet_data(buffer, result.value().size());
134 auto decode_result = Packet::FromBuffer(packet_data);
135 ASSERT_TRUE(decode_result.ok());
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700136
Alexei Frolov3f2d0082020-10-04 22:30:39 -0700137 auto& decoded = decode_result.value();
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700138 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 Frolov86e05de2021-10-19 16:52:31 -0700142 EXPECT_EQ(decoded.call_id(), packet.call_id());
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700143 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 Heplerd78f7c62020-09-28 14:27:32 -0700148 EXPECT_EQ(decoded.status(), Status::Unavailable());
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700149}
150
Wyatt Hepler671946e2020-06-09 14:39:33 -0700151constexpr size_t kReservedSize = 2 /* type */ + 2 /* channel */ +
Wyatt Hepler712d3672020-07-13 15:52:11 -0700152 5 /* service */ + 5 /* method */ +
Wyatt Hepler671946e2020-06-09 14:39:33 -0700153 2 /* payload key */ + 2 /* status */;
Wyatt Hepler142616c2020-06-01 10:16:04 -0700154
155TEST(Packet, PayloadUsableSpace_ExactFit) {
Wyatt Hepler671946e2020-06-09 14:39:33 -0700156 EXPECT_EQ(kReservedSize,
Wyatt Hepler0f262352020-07-29 09:51:27 -0700157 Packet(PacketType::RESPONSE, 1, 42, 100).MinEncodedSizeBytes());
Wyatt Hepler142616c2020-06-01 10:16:04 -0700158}
159
160TEST(Packet, PayloadUsableSpace_LargerVarints) {
Wyatt Hepler0f262352020-07-29 09:51:27 -0700161 EXPECT_EQ(
162 kReservedSize + 2 /* channel */, // service and method are Fixed32
163 Packet(PacketType::RESPONSE, 17000, 200, 200).MinEncodedSizeBytes());
Wyatt Hepler142616c2020-06-01 10:16:04 -0700164}
165
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700166} // namespace
167} // namespace pw::rpc::internal