blob: abc9d540ea8d53268969eb2fd8a705e538320806 [file] [log] [blame]
Alexei Frolovdea46f72020-01-07 13:28:24 -08001// 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 "gtest/gtest.h"
18#include "pw_preprocessor/util.h"
19
20namespace pw::protobuf {
21namespace {
22
23class TestDecodeHandler : public DecodeHandler {
24 public:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070025 Status ProcessField(CallbackDecoder& decoder,
26 uint32_t field_number) override {
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080027 std::string_view str;
28
Alexei Frolovdea46f72020-01-07 13:28:24 -080029 switch (field_number) {
30 case 1:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070031 decoder.ReadInt32(&test_int32);
Alexei Frolovdea46f72020-01-07 13:28:24 -080032 break;
33 case 2:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070034 decoder.ReadSint32(&test_sint32);
Alexei Frolovdea46f72020-01-07 13:28:24 -080035 break;
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080036 case 3:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070037 decoder.ReadBool(&test_bool);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080038 break;
39 case 4:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070040 decoder.ReadDouble(&test_double);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080041 break;
42 case 5:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070043 decoder.ReadFixed32(&test_fixed32);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080044 break;
45 case 6:
Alexei Frolovfe9723c2020-05-11 13:20:47 -070046 decoder.ReadString(&str);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080047 std::memcpy(test_string, str.data(), str.size());
48 test_string[str.size()] = '\0';
49 break;
Alexei Frolovdea46f72020-01-07 13:28:24 -080050 }
51
52 called = true;
53 return Status::OK;
54 }
55
56 bool called = false;
57 int32_t test_int32 = 0;
58 int32_t test_sint32 = 0;
Alexei Frolov6d9b9b42020-01-14 12:57:33 -080059 bool test_bool = true;
60 double test_double = 0;
61 uint32_t test_fixed32 = 0;
62 char test_string[16];
Alexei Frolovdea46f72020-01-07 13:28:24 -080063};
64
65TEST(Decoder, Decode) {
Alexei Frolovfe9723c2020-05-11 13:20:47 -070066 // clang-format off
67 uint8_t encoded_proto[] = {
68 // type=int32, k=1, v=42
69 0x08, 0x2a,
70 // type=sint32, k=2, v=-13
71 0x10, 0x19,
72 // type=bool, k=3, v=false
73 0x18, 0x00,
74 // type=double, k=4, v=3.14159
75 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
76 // type=fixed32, k=5, v=0xdeadbeef
77 0x2d, 0xef, 0xbe, 0xad, 0xde,
78 // type=string, k=6, v="Hello world"
79 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
80 };
81 // clang-format on
82
83 Decoder decoder(as_bytes(span(encoded_proto)));
84
85 int32_t v1 = 0;
86 EXPECT_EQ(decoder.Next(), Status::OK);
87 ASSERT_EQ(decoder.FieldNumber(), 1u);
88 EXPECT_EQ(decoder.ReadInt32(&v1), Status::OK);
89 EXPECT_EQ(v1, 42);
90
91 int32_t v2 = 0;
92 EXPECT_EQ(decoder.Next(), Status::OK);
93 ASSERT_EQ(decoder.FieldNumber(), 2u);
94 EXPECT_EQ(decoder.ReadSint32(&v2), Status::OK);
95 EXPECT_EQ(v2, -13);
96
97 bool v3 = true;
98 EXPECT_EQ(decoder.Next(), Status::OK);
99 ASSERT_EQ(decoder.FieldNumber(), 3u);
100 EXPECT_EQ(decoder.ReadBool(&v3), Status::OK);
101 EXPECT_FALSE(v3);
102
103 double v4 = 0;
104 EXPECT_EQ(decoder.Next(), Status::OK);
105 ASSERT_EQ(decoder.FieldNumber(), 4u);
106 EXPECT_EQ(decoder.ReadDouble(&v4), Status::OK);
107 EXPECT_EQ(v4, 3.14159);
108
109 uint32_t v5 = 0;
110 EXPECT_EQ(decoder.Next(), Status::OK);
111 ASSERT_EQ(decoder.FieldNumber(), 5u);
112 EXPECT_EQ(decoder.ReadFixed32(&v5), Status::OK);
113 EXPECT_EQ(v5, 0xdeadbeef);
114
115 std::string_view v6;
116 char buffer[16];
117 EXPECT_EQ(decoder.Next(), Status::OK);
118 ASSERT_EQ(decoder.FieldNumber(), 6u);
119 EXPECT_EQ(decoder.ReadString(&v6), Status::OK);
120 std::memcpy(buffer, v6.data(), v6.size());
121 buffer[v6.size()] = '\0';
122 EXPECT_STREQ(buffer, "Hello world");
123
124 EXPECT_EQ(decoder.Next(), Status::OUT_OF_RANGE);
125}
126
127TEST(Decoder, Decode_SkipsUnusedFields) {
128 // clang-format off
129 uint8_t encoded_proto[] = {
130 // type=int32, k=1, v=42
131 0x08, 0x2a,
132 // type=sint32, k=2, v=-13
133 0x10, 0x19,
134 // type=bool, k=3, v=false
135 0x18, 0x00,
136 // type=double, k=4, v=3.14159
137 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
138 // type=fixed32, k=5, v=0xdeadbeef
139 0x2d, 0xef, 0xbe, 0xad, 0xde,
140 // type=string, k=6, v="Hello world"
141 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
142 };
143 // clang-format on
144
145 Decoder decoder(as_bytes(span(encoded_proto)));
146
147 // Don't process any fields except for the fourth. Next should still iterate
148 // correctly despite field values not being consumed.
149 EXPECT_EQ(decoder.Next(), Status::OK);
150 EXPECT_EQ(decoder.Next(), Status::OK);
151 EXPECT_EQ(decoder.Next(), Status::OK);
152 EXPECT_EQ(decoder.Next(), Status::OK);
153 ASSERT_EQ(decoder.FieldNumber(), 4u);
154 EXPECT_EQ(decoder.Next(), Status::OK);
155 EXPECT_EQ(decoder.Next(), Status::OK);
156 EXPECT_EQ(decoder.Next(), Status::OUT_OF_RANGE);
157}
158
159TEST(CallbackDecoder, Decode) {
160 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800161 TestDecodeHandler handler;
162
163 // clang-format off
164 uint8_t encoded_proto[] = {
165 // type=int32, k=1, v=42
166 0x08, 0x2a,
167 // type=sint32, k=2, v=-13
168 0x10, 0x19,
169 // type=bool, k=3, v=false
170 0x18, 0x00,
171 // type=double, k=4, v=3.14159
172 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
173 // type=fixed32, k=5, v=0xdeadbeef
174 0x2d, 0xef, 0xbe, 0xad, 0xde,
Alexei Frolov6d9b9b42020-01-14 12:57:33 -0800175 // type=string, k=6, v="Hello world"
176 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
Alexei Frolovdea46f72020-01-07 13:28:24 -0800177 };
178 // clang-format on
179
180 decoder.set_handler(&handler);
181 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
182 EXPECT_TRUE(handler.called);
183 EXPECT_EQ(handler.test_int32, 42);
184 EXPECT_EQ(handler.test_sint32, -13);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -0800185 EXPECT_FALSE(handler.test_bool);
186 EXPECT_EQ(handler.test_double, 3.14159);
187 EXPECT_EQ(handler.test_fixed32, 0xdeadbeef);
188 EXPECT_STREQ(handler.test_string, "Hello world");
Alexei Frolovdea46f72020-01-07 13:28:24 -0800189}
190
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700191TEST(CallbackDecoder, Decode_OverridesDuplicateFields) {
192 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800193 TestDecodeHandler handler;
194
195 // clang-format off
196 uint8_t encoded_proto[] = {
197 // type=int32, k=1, v=42
198 0x08, 0x2a,
199 // type=int32, k=1, v=43
200 0x08, 0x2b,
201 // type=int32, k=1, v=44
202 0x08, 0x2c,
203 };
204 // clang-format on
205
206 decoder.set_handler(&handler);
207 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
208 EXPECT_TRUE(handler.called);
209 EXPECT_EQ(handler.test_int32, 44);
210}
211
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700212TEST(CallbackDecoder, Decode_Empty) {
213 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800214 TestDecodeHandler handler;
215
216 decoder.set_handler(&handler);
217 EXPECT_EQ(decoder.Decode(span<std::byte>()), Status::OK);
218 EXPECT_FALSE(handler.called);
219 EXPECT_EQ(handler.test_int32, 0);
220 EXPECT_EQ(handler.test_sint32, 0);
221}
222
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700223TEST(CallbackDecoder, Decode_BadData) {
224 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800225 TestDecodeHandler handler;
226
227 // Field key without a value.
228 uint8_t encoded_proto[] = {0x08};
229
230 decoder.set_handler(&handler);
231 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::DATA_LOSS);
232}
233
234// Only processes fields numbered 1 or 3.
235class OneThreeDecodeHandler : public DecodeHandler {
236 public:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700237 Status ProcessField(CallbackDecoder& decoder,
238 uint32_t field_number) override {
Alexei Frolovdea46f72020-01-07 13:28:24 -0800239 switch (field_number) {
240 case 1:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700241 EXPECT_EQ(decoder.ReadInt32(&field_one), Status::OK);
Alexei Frolovdea46f72020-01-07 13:28:24 -0800242 break;
243 case 3:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700244 EXPECT_EQ(decoder.ReadInt32(&field_three), Status::OK);
Alexei Frolovdea46f72020-01-07 13:28:24 -0800245 break;
246 default:
247 // Do nothing.
248 break;
249 }
250
251 called = true;
252 return Status::OK;
253 }
254
255 bool called = false;
256 int32_t field_one = 0;
257 int32_t field_three = 0;
258};
259
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700260TEST(CallbackDecoder, Decode_SkipsUnprocessedFields) {
261 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800262 OneThreeDecodeHandler handler;
263
264 // clang-format off
265 uint8_t encoded_proto[] = {
266 // type=int32, k=1, v=42
267 // Should be read.
268 0x08, 0x2a,
269 // type=sint32, k=2, v=-13
270 // Should be ignored.
271 0x10, 0x19,
272 // type=int32, k=2, v=3
273 // Should be ignored.
274 0x10, 0x03,
275 // type=int32, k=3, v=99
276 // Should be read.
277 0x18, 0x63,
278 // type=int32, k=4, v=16
279 // Should be ignored.
280 0x20, 0x10,
281 };
282 // clang-format on
283
284 decoder.set_handler(&handler);
285 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
286 EXPECT_TRUE(handler.called);
287 EXPECT_EQ(handler.field_one, 42);
288 EXPECT_EQ(handler.field_three, 99);
289}
290
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700291// Only processes fields numbered 1 or 3, and stops the decode after hitting 1.
Alexei Frolovdea46f72020-01-07 13:28:24 -0800292class ExitOnOneDecoder : public DecodeHandler {
293 public:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700294 Status ProcessField(CallbackDecoder& decoder,
295 uint32_t field_number) override {
Alexei Frolovdea46f72020-01-07 13:28:24 -0800296 switch (field_number) {
297 case 1:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700298 EXPECT_EQ(decoder.ReadInt32(&field_one), Status::OK);
Alexei Frolovdea46f72020-01-07 13:28:24 -0800299 return Status::CANCELLED;
300 case 3:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700301 EXPECT_EQ(decoder.ReadInt32(&field_three), Status::OK);
Alexei Frolovdea46f72020-01-07 13:28:24 -0800302 break;
303 default:
304 // Do nothing.
305 break;
306 }
307
308 return Status::OK;
309 }
310
311 int32_t field_one = 0;
312 int32_t field_three = 1111;
313};
314
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700315TEST(CallbackDecoder, Decode_StopsOnNonOkStatus) {
316 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800317 ExitOnOneDecoder handler;
318
319 // clang-format off
320 uint8_t encoded_proto[] = {
321 // type=int32, k=1, v=42
322 // Should be read.
323 0x08, 0x2a,
324 // type=int32, k=3, v=99
325 // Should be skipped.
326 0x18, 0x63,
327 // type=int32, k=2, v=16
328 // Should be skipped.
329 0x08, 0x10,
330 };
331 // clang-format on
332
333 decoder.set_handler(&handler);
334 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::CANCELLED);
335 EXPECT_EQ(handler.field_one, 42);
336 EXPECT_EQ(handler.field_three, 1111);
337}
338
339} // namespace
340} // namespace pw::protobuf