1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 #include "pw_protobuf/decoder.h"
17 #include "gtest/gtest.h"
18 #include "pw_preprocessor/util.h"
20 namespace pw::protobuf {
23 class TestDecodeHandler : public DecodeHandler {
25 Status ProcessField(CallbackDecoder& decoder,
26 uint32_t field_number) override {
29 switch (field_number) {
31 decoder.ReadInt32(&test_int32);
34 decoder.ReadSint32(&test_sint32);
37 decoder.ReadBool(&test_bool);
40 decoder.ReadDouble(&test_double);
43 decoder.ReadFixed32(&test_fixed32);
46 decoder.ReadString(&str);
47 std::memcpy(test_string, str.data(), str.size());
48 test_string[str.size()] = '\0';
57 int32_t test_int32 = 0;
58 int32_t test_sint32 = 0;
59 bool test_bool = true;
60 double test_double = 0;
61 uint32_t test_fixed32 = 0;
65 TEST(Decoder, Decode) {
67 uint8_t encoded_proto[] = {
68 // type=int32, k=1, v=42
70 // type=sint32, k=2, v=-13
72 // type=bool, k=3, v=false
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',
83 Decoder decoder(std::as_bytes(std::span(encoded_proto)));
86 EXPECT_EQ(decoder.Next(), OkStatus());
87 ASSERT_EQ(decoder.FieldNumber(), 1u);
88 EXPECT_EQ(decoder.ReadInt32(&v1), OkStatus());
92 EXPECT_EQ(decoder.Next(), OkStatus());
93 ASSERT_EQ(decoder.FieldNumber(), 2u);
94 EXPECT_EQ(decoder.ReadSint32(&v2), OkStatus());
98 EXPECT_EQ(decoder.Next(), OkStatus());
99 ASSERT_EQ(decoder.FieldNumber(), 3u);
100 EXPECT_EQ(decoder.ReadBool(&v3), OkStatus());
104 EXPECT_EQ(decoder.Next(), OkStatus());
105 ASSERT_EQ(decoder.FieldNumber(), 4u);
106 EXPECT_EQ(decoder.ReadDouble(&v4), OkStatus());
107 EXPECT_EQ(v4, 3.14159);
110 EXPECT_EQ(decoder.Next(), OkStatus());
111 ASSERT_EQ(decoder.FieldNumber(), 5u);
112 EXPECT_EQ(decoder.ReadFixed32(&v5), OkStatus());
113 EXPECT_EQ(v5, 0xdeadbeef);
117 EXPECT_EQ(decoder.Next(), OkStatus());
118 ASSERT_EQ(decoder.FieldNumber(), 6u);
119 EXPECT_EQ(decoder.ReadString(&v6), OkStatus());
120 std::memcpy(buffer, v6.data(), v6.size());
121 buffer[v6.size()] = '\0';
122 EXPECT_STREQ(buffer, "Hello world");
124 EXPECT_EQ(decoder.Next(), Status::OutOfRange());
127 TEST(Decoder, Decode_SkipsUnusedFields) {
129 uint8_t encoded_proto[] = {
130 // type=int32, k=1, v=42
132 // type=sint32, k=2, v=-13
134 // type=bool, k=3, v=false
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',
145 Decoder decoder(std::as_bytes(std::span(encoded_proto)));
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(), OkStatus());
150 EXPECT_EQ(decoder.Next(), OkStatus());
151 EXPECT_EQ(decoder.Next(), OkStatus());
152 EXPECT_EQ(decoder.Next(), OkStatus());
153 ASSERT_EQ(decoder.FieldNumber(), 4u);
154 EXPECT_EQ(decoder.Next(), OkStatus());
155 EXPECT_EQ(decoder.Next(), OkStatus());
156 EXPECT_EQ(decoder.Next(), Status::OutOfRange());
159 TEST(CallbackDecoder, Decode) {
160 CallbackDecoder decoder;
161 TestDecodeHandler handler;
164 uint8_t encoded_proto[] = {
165 // type=int32, k=1, v=42
167 // type=sint32, k=2, v=-13
169 // type=bool, k=3, v=false
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,
175 // type=string, k=6, v="Hello world"
176 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
180 decoder.set_handler(&handler);
181 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
183 EXPECT_TRUE(handler.called);
184 EXPECT_EQ(handler.test_int32, 42);
185 EXPECT_EQ(handler.test_sint32, -13);
186 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");
192 TEST(CallbackDecoder, Decode_OverridesDuplicateFields) {
193 CallbackDecoder decoder;
194 TestDecodeHandler handler;
197 uint8_t encoded_proto[] = {
198 // type=int32, k=1, v=42
200 // type=int32, k=1, v=43
202 // type=int32, k=1, v=44
207 decoder.set_handler(&handler);
208 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
210 EXPECT_TRUE(handler.called);
211 EXPECT_EQ(handler.test_int32, 44);
214 TEST(CallbackDecoder, Decode_Empty) {
215 CallbackDecoder decoder;
216 TestDecodeHandler handler;
218 decoder.set_handler(&handler);
219 EXPECT_EQ(decoder.Decode(std::span<std::byte>()), OkStatus());
220 EXPECT_FALSE(handler.called);
221 EXPECT_EQ(handler.test_int32, 0);
222 EXPECT_EQ(handler.test_sint32, 0);
225 TEST(CallbackDecoder, Decode_BadData) {
226 CallbackDecoder decoder;
227 TestDecodeHandler handler;
229 // Field key without a value.
230 uint8_t encoded_proto[] = {0x08};
232 decoder.set_handler(&handler);
233 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
237 // Only processes fields numbered 1 or 3.
238 class OneThreeDecodeHandler : public DecodeHandler {
240 Status ProcessField(CallbackDecoder& decoder,
241 uint32_t field_number) override {
242 switch (field_number) {
244 EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
247 EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
259 int32_t field_one = 0;
260 int32_t field_three = 0;
263 TEST(CallbackDecoder, Decode_SkipsUnprocessedFields) {
264 CallbackDecoder decoder;
265 OneThreeDecodeHandler handler;
268 uint8_t encoded_proto[] = {
269 // type=int32, k=1, v=42
272 // type=sint32, k=2, v=-13
273 // Should be ignored.
275 // type=int32, k=2, v=3
276 // Should be ignored.
278 // type=int32, k=3, v=99
281 // type=int32, k=4, v=16
282 // Should be ignored.
287 decoder.set_handler(&handler);
288 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
290 EXPECT_TRUE(handler.called);
291 EXPECT_EQ(handler.field_one, 42);
292 EXPECT_EQ(handler.field_three, 99);
295 // Only processes fields numbered 1 or 3, and stops the decode after hitting 1.
296 class ExitOnOneDecoder : public DecodeHandler {
298 Status ProcessField(CallbackDecoder& decoder,
299 uint32_t field_number) override {
300 switch (field_number) {
302 EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
303 return Status::Cancelled();
305 EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
315 int32_t field_one = 0;
316 int32_t field_three = 1111;
319 TEST(CallbackDecoder, Decode_StopsOnNonOkStatus) {
320 CallbackDecoder decoder;
321 ExitOnOneDecoder handler;
324 uint8_t encoded_proto[] = {
325 // type=int32, k=1, v=42
328 // type=int32, k=3, v=99
329 // Should be skipped.
331 // type=int32, k=2, v=16
332 // Should be skipped.
337 decoder.set_handler(&handler);
338 EXPECT_EQ(decoder.Decode(std::as_bytes(std::span(encoded_proto))),
339 Status::Cancelled());
340 EXPECT_EQ(handler.field_one, 42);
341 EXPECT_EQ(handler.field_three, 1111);
345 } // namespace pw::protobuf