xref: /aosp_15_r20/external/pigweed/pw_protobuf/decoder_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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_protobuf/decoder.h"
16 
17 #include <cstring>
18 
19 #include "pw_preprocessor/util.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace pw::protobuf {
23 namespace {
24 
25 class TestDecodeHandler : public DecodeHandler {
26  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)27   Status ProcessField(CallbackDecoder& decoder,
28                       uint32_t field_number) override {
29     std::string_view str;
30 
31     switch (field_number) {
32       case 1:
33         EXPECT_EQ(OkStatus(), decoder.ReadInt32(&test_int32));
34         break;
35       case 2:
36         EXPECT_EQ(OkStatus(), decoder.ReadSint32(&test_sint32));
37         break;
38       case 3:
39         EXPECT_EQ(OkStatus(), decoder.ReadBool(&test_bool));
40         break;
41       case 4:
42         EXPECT_EQ(OkStatus(), decoder.ReadDouble(&test_double));
43         break;
44       case 5:
45         EXPECT_EQ(OkStatus(), decoder.ReadFixed32(&test_fixed32));
46         break;
47       case 6:
48         EXPECT_EQ(OkStatus(), decoder.ReadString(&str));
49         std::memcpy(test_string, str.data(), str.size());
50         test_string[str.size()] = '\0';
51         break;
52     }
53 
54     called = true;
55     return OkStatus();
56   }
57 
58   bool called = false;
59   int32_t test_int32 = 0;
60   int32_t test_sint32 = 0;
61   bool test_bool = true;
62   double test_double = 0;
63   uint32_t test_fixed32 = 0;
64   char test_string[16];
65 };
66 
TEST(Decoder,Decode)67 TEST(Decoder, Decode) {
68   // clang-format off
69   uint8_t encoded_proto[] = {
70     // type=int32, k=1, v=42
71     0x08, 0x2a,
72     // type=sint32, k=2, v=-13
73     0x10, 0x19,
74     // type=bool, k=3, v=false
75     0x18, 0x00,
76     // type=double, k=4, v=3.14159
77     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
78     // type=fixed32, k=5, v=0xdeadbeef
79     0x2d, 0xef, 0xbe, 0xad, 0xde,
80     // type=string, k=6, v="Hello world"
81     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
82   };
83   // clang-format on
84 
85   Decoder decoder(as_bytes(span(encoded_proto)));
86 
87   int32_t v1 = 0;
88   EXPECT_EQ(decoder.Next(), OkStatus());
89   ASSERT_EQ(decoder.FieldNumber(), 1u);
90   EXPECT_EQ(decoder.ReadInt32(&v1), OkStatus());
91   EXPECT_EQ(v1, 42);
92 
93   int32_t v2 = 0;
94   EXPECT_EQ(decoder.Next(), OkStatus());
95   ASSERT_EQ(decoder.FieldNumber(), 2u);
96   EXPECT_EQ(decoder.ReadSint32(&v2), OkStatus());
97   EXPECT_EQ(v2, -13);
98 
99   bool v3 = true;
100   EXPECT_EQ(decoder.Next(), OkStatus());
101   ASSERT_EQ(decoder.FieldNumber(), 3u);
102   EXPECT_EQ(decoder.ReadBool(&v3), OkStatus());
103   EXPECT_FALSE(v3);
104 
105   double v4 = 0;
106   EXPECT_EQ(decoder.Next(), OkStatus());
107   ASSERT_EQ(decoder.FieldNumber(), 4u);
108   EXPECT_EQ(decoder.ReadDouble(&v4), OkStatus());
109   EXPECT_EQ(v4, 3.14159);
110 
111   uint32_t v5 = 0;
112   EXPECT_EQ(decoder.Next(), OkStatus());
113   ASSERT_EQ(decoder.FieldNumber(), 5u);
114   EXPECT_EQ(decoder.ReadFixed32(&v5), OkStatus());
115   EXPECT_EQ(v5, 0xdeadbeef);
116 
117   std::string_view v6;
118   char buffer[16];
119   EXPECT_EQ(decoder.Next(), OkStatus());
120   ASSERT_EQ(decoder.FieldNumber(), 6u);
121   EXPECT_EQ(decoder.ReadString(&v6), OkStatus());
122   std::memcpy(buffer, v6.data(), v6.size());
123   buffer[v6.size()] = '\0';
124   EXPECT_STREQ(buffer, "Hello world");
125 
126   EXPECT_EQ(decoder.Next(), Status::OutOfRange());
127 }
128 
TEST(Decoder,Decode_SkipsUnusedFields)129 TEST(Decoder, Decode_SkipsUnusedFields) {
130   // clang-format off
131   uint8_t encoded_proto[] = {
132     // type=int32, k=1, v=42
133     0x08, 0x2a,
134     // type=sint32, k=2, v=-13
135     0x10, 0x19,
136     // type=bool, k=3, v=false
137     0x18, 0x00,
138     // type=double, k=4, v=3.14159
139     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
140     // type=fixed32, k=5, v=0xdeadbeef
141     0x2d, 0xef, 0xbe, 0xad, 0xde,
142     // type=string, k=6, v="Hello world"
143     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
144   };
145   // clang-format on
146 
147   Decoder decoder(as_bytes(span(encoded_proto)));
148 
149   // Don't process any fields except for the fourth. Next should still iterate
150   // correctly despite field values not being consumed.
151   EXPECT_EQ(decoder.Next(), OkStatus());
152   EXPECT_EQ(decoder.Next(), OkStatus());
153   EXPECT_EQ(decoder.Next(), OkStatus());
154   EXPECT_EQ(decoder.Next(), OkStatus());
155   ASSERT_EQ(decoder.FieldNumber(), 4u);
156   EXPECT_EQ(decoder.Next(), OkStatus());
157   EXPECT_EQ(decoder.Next(), OkStatus());
158   EXPECT_EQ(decoder.Next(), Status::OutOfRange());
159 }
160 
TEST(Decoder,Decode_BadFieldNumber)161 TEST(Decoder, Decode_BadFieldNumber) {
162   // clang-format off
163   constexpr uint8_t encoded_proto[] = {
164     // type=int32, k=1, v=42
165     0x08, 0x2a,
166     // type=int32, k=19001, v=42 (invalid field number)
167     0xc8, 0xa3, 0x09, 0x2a,
168     // type=bool, k=3, v=false
169     0x18, 0x00,
170   };
171   // clang-format on
172 
173   Decoder decoder(as_bytes(span(encoded_proto)));
174   int32_t value;
175 
176   EXPECT_EQ(decoder.Next(), OkStatus());
177   EXPECT_EQ(decoder.FieldNumber(), 1u);
178   ASSERT_EQ(decoder.ReadInt32(&value), OkStatus());
179   EXPECT_EQ(value, 42);
180 
181   // Bad field.
182   EXPECT_EQ(decoder.Next(), Status::DataLoss());
183   EXPECT_EQ(decoder.FieldNumber(), 0u);
184   EXPECT_EQ(decoder.ReadInt32(&value), Status::DataLoss());
185 }
186 
TEST(CallbackDecoder,Decode)187 TEST(CallbackDecoder, Decode) {
188   CallbackDecoder decoder;
189   TestDecodeHandler handler;
190 
191   // clang-format off
192   uint8_t encoded_proto[] = {
193     // type=int32, k=1, v=42
194     0x08, 0x2a,
195     // type=sint32, k=2, v=-13
196     0x10, 0x19,
197     // type=bool, k=3, v=false
198     0x18, 0x00,
199     // type=double, k=4, v=3.14159
200     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
201     // type=fixed32, k=5, v=0xdeadbeef
202     0x2d, 0xef, 0xbe, 0xad, 0xde,
203     // type=string, k=6, v="Hello world"
204     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
205   };
206   // clang-format on
207 
208   decoder.set_handler(&handler);
209   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
210   EXPECT_TRUE(handler.called);
211   EXPECT_EQ(handler.test_int32, 42);
212   EXPECT_EQ(handler.test_sint32, -13);
213   EXPECT_FALSE(handler.test_bool);
214   EXPECT_EQ(handler.test_double, 3.14159);
215   EXPECT_EQ(handler.test_fixed32, 0xdeadbeef);
216   EXPECT_STREQ(handler.test_string, "Hello world");
217 }
218 
TEST(CallbackDecoder,Decode_OverridesDuplicateFields)219 TEST(CallbackDecoder, Decode_OverridesDuplicateFields) {
220   CallbackDecoder decoder;
221   TestDecodeHandler handler;
222 
223   // clang-format off
224   uint8_t encoded_proto[] = {
225     // type=int32, k=1, v=42
226     0x08, 0x2a,
227     // type=int32, k=1, v=43
228     0x08, 0x2b,
229     // type=int32, k=1, v=44
230     0x08, 0x2c,
231   };
232   // clang-format on
233 
234   decoder.set_handler(&handler);
235   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
236   EXPECT_TRUE(handler.called);
237   EXPECT_EQ(handler.test_int32, 44);
238 }
239 
TEST(CallbackDecoder,Decode_Empty)240 TEST(CallbackDecoder, Decode_Empty) {
241   CallbackDecoder decoder;
242   TestDecodeHandler handler;
243 
244   decoder.set_handler(&handler);
245   EXPECT_EQ(decoder.Decode(span<std::byte>()), OkStatus());
246   EXPECT_FALSE(handler.called);
247   EXPECT_EQ(handler.test_int32, 0);
248   EXPECT_EQ(handler.test_sint32, 0);
249 }
250 
TEST(CallbackDecoder,Decode_BadData)251 TEST(CallbackDecoder, Decode_BadData) {
252   CallbackDecoder decoder;
253   TestDecodeHandler handler;
254 
255   // Field key without a value.
256   uint8_t encoded_proto[] = {0x08};
257 
258   decoder.set_handler(&handler);
259   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::DataLoss());
260 }
261 
262 // Only processes fields numbered 1 or 3.
263 class OneThreeDecodeHandler : public DecodeHandler {
264  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)265   Status ProcessField(CallbackDecoder& decoder,
266                       uint32_t field_number) override {
267     switch (field_number) {
268       case 1:
269         EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
270         break;
271       case 3:
272         EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
273         break;
274       default:
275         // Do nothing.
276         break;
277     }
278 
279     called = true;
280     return OkStatus();
281   }
282 
283   bool called = false;
284   int32_t field_one = 0;
285   int32_t field_three = 0;
286 };
287 
TEST(CallbackDecoder,Decode_SkipsUnprocessedFields)288 TEST(CallbackDecoder, Decode_SkipsUnprocessedFields) {
289   CallbackDecoder decoder;
290   OneThreeDecodeHandler handler;
291 
292   // clang-format off
293   uint8_t encoded_proto[] = {
294     // type=int32, k=1, v=42
295     // Should be read.
296     0x08, 0x2a,
297     // type=sint32, k=2, v=-13
298     // Should be ignored.
299     0x10, 0x19,
300     // type=int32, k=2, v=3
301     // Should be ignored.
302     0x10, 0x03,
303     // type=int32, k=3, v=99
304     // Should be read.
305     0x18, 0x63,
306     // type=int32, k=4, v=16
307     // Should be ignored.
308     0x20, 0x10,
309   };
310   // clang-format on
311 
312   decoder.set_handler(&handler);
313   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
314   EXPECT_TRUE(handler.called);
315   EXPECT_EQ(handler.field_one, 42);
316   EXPECT_EQ(handler.field_three, 99);
317 }
318 
319 // Only processes fields numbered 1 or 3, and stops the decode after hitting 1.
320 class ExitOnOneDecoder : public DecodeHandler {
321  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)322   Status ProcessField(CallbackDecoder& decoder,
323                       uint32_t field_number) override {
324     switch (field_number) {
325       case 1:
326         EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
327         return Status::Cancelled();
328       case 3:
329         EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
330         break;
331       default:
332         // Do nothing.
333         break;
334     }
335 
336     return OkStatus();
337   }
338 
339   int32_t field_one = 0;
340   int32_t field_three = 1111;
341 };
342 
TEST(CallbackDecoder,Decode_StopsOnNonOkStatus)343 TEST(CallbackDecoder, Decode_StopsOnNonOkStatus) {
344   CallbackDecoder decoder;
345   ExitOnOneDecoder handler;
346 
347   // clang-format off
348   uint8_t encoded_proto[] = {
349     // type=int32, k=1, v=42
350     // Should be read.
351     0x08, 0x2a,
352     // type=int32, k=3, v=99
353     // Should be skipped.
354     0x18, 0x63,
355     // type=int32, k=2, v=16
356     // Should be skipped.
357     0x08, 0x10,
358   };
359   // clang-format on
360 
361   decoder.set_handler(&handler);
362   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::Cancelled());
363   EXPECT_EQ(handler.field_one, 42);
364   EXPECT_EQ(handler.field_three, 1111);
365 }
366 
367 }  // namespace
368 }  // namespace pw::protobuf
369