blob: c77e990459517824cad8e7fe459caeadda84749c [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;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080053 return OkStatus();
Alexei Frolovdea46f72020-01-07 13:28:24 -080054 }
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
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070083 Decoder decoder(std::as_bytes(std::span(encoded_proto)));
Alexei Frolovfe9723c2020-05-11 13:20:47 -070084
85 int32_t v1 = 0;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080086 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -070087 ASSERT_EQ(decoder.FieldNumber(), 1u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080088 EXPECT_EQ(decoder.ReadInt32(&v1), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -070089 EXPECT_EQ(v1, 42);
90
91 int32_t v2 = 0;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080092 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -070093 ASSERT_EQ(decoder.FieldNumber(), 2u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080094 EXPECT_EQ(decoder.ReadSint32(&v2), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -070095 EXPECT_EQ(v2, -13);
96
97 bool v3 = true;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080098 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -070099 ASSERT_EQ(decoder.FieldNumber(), 3u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800100 EXPECT_EQ(decoder.ReadBool(&v3), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700101 EXPECT_FALSE(v3);
102
103 double v4 = 0;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800104 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700105 ASSERT_EQ(decoder.FieldNumber(), 4u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800106 EXPECT_EQ(decoder.ReadDouble(&v4), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700107 EXPECT_EQ(v4, 3.14159);
108
109 uint32_t v5 = 0;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800110 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700111 ASSERT_EQ(decoder.FieldNumber(), 5u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800112 EXPECT_EQ(decoder.ReadFixed32(&v5), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700113 EXPECT_EQ(v5, 0xdeadbeef);
114
115 std::string_view v6;
116 char buffer[16];
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800117 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700118 ASSERT_EQ(decoder.FieldNumber(), 6u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800119 EXPECT_EQ(decoder.ReadString(&v6), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700120 std::memcpy(buffer, v6.data(), v6.size());
121 buffer[v6.size()] = '\0';
122 EXPECT_STREQ(buffer, "Hello world");
123
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700124 EXPECT_EQ(decoder.Next(), Status::OutOfRange());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700125}
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
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700145 Decoder decoder(std::as_bytes(std::span(encoded_proto)));
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700146
147 // Don't process any fields except for the fourth. Next should still iterate
148 // correctly despite field values not being consumed.
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800149 EXPECT_EQ(decoder.Next(), OkStatus());
150 EXPECT_EQ(decoder.Next(), OkStatus());
151 EXPECT_EQ(decoder.Next(), OkStatus());
152 EXPECT_EQ(decoder.Next(), OkStatus());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700153 ASSERT_EQ(decoder.FieldNumber(), 4u);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800154 EXPECT_EQ(decoder.Next(), OkStatus());
155 EXPECT_EQ(decoder.Next(), OkStatus());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700156 EXPECT_EQ(decoder.Next(), Status::OutOfRange());
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700157}
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);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700181 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800182 OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800183 EXPECT_TRUE(handler.called);
184 EXPECT_EQ(handler.test_int32, 42);
185 EXPECT_EQ(handler.test_sint32, -13);
Alexei Frolov6d9b9b42020-01-14 12:57:33 -0800186 EXPECT_FALSE(handler.test_bool);
187 EXPECT_EQ(handler.test_double, 3.14159);
188 EXPECT_EQ(handler.test_fixed32, 0xdeadbeef);
189 EXPECT_STREQ(handler.test_string, "Hello world");
Alexei Frolovdea46f72020-01-07 13:28:24 -0800190}
191
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700192TEST(CallbackDecoder, Decode_OverridesDuplicateFields) {
193 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800194 TestDecodeHandler handler;
195
196 // clang-format off
197 uint8_t encoded_proto[] = {
198 // type=int32, k=1, v=42
199 0x08, 0x2a,
200 // type=int32, k=1, v=43
201 0x08, 0x2b,
202 // type=int32, k=1, v=44
203 0x08, 0x2c,
204 };
205 // clang-format on
206
207 decoder.set_handler(&handler);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700208 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800209 OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800210 EXPECT_TRUE(handler.called);
211 EXPECT_EQ(handler.test_int32, 44);
212}
213
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700214TEST(CallbackDecoder, Decode_Empty) {
215 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800216 TestDecodeHandler handler;
217
218 decoder.set_handler(&handler);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800219 EXPECT_EQ(decoder.Decode(std::span<std::byte>()), OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800220 EXPECT_FALSE(handler.called);
221 EXPECT_EQ(handler.test_int32, 0);
222 EXPECT_EQ(handler.test_sint32, 0);
223}
224
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700225TEST(CallbackDecoder, Decode_BadData) {
226 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800227 TestDecodeHandler handler;
228
229 // Field key without a value.
230 uint8_t encoded_proto[] = {0x08};
231
232 decoder.set_handler(&handler);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700233 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700234 Status::DataLoss());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800235}
236
237// Only processes fields numbered 1 or 3.
238class OneThreeDecodeHandler : public DecodeHandler {
239 public:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700240 Status ProcessField(CallbackDecoder& decoder,
241 uint32_t field_number) override {
Alexei Frolovdea46f72020-01-07 13:28:24 -0800242 switch (field_number) {
243 case 1:
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800244 EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800245 break;
246 case 3:
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800247 EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800248 break;
249 default:
250 // Do nothing.
251 break;
252 }
253
254 called = true;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800255 return OkStatus();
Alexei Frolovdea46f72020-01-07 13:28:24 -0800256 }
257
258 bool called = false;
259 int32_t field_one = 0;
260 int32_t field_three = 0;
261};
262
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700263TEST(CallbackDecoder, Decode_SkipsUnprocessedFields) {
264 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800265 OneThreeDecodeHandler handler;
266
267 // clang-format off
268 uint8_t encoded_proto[] = {
269 // type=int32, k=1, v=42
270 // Should be read.
271 0x08, 0x2a,
272 // type=sint32, k=2, v=-13
273 // Should be ignored.
274 0x10, 0x19,
275 // type=int32, k=2, v=3
276 // Should be ignored.
277 0x10, 0x03,
278 // type=int32, k=3, v=99
279 // Should be read.
280 0x18, 0x63,
281 // type=int32, k=4, v=16
282 // Should be ignored.
283 0x20, 0x10,
284 };
285 // clang-format on
286
287 decoder.set_handler(&handler);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700288 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800289 OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800290 EXPECT_TRUE(handler.called);
291 EXPECT_EQ(handler.field_one, 42);
292 EXPECT_EQ(handler.field_three, 99);
293}
294
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700295// Only processes fields numbered 1 or 3, and stops the decode after hitting 1.
Alexei Frolovdea46f72020-01-07 13:28:24 -0800296class ExitOnOneDecoder : public DecodeHandler {
297 public:
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700298 Status ProcessField(CallbackDecoder& decoder,
299 uint32_t field_number) override {
Alexei Frolovdea46f72020-01-07 13:28:24 -0800300 switch (field_number) {
301 case 1:
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800302 EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700303 return Status::Cancelled();
Alexei Frolovdea46f72020-01-07 13:28:24 -0800304 case 3:
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800305 EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800306 break;
307 default:
308 // Do nothing.
309 break;
310 }
311
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800312 return OkStatus();
Alexei Frolovdea46f72020-01-07 13:28:24 -0800313 }
314
315 int32_t field_one = 0;
316 int32_t field_three = 1111;
317};
318
Alexei Frolovfe9723c2020-05-11 13:20:47 -0700319TEST(CallbackDecoder, Decode_StopsOnNonOkStatus) {
320 CallbackDecoder decoder;
Alexei Frolovdea46f72020-01-07 13:28:24 -0800321 ExitOnOneDecoder handler;
322
323 // clang-format off
324 uint8_t encoded_proto[] = {
325 // type=int32, k=1, v=42
326 // Should be read.
327 0x08, 0x2a,
328 // type=int32, k=3, v=99
329 // Should be skipped.
330 0x18, 0x63,
331 // type=int32, k=2, v=16
332 // Should be skipped.
333 0x08, 0x10,
334 };
335 // clang-format on
336
337 decoder.set_handler(&handler);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700338 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700339 Status::Cancelled());
Alexei Frolovdea46f72020-01-07 13:28:24 -0800340 EXPECT_EQ(handler.field_one, 42);
341 EXPECT_EQ(handler.field_three, 1111);
342}
343
344} // namespace
345} // namespace pw::protobuf