blob: 45fe93dd741f335463a56dfcbd28667d3abcce06 [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:
25 Status ProcessField(Decoder* decoder, uint32_t field_number) override {
26 switch (field_number) {
27 case 1:
28 decoder->ReadInt32(field_number, &test_int32);
29 break;
30 case 2:
31 decoder->ReadSint32(field_number, &test_sint32);
32 break;
33 }
34
35 called = true;
36 return Status::OK;
37 }
38
39 bool called = false;
40 int32_t test_int32 = 0;
41 int32_t test_sint32 = 0;
42};
43
44TEST(Decoder, Decode) {
45 Decoder decoder;
46 TestDecodeHandler handler;
47
48 // clang-format off
49 uint8_t encoded_proto[] = {
50 // type=int32, k=1, v=42
51 0x08, 0x2a,
52 // type=sint32, k=2, v=-13
53 0x10, 0x19,
54 // type=bool, k=3, v=false
55 0x18, 0x00,
56 // type=double, k=4, v=3.14159
57 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
58 // type=fixed32, k=5, v=0xdeadbeef
59 0x2d, 0xef, 0xbe, 0xad, 0xde,
60 };
61 // clang-format on
62
63 decoder.set_handler(&handler);
64 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
65 EXPECT_TRUE(handler.called);
66 EXPECT_EQ(handler.test_int32, 42);
67 EXPECT_EQ(handler.test_sint32, -13);
68}
69
70TEST(Decoder, Decode_OverridesDuplicateFields) {
71 Decoder decoder;
72 TestDecodeHandler handler;
73
74 // clang-format off
75 uint8_t encoded_proto[] = {
76 // type=int32, k=1, v=42
77 0x08, 0x2a,
78 // type=int32, k=1, v=43
79 0x08, 0x2b,
80 // type=int32, k=1, v=44
81 0x08, 0x2c,
82 };
83 // clang-format on
84
85 decoder.set_handler(&handler);
86 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
87 EXPECT_TRUE(handler.called);
88 EXPECT_EQ(handler.test_int32, 44);
89}
90
91TEST(Decoder, Decode_Empty) {
92 Decoder decoder;
93 TestDecodeHandler handler;
94
95 decoder.set_handler(&handler);
96 EXPECT_EQ(decoder.Decode(span<std::byte>()), Status::OK);
97 EXPECT_FALSE(handler.called);
98 EXPECT_EQ(handler.test_int32, 0);
99 EXPECT_EQ(handler.test_sint32, 0);
100}
101
102TEST(Decoder, Decode_BadData) {
103 Decoder decoder;
104 TestDecodeHandler handler;
105
106 // Field key without a value.
107 uint8_t encoded_proto[] = {0x08};
108
109 decoder.set_handler(&handler);
110 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::DATA_LOSS);
111}
112
113// Only processes fields numbered 1 or 3.
114class OneThreeDecodeHandler : public DecodeHandler {
115 public:
116 Status ProcessField(Decoder* decoder, uint32_t field_number) override {
117 switch (field_number) {
118 case 1:
119 EXPECT_EQ(decoder->ReadInt32(field_number, &field_one), Status::OK);
120 break;
121 case 3:
122 EXPECT_EQ(decoder->ReadInt32(field_number, &field_three), Status::OK);
123 break;
124 default:
125 // Do nothing.
126 break;
127 }
128
129 called = true;
130 return Status::OK;
131 }
132
133 bool called = false;
134 int32_t field_one = 0;
135 int32_t field_three = 0;
136};
137
138TEST(Decoder, Decode_SkipsUnprocessedFields) {
139 Decoder decoder;
140 OneThreeDecodeHandler handler;
141
142 // clang-format off
143 uint8_t encoded_proto[] = {
144 // type=int32, k=1, v=42
145 // Should be read.
146 0x08, 0x2a,
147 // type=sint32, k=2, v=-13
148 // Should be ignored.
149 0x10, 0x19,
150 // type=int32, k=2, v=3
151 // Should be ignored.
152 0x10, 0x03,
153 // type=int32, k=3, v=99
154 // Should be read.
155 0x18, 0x63,
156 // type=int32, k=4, v=16
157 // Should be ignored.
158 0x20, 0x10,
159 };
160 // clang-format on
161
162 decoder.set_handler(&handler);
163 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::OK);
164 EXPECT_TRUE(handler.called);
165 EXPECT_EQ(handler.field_one, 42);
166 EXPECT_EQ(handler.field_three, 99);
167}
168
169// Only processes fields numbered 1 or 3.
170class ExitOnOneDecoder : public DecodeHandler {
171 public:
172 Status ProcessField(Decoder* decoder, uint32_t field_number) override {
173 switch (field_number) {
174 case 1:
175 EXPECT_EQ(decoder->ReadInt32(field_number, &field_one), Status::OK);
176 return Status::CANCELLED;
177 case 3:
178 EXPECT_EQ(decoder->ReadInt32(field_number, &field_three), Status::OK);
179 break;
180 default:
181 // Do nothing.
182 break;
183 }
184
185 return Status::OK;
186 }
187
188 int32_t field_one = 0;
189 int32_t field_three = 1111;
190};
191
192TEST(Decoder, Decode_StopsOnNonOkStatus) {
193 Decoder decoder;
194 ExitOnOneDecoder handler;
195
196 // clang-format off
197 uint8_t encoded_proto[] = {
198 // type=int32, k=1, v=42
199 // Should be read.
200 0x08, 0x2a,
201 // type=int32, k=3, v=99
202 // Should be skipped.
203 0x18, 0x63,
204 // type=int32, k=2, v=16
205 // Should be skipped.
206 0x08, 0x10,
207 };
208 // clang-format on
209
210 decoder.set_handler(&handler);
211 EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::CANCELLED);
212 EXPECT_EQ(handler.field_one, 42);
213 EXPECT_EQ(handler.field_three, 1111);
214}
215
216} // namespace
217} // namespace pw::protobuf