xref: /aosp_15_r20/external/pigweed/pw_rpc/packet_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/packet.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/array.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_fuzzer/fuzztest.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/wire_format.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
21*61c4878aSAndroid Build Coastguard Worker 
22*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc::internal {
23*61c4878aSAndroid Build Coastguard Worker namespace {
24*61c4878aSAndroid Build Coastguard Worker 
25*61c4878aSAndroid Build Coastguard Worker using protobuf::FieldKey;
26*61c4878aSAndroid Build Coastguard Worker using ::pw::rpc::internal::pwpb::PacketType;
27*61c4878aSAndroid Build Coastguard Worker using std::byte;
28*61c4878aSAndroid Build Coastguard Worker using namespace fuzzer;
29*61c4878aSAndroid Build Coastguard Worker 
30*61c4878aSAndroid Build Coastguard Worker constexpr auto kPayload = bytes::Array<0x82, 0x02, 0xff, 0xff>();
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker constexpr auto kEncoded = bytes::Array<
33*61c4878aSAndroid Build Coastguard Worker     // Payload
34*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(5, protobuf::WireType::kDelimited)),
35*61c4878aSAndroid Build Coastguard Worker     0x04,
36*61c4878aSAndroid Build Coastguard Worker     0x82,
37*61c4878aSAndroid Build Coastguard Worker     0x02,
38*61c4878aSAndroid Build Coastguard Worker     0xff,
39*61c4878aSAndroid Build Coastguard Worker     0xff,
40*61c4878aSAndroid Build Coastguard Worker 
41*61c4878aSAndroid Build Coastguard Worker     // Packet type
42*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(1, protobuf::WireType::kVarint)),
43*61c4878aSAndroid Build Coastguard Worker     1,  // RESPONSE
44*61c4878aSAndroid Build Coastguard Worker 
45*61c4878aSAndroid Build Coastguard Worker     // Channel ID
46*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(2, protobuf::WireType::kVarint)),
47*61c4878aSAndroid Build Coastguard Worker     1,
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker     // Service ID
50*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(3, protobuf::WireType::kFixed32)),
51*61c4878aSAndroid Build Coastguard Worker     42,
52*61c4878aSAndroid Build Coastguard Worker     0,
53*61c4878aSAndroid Build Coastguard Worker     0,
54*61c4878aSAndroid Build Coastguard Worker     0,
55*61c4878aSAndroid Build Coastguard Worker 
56*61c4878aSAndroid Build Coastguard Worker     // Method ID
57*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(4, protobuf::WireType::kFixed32)),
58*61c4878aSAndroid Build Coastguard Worker     100,
59*61c4878aSAndroid Build Coastguard Worker     0,
60*61c4878aSAndroid Build Coastguard Worker     0,
61*61c4878aSAndroid Build Coastguard Worker     0,
62*61c4878aSAndroid Build Coastguard Worker 
63*61c4878aSAndroid Build Coastguard Worker     // Status (not encoded if it is zero)
64*61c4878aSAndroid Build Coastguard Worker     // FieldKey(6, protobuf::WireType::kVarint),
65*61c4878aSAndroid Build Coastguard Worker     // 0x00
66*61c4878aSAndroid Build Coastguard Worker 
67*61c4878aSAndroid Build Coastguard Worker     // Call ID
68*61c4878aSAndroid Build Coastguard Worker     uint32_t(FieldKey(7, protobuf::WireType::kVarint)),
69*61c4878aSAndroid Build Coastguard Worker     7>();
70*61c4878aSAndroid Build Coastguard Worker 
71*61c4878aSAndroid Build Coastguard Worker // Test that a default-constructed packet sets its members to the default
72*61c4878aSAndroid Build Coastguard Worker // protobuf values.
73*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().type() == PacketType{});
74*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().channel_id() == 0);
75*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().service_id() == 0);
76*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().method_id() == 0);
77*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().status() == static_cast<Status::Code>(0));
78*61c4878aSAndroid Build Coastguard Worker static_assert(Packet().payload().empty());
79*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,Encode)80*61c4878aSAndroid Build Coastguard Worker TEST(Packet, Encode) {
81*61c4878aSAndroid Build Coastguard Worker   byte buffer[64];
82*61c4878aSAndroid Build Coastguard Worker 
83*61c4878aSAndroid Build Coastguard Worker   Packet packet(PacketType::RESPONSE, 1, 42, 100, 7, kPayload);
84*61c4878aSAndroid Build Coastguard Worker 
85*61c4878aSAndroid Build Coastguard Worker   auto result = packet.Encode(buffer);
86*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), result.status());
87*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(kEncoded.size(), result.value().size());
88*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(kEncoded.data(), buffer, kEncoded.size()), 0);
89*61c4878aSAndroid Build Coastguard Worker }
90*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,Encode_BufferTooSmall)91*61c4878aSAndroid Build Coastguard Worker TEST(Packet, Encode_BufferTooSmall) {
92*61c4878aSAndroid Build Coastguard Worker   byte buffer[2];
93*61c4878aSAndroid Build Coastguard Worker 
94*61c4878aSAndroid Build Coastguard Worker   Packet packet(PacketType::RESPONSE, 1, 42, 100, 12, kPayload);
95*61c4878aSAndroid Build Coastguard Worker 
96*61c4878aSAndroid Build Coastguard Worker   auto result = packet.Encode(buffer);
97*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::ResourceExhausted(), result.status());
98*61c4878aSAndroid Build Coastguard Worker }
99*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,Decode_ValidPacket)100*61c4878aSAndroid Build Coastguard Worker TEST(Packet, Decode_ValidPacket) {
101*61c4878aSAndroid Build Coastguard Worker   auto result = Packet::FromBuffer(kEncoded);
102*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
103*61c4878aSAndroid Build Coastguard Worker 
104*61c4878aSAndroid Build Coastguard Worker   auto& packet = result.value();
105*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(PacketType::RESPONSE, packet.type());
106*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, packet.channel_id());
107*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(42u, packet.service_id());
108*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(100u, packet.method_id());
109*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(7u, packet.call_id());
110*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(kPayload), packet.payload().size());
111*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
112*61c4878aSAndroid Build Coastguard Worker       0,
113*61c4878aSAndroid Build Coastguard Worker       std::memcmp(packet.payload().data(), kPayload.data(), kPayload.size()));
114*61c4878aSAndroid Build Coastguard Worker }
115*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,Decode_InvalidPacket)116*61c4878aSAndroid Build Coastguard Worker TEST(Packet, Decode_InvalidPacket) {
117*61c4878aSAndroid Build Coastguard Worker   byte bad_data[] = {byte{0xFF}, byte{0x00}, byte{0x00}, byte{0xFF}};
118*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::DataLoss(), Packet::FromBuffer(bad_data).status());
119*61c4878aSAndroid Build Coastguard Worker }
120*61c4878aSAndroid Build Coastguard Worker 
EncodeDecode(uint32_t channel_id,uint32_t service_id,uint32_t method_id,uint32_t call_id,ConstByteSpan payload,Status status)121*61c4878aSAndroid Build Coastguard Worker void EncodeDecode(uint32_t channel_id,
122*61c4878aSAndroid Build Coastguard Worker                   uint32_t service_id,
123*61c4878aSAndroid Build Coastguard Worker                   uint32_t method_id,
124*61c4878aSAndroid Build Coastguard Worker                   uint32_t call_id,
125*61c4878aSAndroid Build Coastguard Worker                   ConstByteSpan payload,
126*61c4878aSAndroid Build Coastguard Worker                   Status status) {
127*61c4878aSAndroid Build Coastguard Worker   Packet packet;
128*61c4878aSAndroid Build Coastguard Worker   packet.set_channel_id(channel_id);
129*61c4878aSAndroid Build Coastguard Worker   packet.set_service_id(service_id);
130*61c4878aSAndroid Build Coastguard Worker   packet.set_method_id(method_id);
131*61c4878aSAndroid Build Coastguard Worker   packet.set_call_id(call_id);
132*61c4878aSAndroid Build Coastguard Worker   packet.set_payload(payload);
133*61c4878aSAndroid Build Coastguard Worker   packet.set_status(status);
134*61c4878aSAndroid Build Coastguard Worker 
135*61c4878aSAndroid Build Coastguard Worker   byte buffer[128];
136*61c4878aSAndroid Build Coastguard Worker   Result result = packet.Encode(buffer);
137*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
138*61c4878aSAndroid Build Coastguard Worker 
139*61c4878aSAndroid Build Coastguard Worker   span<byte> packet_data(buffer, result.value().size());
140*61c4878aSAndroid Build Coastguard Worker   auto decode_result = Packet::FromBuffer(packet_data);
141*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(decode_result.ok());
142*61c4878aSAndroid Build Coastguard Worker 
143*61c4878aSAndroid Build Coastguard Worker   auto& decoded = decode_result.value();
144*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.type(), packet.type());
145*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.channel_id(), packet.channel_id());
146*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.service_id(), packet.service_id());
147*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.method_id(), packet.method_id());
148*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.call_id(), packet.call_id());
149*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(decoded.payload().size(), packet.payload().size());
150*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(decoded.payload().data(),
151*61c4878aSAndroid Build Coastguard Worker                         packet.payload().data(),
152*61c4878aSAndroid Build Coastguard Worker                         packet.payload().size()),
153*61c4878aSAndroid Build Coastguard Worker             0);
154*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(decoded.status(), status);
155*61c4878aSAndroid Build Coastguard Worker }
156*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,EncodeDecodeFixed)157*61c4878aSAndroid Build Coastguard Worker TEST(Packet, EncodeDecodeFixed) {
158*61c4878aSAndroid Build Coastguard Worker   constexpr byte payload[]{byte(0x00), byte(0x01), byte(0x02), byte(0x03)};
159*61c4878aSAndroid Build Coastguard Worker   EncodeDecode(12, 0xdeadbeef, 0x03a82921, 33, payload, Status::Unavailable());
160*61c4878aSAndroid Build Coastguard Worker }
161*61c4878aSAndroid Build Coastguard Worker 
162*61c4878aSAndroid Build Coastguard Worker FUZZ_TEST(Packet, EncodeDecode)
163*61c4878aSAndroid Build Coastguard Worker     .WithDomains(NonZero<uint32_t>(),
164*61c4878aSAndroid Build Coastguard Worker                  NonZero<uint32_t>(),
165*61c4878aSAndroid Build Coastguard Worker                  NonZero<uint32_t>(),
166*61c4878aSAndroid Build Coastguard Worker                  NonZero<uint32_t>(),
167*61c4878aSAndroid Build Coastguard Worker                  VectorOf<100>(Arbitrary<byte>()),
168*61c4878aSAndroid Build Coastguard Worker                  Arbitrary<Status>());
169*61c4878aSAndroid Build Coastguard Worker 
170*61c4878aSAndroid Build Coastguard Worker constexpr size_t kReservedSize = 2 /* type */ + 2 /* channel */ +
171*61c4878aSAndroid Build Coastguard Worker                                  5 /* service */ + 5 /* method */ +
172*61c4878aSAndroid Build Coastguard Worker                                  2 /* payload key */ + 2 /* status */;
173*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,PayloadUsableSpace_ExactFit)174*61c4878aSAndroid Build Coastguard Worker TEST(Packet, PayloadUsableSpace_ExactFit) {
175*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
176*61c4878aSAndroid Build Coastguard Worker       kReservedSize,
177*61c4878aSAndroid Build Coastguard Worker       Packet(PacketType::RESPONSE, 1, 42, 100, 28282).MinEncodedSizeBytes());
178*61c4878aSAndroid Build Coastguard Worker }
179*61c4878aSAndroid Build Coastguard Worker 
TEST(Packet,PayloadUsableSpace_LargerVarints)180*61c4878aSAndroid Build Coastguard Worker TEST(Packet, PayloadUsableSpace_LargerVarints) {
181*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(kReservedSize + 2 /* channel */,  // service and method are Fixed32
182*61c4878aSAndroid Build Coastguard Worker             Packet(PacketType::RESPONSE, 17000, 200, 200, 28282)
183*61c4878aSAndroid Build Coastguard Worker                 .MinEncodedSizeBytes());
184*61c4878aSAndroid Build Coastguard Worker }
185*61c4878aSAndroid Build Coastguard Worker 
186*61c4878aSAndroid Build Coastguard Worker }  // namespace
187*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc::internal
188