1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/stream_decoder.h"
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker #include <array>
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status_with_size.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/memory_stream.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/stream.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
24*61c4878aSAndroid Build Coastguard Worker
25*61c4878aSAndroid Build Coastguard Worker namespace pw::protobuf {
26*61c4878aSAndroid Build Coastguard Worker namespace {
27*61c4878aSAndroid Build Coastguard Worker // Non-seekable wrapper for MemoryReader for testing behavior when seeking is
28*61c4878aSAndroid Build Coastguard Worker // not available.
29*61c4878aSAndroid Build Coastguard Worker class NonSeekableMemoryReader : public stream::NonSeekableReader {
30*61c4878aSAndroid Build Coastguard Worker public:
NonSeekableMemoryReader(stream::MemoryReader & reader)31*61c4878aSAndroid Build Coastguard Worker explicit NonSeekableMemoryReader(stream::MemoryReader& reader)
32*61c4878aSAndroid Build Coastguard Worker : reader_(reader) {}
33*61c4878aSAndroid Build Coastguard Worker
bytes_read() const34*61c4878aSAndroid Build Coastguard Worker size_t bytes_read() const { return reader_.bytes_read(); }
data() const35*61c4878aSAndroid Build Coastguard Worker const std::byte* data() const { return reader_.data(); }
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker private:
DoRead(ByteSpan destination)38*61c4878aSAndroid Build Coastguard Worker StatusWithSize DoRead(ByteSpan destination) override {
39*61c4878aSAndroid Build Coastguard Worker const pw::Result<pw::ByteSpan> result = reader_.Read(destination);
40*61c4878aSAndroid Build Coastguard Worker if (!result.ok()) {
41*61c4878aSAndroid Build Coastguard Worker return StatusWithSize(result.status(), 0);
42*61c4878aSAndroid Build Coastguard Worker }
43*61c4878aSAndroid Build Coastguard Worker return StatusWithSize(result.value().size_bytes());
44*61c4878aSAndroid Build Coastguard Worker }
45*61c4878aSAndroid Build Coastguard Worker
46*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader& reader_;
47*61c4878aSAndroid Build Coastguard Worker };
48*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode)49*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode) {
50*61c4878aSAndroid Build Coastguard Worker // clang-format off
51*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
52*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
53*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
54*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
55*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
56*61c4878aSAndroid Build Coastguard Worker // type=bool, k=3, v=false
57*61c4878aSAndroid Build Coastguard Worker 0x18, 0x00,
58*61c4878aSAndroid Build Coastguard Worker // type=double, k=4, v=3.14159
59*61c4878aSAndroid Build Coastguard Worker 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
60*61c4878aSAndroid Build Coastguard Worker // type=fixed32, k=5, v=0xdeadbeef
61*61c4878aSAndroid Build Coastguard Worker 0x2d, 0xef, 0xbe, 0xad, 0xde,
62*61c4878aSAndroid Build Coastguard Worker // type=string, k=6, v="Hello world"
63*61c4878aSAndroid Build Coastguard Worker 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
64*61c4878aSAndroid Build Coastguard Worker // type=sfixed32, k=7, v=-50
65*61c4878aSAndroid Build Coastguard Worker 0x3d, 0xce, 0xff, 0xff, 0xff,
66*61c4878aSAndroid Build Coastguard Worker // type=sfixed64, k=8, v=-1647993274
67*61c4878aSAndroid Build Coastguard Worker 0x41, 0x46, 0x9e, 0xc5, 0x9d, 0xff, 0xff, 0xff, 0xff,
68*61c4878aSAndroid Build Coastguard Worker // type=float, k=9, v=2.718
69*61c4878aSAndroid Build Coastguard Worker 0x4d, 0xb6, 0xf3, 0x2d, 0x40,
70*61c4878aSAndroid Build Coastguard Worker };
71*61c4878aSAndroid Build Coastguard Worker // clang-format on
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
74*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
75*61c4878aSAndroid Build Coastguard Worker
76*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
77*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
78*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
79*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
80*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
83*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 2u);
84*61c4878aSAndroid Build Coastguard Worker Result<int32_t> sint32 = decoder.ReadSint32();
85*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sint32.status(), OkStatus());
86*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32.value(), -13);
87*61c4878aSAndroid Build Coastguard Worker
88*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
89*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 3u);
90*61c4878aSAndroid Build Coastguard Worker Result<bool> boolean = decoder.ReadBool();
91*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(boolean.status(), OkStatus());
92*61c4878aSAndroid Build Coastguard Worker EXPECT_FALSE(boolean.value());
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
95*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 4u);
96*61c4878aSAndroid Build Coastguard Worker Result<double> dbl = decoder.ReadDouble();
97*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(dbl.status(), OkStatus());
98*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(dbl.value(), 3.14159);
99*61c4878aSAndroid Build Coastguard Worker
100*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
101*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 5u);
102*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> fixed32 = decoder.ReadFixed32();
103*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(fixed32.status(), OkStatus());
104*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32.value(), 0xdeadbeef);
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker char buffer[16];
107*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
108*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 6u);
109*61c4878aSAndroid Build Coastguard Worker StatusWithSize sws = decoder.ReadString(buffer);
110*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sws.status(), OkStatus());
111*61c4878aSAndroid Build Coastguard Worker buffer[sws.size()] = '\0';
112*61c4878aSAndroid Build Coastguard Worker EXPECT_STREQ(buffer, "Hello world");
113*61c4878aSAndroid Build Coastguard Worker
114*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
115*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 7u);
116*61c4878aSAndroid Build Coastguard Worker Result<int32_t> sfixed32 = decoder.ReadSfixed32();
117*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sfixed32.status(), OkStatus());
118*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32.value(), -50);
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
121*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 8u);
122*61c4878aSAndroid Build Coastguard Worker Result<int64_t> sfixed64 = decoder.ReadSfixed64();
123*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sfixed64.status(), OkStatus());
124*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed64.value(), -1647993274);
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
127*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 9u);
128*61c4878aSAndroid Build Coastguard Worker Result<float> flt = decoder.ReadFloat();
129*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(flt.status(), OkStatus());
130*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(flt.value(), 2.718f);
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
133*61c4878aSAndroid Build Coastguard Worker }
134*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_SkipsUnusedFields)135*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_SkipsUnusedFields) {
136*61c4878aSAndroid Build Coastguard Worker // clang-format off
137*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
138*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
139*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
140*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
141*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
142*61c4878aSAndroid Build Coastguard Worker // type=bool, k=3, v=false
143*61c4878aSAndroid Build Coastguard Worker 0x18, 0x00,
144*61c4878aSAndroid Build Coastguard Worker // type=double, k=4, v=3.14159
145*61c4878aSAndroid Build Coastguard Worker 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
146*61c4878aSAndroid Build Coastguard Worker // type=fixed32, k=5, v=0xdeadbeef
147*61c4878aSAndroid Build Coastguard Worker 0x2d, 0xef, 0xbe, 0xad, 0xde,
148*61c4878aSAndroid Build Coastguard Worker // type=string, k=6, v="Hello world"
149*61c4878aSAndroid Build Coastguard Worker 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
150*61c4878aSAndroid Build Coastguard Worker };
151*61c4878aSAndroid Build Coastguard Worker // clang-format on
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
154*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard Worker // Don't process any fields except for the fourth. Next should still iterate
157*61c4878aSAndroid Build Coastguard Worker // correctly despite field values not being consumed.
158*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
159*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
160*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
161*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
162*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 4u);
163*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
164*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
165*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
166*61c4878aSAndroid Build Coastguard Worker }
167*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_NonSeekable_SkipsUnusedFields)168*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_NonSeekable_SkipsUnusedFields) {
169*61c4878aSAndroid Build Coastguard Worker // clang-format off
170*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
171*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
172*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
173*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
174*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
175*61c4878aSAndroid Build Coastguard Worker // type=bool, k=3, v=false
176*61c4878aSAndroid Build Coastguard Worker 0x18, 0x00,
177*61c4878aSAndroid Build Coastguard Worker // type=double, k=4, v=3.14159
178*61c4878aSAndroid Build Coastguard Worker 0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
179*61c4878aSAndroid Build Coastguard Worker // type=fixed32, k=5, v=0xdeadbeef
180*61c4878aSAndroid Build Coastguard Worker 0x2d, 0xef, 0xbe, 0xad, 0xde,
181*61c4878aSAndroid Build Coastguard Worker // type=string, k=6, v="Hello world"
182*61c4878aSAndroid Build Coastguard Worker 0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
183*61c4878aSAndroid Build Coastguard Worker };
184*61c4878aSAndroid Build Coastguard Worker // clang-format on
185*61c4878aSAndroid Build Coastguard Worker
186*61c4878aSAndroid Build Coastguard Worker // Test with a non-seekable memory reader
187*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader wrapped_reader(as_bytes(span(encoded_proto)));
188*61c4878aSAndroid Build Coastguard Worker NonSeekableMemoryReader reader(wrapped_reader);
189*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
190*61c4878aSAndroid Build Coastguard Worker
191*61c4878aSAndroid Build Coastguard Worker // Don't process any fields except for the fourth. Next should still iterate
192*61c4878aSAndroid Build Coastguard Worker // correctly despite field values not being consumed.
193*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
194*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
195*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
196*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
197*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 4u);
198*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
199*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
200*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
201*61c4878aSAndroid Build Coastguard Worker }
202*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BadData)203*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BadData) {
204*61c4878aSAndroid Build Coastguard Worker // clang-format off
205*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
206*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
207*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
208*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, value... missing
209*61c4878aSAndroid Build Coastguard Worker 0x10,
210*61c4878aSAndroid Build Coastguard Worker };
211*61c4878aSAndroid Build Coastguard Worker // clang-format on
212*61c4878aSAndroid Build Coastguard Worker
213*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
214*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
215*61c4878aSAndroid Build Coastguard Worker
216*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
217*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
218*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
219*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
220*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
221*61c4878aSAndroid Build Coastguard Worker
222*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
223*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 2u);
224*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.ReadSint32().status(), Status::DataLoss());
225*61c4878aSAndroid Build Coastguard Worker
226*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
227*61c4878aSAndroid Build Coastguard Worker }
228*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_MissingDelimitedLength)229*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_MissingDelimitedLength) {
230*61c4878aSAndroid Build Coastguard Worker // clang-format off
231*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
232*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
233*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
234*61c4878aSAndroid Build Coastguard Worker // Submessage (bytes) key=8, length=... missing
235*61c4878aSAndroid Build Coastguard Worker 0x32,
236*61c4878aSAndroid Build Coastguard Worker };
237*61c4878aSAndroid Build Coastguard Worker // clang-format on
238*61c4878aSAndroid Build Coastguard Worker
239*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
240*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
243*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
244*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
245*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
246*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
247*61c4878aSAndroid Build Coastguard Worker
248*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
249*61c4878aSAndroid Build Coastguard Worker }
250*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_VarintTooBig)251*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_VarintTooBig) {
252*61c4878aSAndroid Build Coastguard Worker // clang-format off
253*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
254*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=>uint32_t::max
255*61c4878aSAndroid Build Coastguard Worker 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
256*61c4878aSAndroid Build Coastguard Worker // type=int32, k=2, v=>int32_t::max
257*61c4878aSAndroid Build Coastguard Worker 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
258*61c4878aSAndroid Build Coastguard Worker // type=int32, k=3, v<=int32_t::min
259*61c4878aSAndroid Build Coastguard Worker 0x18, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01,
260*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=4, v=>int32_t::max
261*61c4878aSAndroid Build Coastguard Worker 0x20, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f,
262*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=5, v<=int32_t::max
263*61c4878aSAndroid Build Coastguard Worker 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
264*61c4878aSAndroid Build Coastguard Worker };
265*61c4878aSAndroid Build Coastguard Worker // clang-format on
266*61c4878aSAndroid Build Coastguard Worker
267*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
268*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
269*61c4878aSAndroid Build Coastguard Worker
270*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
271*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
272*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> uint32 = decoder.ReadUint32();
273*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), Status::FailedPrecondition());
274*61c4878aSAndroid Build Coastguard Worker
275*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
276*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 2u);
277*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
278*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), Status::FailedPrecondition());
279*61c4878aSAndroid Build Coastguard Worker
280*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
281*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 3u);
282*61c4878aSAndroid Build Coastguard Worker int32 = decoder.ReadInt32();
283*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), Status::FailedPrecondition());
284*61c4878aSAndroid Build Coastguard Worker
285*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
286*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 4u);
287*61c4878aSAndroid Build Coastguard Worker Result<int32_t> sint32 = decoder.ReadSint32();
288*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sint32.status(), Status::FailedPrecondition());
289*61c4878aSAndroid Build Coastguard Worker
290*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
291*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 5u);
292*61c4878aSAndroid Build Coastguard Worker sint32 = decoder.ReadSint32();
293*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sint32.status(), Status::FailedPrecondition());
294*61c4878aSAndroid Build Coastguard Worker
295*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
296*61c4878aSAndroid Build Coastguard Worker }
297*61c4878aSAndroid Build Coastguard Worker
TEST(Decoder,Decode_SkipsBadFieldNumbers)298*61c4878aSAndroid Build Coastguard Worker TEST(Decoder, Decode_SkipsBadFieldNumbers) {
299*61c4878aSAndroid Build Coastguard Worker // clang-format off
300*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
301*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
302*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
303*61c4878aSAndroid Build Coastguard Worker // type=int32, k=19001, v=42 (invalid field number)
304*61c4878aSAndroid Build Coastguard Worker 0xc8, 0xa3, 0x09, 0x2a,
305*61c4878aSAndroid Build Coastguard Worker // type=bool, k=3, v=false
306*61c4878aSAndroid Build Coastguard Worker 0x18, 0x00,
307*61c4878aSAndroid Build Coastguard Worker };
308*61c4878aSAndroid Build Coastguard Worker // clang-format on
309*61c4878aSAndroid Build Coastguard Worker
310*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
311*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
312*61c4878aSAndroid Build Coastguard Worker
313*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
314*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 1u);
315*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
316*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
317*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
318*61c4878aSAndroid Build Coastguard Worker
319*61c4878aSAndroid Build Coastguard Worker // Bad field.
320*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
321*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.FieldNumber().status(), Status::FailedPrecondition());
322*61c4878aSAndroid Build Coastguard Worker
323*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
324*61c4878aSAndroid Build Coastguard Worker }
325*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested)326*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested) {
327*61c4878aSAndroid Build Coastguard Worker // clang-format off
328*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
329*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
330*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
331*61c4878aSAndroid Build Coastguard Worker
332*61c4878aSAndroid Build Coastguard Worker // Submessage (bytes) key=8, length=4
333*61c4878aSAndroid Build Coastguard Worker 0x32, 0x04,
334*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=2
335*61c4878aSAndroid Build Coastguard Worker 0x08, 0x02,
336*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=2, v=7
337*61c4878aSAndroid Build Coastguard Worker 0x10, 0x07,
338*61c4878aSAndroid Build Coastguard Worker // End submessage
339*61c4878aSAndroid Build Coastguard Worker
340*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
341*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
342*61c4878aSAndroid Build Coastguard Worker };
343*61c4878aSAndroid Build Coastguard Worker // clang-format on
344*61c4878aSAndroid Build Coastguard Worker
345*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
346*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
347*61c4878aSAndroid Build Coastguard Worker
348*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
349*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
350*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
351*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
352*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
353*61c4878aSAndroid Build Coastguard Worker
354*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
355*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 6u);
356*61c4878aSAndroid Build Coastguard Worker {
357*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
358*61c4878aSAndroid Build Coastguard Worker
359*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
360*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
361*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> uint32 = nested.ReadUint32();
362*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
363*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 2u);
364*61c4878aSAndroid Build Coastguard Worker
365*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
366*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 2u);
367*61c4878aSAndroid Build Coastguard Worker uint32 = nested.ReadUint32();
368*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
369*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 7u);
370*61c4878aSAndroid Build Coastguard Worker
371*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(nested.Next(), Status::OutOfRange());
372*61c4878aSAndroid Build Coastguard Worker }
373*61c4878aSAndroid Build Coastguard Worker
374*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
375*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 2u);
376*61c4878aSAndroid Build Coastguard Worker Result<int32_t> sint32 = decoder.ReadSint32();
377*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(sint32.status(), OkStatus());
378*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32.value(), -13);
379*61c4878aSAndroid Build Coastguard Worker
380*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
381*61c4878aSAndroid Build Coastguard Worker }
382*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_SeeksToNextFieldOnDestruction)383*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_SeeksToNextFieldOnDestruction) {
384*61c4878aSAndroid Build Coastguard Worker // clang-format off
385*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
386*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
387*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
388*61c4878aSAndroid Build Coastguard Worker
389*61c4878aSAndroid Build Coastguard Worker // Submessage (bytes) key=8, length=4
390*61c4878aSAndroid Build Coastguard Worker 0x32, 0x04,
391*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=2
392*61c4878aSAndroid Build Coastguard Worker 0x08, 0x02,
393*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=2, v=7
394*61c4878aSAndroid Build Coastguard Worker 0x10, 0x07,
395*61c4878aSAndroid Build Coastguard Worker // End submessage
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
398*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
399*61c4878aSAndroid Build Coastguard Worker };
400*61c4878aSAndroid Build Coastguard Worker // clang-format on
401*61c4878aSAndroid Build Coastguard Worker
402*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
403*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
404*61c4878aSAndroid Build Coastguard Worker
405*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
406*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
407*61c4878aSAndroid Build Coastguard Worker
408*61c4878aSAndroid Build Coastguard Worker // Create a nested encoder for the nested field, but don't use it.
409*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
410*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 6u);
411*61c4878aSAndroid Build Coastguard Worker {
412*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
413*61c4878aSAndroid Build Coastguard Worker }
414*61c4878aSAndroid Build Coastguard Worker
415*61c4878aSAndroid Build Coastguard Worker // The root decoder should still advance to the next field after the nested
416*61c4878aSAndroid Build Coastguard Worker // decoder is closed.
417*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
418*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 2u);
419*61c4878aSAndroid Build Coastguard Worker
420*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
421*61c4878aSAndroid Build Coastguard Worker }
422*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_NonSeekable_AdvancesToNextFieldOnDestruction)423*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder,
424*61c4878aSAndroid Build Coastguard Worker Decode_Nested_NonSeekable_AdvancesToNextFieldOnDestruction) {
425*61c4878aSAndroid Build Coastguard Worker // clang-format off
426*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
427*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
428*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
429*61c4878aSAndroid Build Coastguard Worker
430*61c4878aSAndroid Build Coastguard Worker // Submessage (bytes) key=8, length=4
431*61c4878aSAndroid Build Coastguard Worker 0x32, 0x04,
432*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=2
433*61c4878aSAndroid Build Coastguard Worker 0x08, 0x02,
434*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=2, v=7
435*61c4878aSAndroid Build Coastguard Worker 0x10, 0x07,
436*61c4878aSAndroid Build Coastguard Worker // End submessage
437*61c4878aSAndroid Build Coastguard Worker
438*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
439*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
440*61c4878aSAndroid Build Coastguard Worker };
441*61c4878aSAndroid Build Coastguard Worker // clang-format on
442*61c4878aSAndroid Build Coastguard Worker
443*61c4878aSAndroid Build Coastguard Worker // Test with a non-seekable memory reader
444*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader wrapped_reader(as_bytes(span(encoded_proto)));
445*61c4878aSAndroid Build Coastguard Worker NonSeekableMemoryReader reader(wrapped_reader);
446*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
447*61c4878aSAndroid Build Coastguard Worker
448*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
449*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
450*61c4878aSAndroid Build Coastguard Worker
451*61c4878aSAndroid Build Coastguard Worker // Create a nested encoder for the nested field, but don't use it.
452*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
453*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 6u);
454*61c4878aSAndroid Build Coastguard Worker {
455*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
456*61c4878aSAndroid Build Coastguard Worker }
457*61c4878aSAndroid Build Coastguard Worker
458*61c4878aSAndroid Build Coastguard Worker // The root decoder should still advance to the next field after the nested
459*61c4878aSAndroid Build Coastguard Worker // decoder is closed.
460*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
461*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 2u);
462*61c4878aSAndroid Build Coastguard Worker
463*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
464*61c4878aSAndroid Build Coastguard Worker }
465*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_LastField)466*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_LastField) {
467*61c4878aSAndroid Build Coastguard Worker // clang-format off
468*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
469*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
470*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
471*61c4878aSAndroid Build Coastguard Worker
472*61c4878aSAndroid Build Coastguard Worker // Submessage (bytes) key=8, length=4
473*61c4878aSAndroid Build Coastguard Worker 0x32, 0x04,
474*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=2
475*61c4878aSAndroid Build Coastguard Worker 0x08, 0x02,
476*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=2, v=7
477*61c4878aSAndroid Build Coastguard Worker 0x10, 0x07,
478*61c4878aSAndroid Build Coastguard Worker // End submessage and proto
479*61c4878aSAndroid Build Coastguard Worker };
480*61c4878aSAndroid Build Coastguard Worker // clang-format on
481*61c4878aSAndroid Build Coastguard Worker
482*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
483*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
484*61c4878aSAndroid Build Coastguard Worker
485*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
486*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
487*61c4878aSAndroid Build Coastguard Worker
488*61c4878aSAndroid Build Coastguard Worker // Create a nested encoder for the nested field, which is the last field in
489*61c4878aSAndroid Build Coastguard Worker // the root proto.
490*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
491*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 6u);
492*61c4878aSAndroid Build Coastguard Worker {
493*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
494*61c4878aSAndroid Build Coastguard Worker }
495*61c4878aSAndroid Build Coastguard Worker
496*61c4878aSAndroid Build Coastguard Worker // Root decoder should correctly terminate after the nested decoder is closed.
497*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
498*61c4878aSAndroid Build Coastguard Worker }
499*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_MultiLevel)500*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_MultiLevel) {
501*61c4878aSAndroid Build Coastguard Worker // clang-format off
502*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
503*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=4
504*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x04,
505*61c4878aSAndroid Build Coastguard Worker
506*61c4878aSAndroid Build Coastguard Worker // Sub-submessage key=1, length=2
507*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x02,
508*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=2, v=7
509*61c4878aSAndroid Build Coastguard Worker 0x10, 0x07,
510*61c4878aSAndroid Build Coastguard Worker // End sub-submessage
511*61c4878aSAndroid Build Coastguard Worker
512*61c4878aSAndroid Build Coastguard Worker // End submessage
513*61c4878aSAndroid Build Coastguard Worker };
514*61c4878aSAndroid Build Coastguard Worker // clang-format on
515*61c4878aSAndroid Build Coastguard Worker
516*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
517*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
518*61c4878aSAndroid Build Coastguard Worker
519*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
520*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
521*61c4878aSAndroid Build Coastguard Worker {
522*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
523*61c4878aSAndroid Build Coastguard Worker
524*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
525*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
526*61c4878aSAndroid Build Coastguard Worker
527*61c4878aSAndroid Build Coastguard Worker {
528*61c4878aSAndroid Build Coastguard Worker StreamDecoder double_nested = nested.GetNestedDecoder();
529*61c4878aSAndroid Build Coastguard Worker
530*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(double_nested.Next(), OkStatus());
531*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*double_nested.FieldNumber(), 2u);
532*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> result = double_nested.ReadUint32();
533*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(result.status(), OkStatus());
534*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(result.value(), 7u);
535*61c4878aSAndroid Build Coastguard Worker
536*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(double_nested.Next(), Status::OutOfRange());
537*61c4878aSAndroid Build Coastguard Worker }
538*61c4878aSAndroid Build Coastguard Worker
539*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::OutOfRange());
540*61c4878aSAndroid Build Coastguard Worker }
541*61c4878aSAndroid Build Coastguard Worker
542*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
543*61c4878aSAndroid Build Coastguard Worker }
544*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_InvalidField)545*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_InvalidField) {
546*61c4878aSAndroid Build Coastguard Worker // clang-format off
547*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
548*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=4
549*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x04,
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard Worker // Oops. No data!
552*61c4878aSAndroid Build Coastguard Worker };
553*61c4878aSAndroid Build Coastguard Worker
554*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
555*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
556*61c4878aSAndroid Build Coastguard Worker
557*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
558*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
559*61c4878aSAndroid Build Coastguard Worker {
560*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
561*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
562*61c4878aSAndroid Build Coastguard Worker }
563*61c4878aSAndroid Build Coastguard Worker
564*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
565*61c4878aSAndroid Build Coastguard Worker }
566*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_InvalidFieldKey)567*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_InvalidFieldKey) {
568*61c4878aSAndroid Build Coastguard Worker // clang-format off
569*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
570*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
571*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x02,
572*61c4878aSAndroid Build Coastguard Worker // type=invalid...
573*61c4878aSAndroid Build Coastguard Worker 0xff, 0xff,
574*61c4878aSAndroid Build Coastguard Worker // End submessage
575*61c4878aSAndroid Build Coastguard Worker
576*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
577*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
578*61c4878aSAndroid Build Coastguard Worker };
579*61c4878aSAndroid Build Coastguard Worker // clang-format on
580*61c4878aSAndroid Build Coastguard Worker
581*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
582*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
583*61c4878aSAndroid Build Coastguard Worker
584*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
585*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
586*61c4878aSAndroid Build Coastguard Worker
587*61c4878aSAndroid Build Coastguard Worker {
588*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
589*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
590*61c4878aSAndroid Build Coastguard Worker
591*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
592*61c4878aSAndroid Build Coastguard Worker // submessage.
593*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 4u);
594*61c4878aSAndroid Build Coastguard Worker }
595*61c4878aSAndroid Build Coastguard Worker }
596*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_MissingDelimitedLength)597*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_MissingDelimitedLength) {
598*61c4878aSAndroid Build Coastguard Worker // clang-format off
599*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
600*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=1
601*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x01,
602*61c4878aSAndroid Build Coastguard Worker // Delimited field (bytes) key=1, length=missing...
603*61c4878aSAndroid Build Coastguard Worker 0x0a,
604*61c4878aSAndroid Build Coastguard Worker // End submessage
605*61c4878aSAndroid Build Coastguard Worker
606*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
607*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
608*61c4878aSAndroid Build Coastguard Worker };
609*61c4878aSAndroid Build Coastguard Worker // clang-format on
610*61c4878aSAndroid Build Coastguard Worker
611*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
612*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
613*61c4878aSAndroid Build Coastguard Worker
614*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
615*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
616*61c4878aSAndroid Build Coastguard Worker
617*61c4878aSAndroid Build Coastguard Worker {
618*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
619*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
620*61c4878aSAndroid Build Coastguard Worker
621*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
622*61c4878aSAndroid Build Coastguard Worker // submessage.
623*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 3u);
624*61c4878aSAndroid Build Coastguard Worker }
625*61c4878aSAndroid Build Coastguard Worker }
626*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_InvalidDelimitedLength)627*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_InvalidDelimitedLength) {
628*61c4878aSAndroid Build Coastguard Worker // clang-format off
629*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
630*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
631*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x02,
632*61c4878aSAndroid Build Coastguard Worker // Delimited field (bytes) key=1, length=invalid...
633*61c4878aSAndroid Build Coastguard Worker 0x0a, 0xff,
634*61c4878aSAndroid Build Coastguard Worker // End submessage
635*61c4878aSAndroid Build Coastguard Worker
636*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
637*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
638*61c4878aSAndroid Build Coastguard Worker };
639*61c4878aSAndroid Build Coastguard Worker // clang-format on
640*61c4878aSAndroid Build Coastguard Worker
641*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
642*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
643*61c4878aSAndroid Build Coastguard Worker
644*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
645*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
646*61c4878aSAndroid Build Coastguard Worker
647*61c4878aSAndroid Build Coastguard Worker {
648*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
649*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
650*61c4878aSAndroid Build Coastguard Worker
651*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
652*61c4878aSAndroid Build Coastguard Worker // submessage.
653*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 4u);
654*61c4878aSAndroid Build Coastguard Worker }
655*61c4878aSAndroid Build Coastguard Worker }
656*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_InvalidVarint)657*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_InvalidVarint) {
658*61c4878aSAndroid Build Coastguard Worker // clang-format off
659*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
660*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
661*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x02,
662*61c4878aSAndroid Build Coastguard Worker // type=uint32 key=1, value=invalid...
663*61c4878aSAndroid Build Coastguard Worker 0x08, 0xff,
664*61c4878aSAndroid Build Coastguard Worker // End submessage
665*61c4878aSAndroid Build Coastguard Worker
666*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
667*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
668*61c4878aSAndroid Build Coastguard Worker };
669*61c4878aSAndroid Build Coastguard Worker // clang-format on
670*61c4878aSAndroid Build Coastguard Worker
671*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
672*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
673*61c4878aSAndroid Build Coastguard Worker
674*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
675*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
676*61c4878aSAndroid Build Coastguard Worker
677*61c4878aSAndroid Build Coastguard Worker {
678*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
679*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
680*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
681*61c4878aSAndroid Build Coastguard Worker
682*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> uint32 = nested.ReadUint32();
683*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.status(), Status::DataLoss());
684*61c4878aSAndroid Build Coastguard Worker
685*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
686*61c4878aSAndroid Build Coastguard Worker // submessage.
687*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 4u);
688*61c4878aSAndroid Build Coastguard Worker }
689*61c4878aSAndroid Build Coastguard Worker }
690*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_SkipInvalidVarint)691*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_SkipInvalidVarint) {
692*61c4878aSAndroid Build Coastguard Worker // clang-format off
693*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
694*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
695*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x02,
696*61c4878aSAndroid Build Coastguard Worker // type=uint32 key=1, value=invalid...
697*61c4878aSAndroid Build Coastguard Worker 0x08, 0xff,
698*61c4878aSAndroid Build Coastguard Worker // End submessage
699*61c4878aSAndroid Build Coastguard Worker
700*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
701*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
702*61c4878aSAndroid Build Coastguard Worker };
703*61c4878aSAndroid Build Coastguard Worker // clang-format on
704*61c4878aSAndroid Build Coastguard Worker
705*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
706*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
707*61c4878aSAndroid Build Coastguard Worker
708*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
709*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
710*61c4878aSAndroid Build Coastguard Worker
711*61c4878aSAndroid Build Coastguard Worker {
712*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
713*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
714*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
715*61c4878aSAndroid Build Coastguard Worker
716*61c4878aSAndroid Build Coastguard Worker // Skip without reading.
717*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
718*61c4878aSAndroid Build Coastguard Worker
719*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
720*61c4878aSAndroid Build Coastguard Worker // submessage.
721*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 4u);
722*61c4878aSAndroid Build Coastguard Worker }
723*61c4878aSAndroid Build Coastguard Worker }
724*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_TruncatedFixed)725*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_TruncatedFixed) {
726*61c4878aSAndroid Build Coastguard Worker // clang-format off
727*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
728*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
729*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x03,
730*61c4878aSAndroid Build Coastguard Worker // type=fixed32 key=1, value=truncated...
731*61c4878aSAndroid Build Coastguard Worker 0x0d, 0x42, 0x00,
732*61c4878aSAndroid Build Coastguard Worker // End submessage
733*61c4878aSAndroid Build Coastguard Worker
734*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
735*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
736*61c4878aSAndroid Build Coastguard Worker };
737*61c4878aSAndroid Build Coastguard Worker // clang-format on
738*61c4878aSAndroid Build Coastguard Worker
739*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
740*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
741*61c4878aSAndroid Build Coastguard Worker
742*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
743*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
744*61c4878aSAndroid Build Coastguard Worker
745*61c4878aSAndroid Build Coastguard Worker {
746*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
747*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
748*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
749*61c4878aSAndroid Build Coastguard Worker
750*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> uint32 = nested.ReadFixed32();
751*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.status(), Status::DataLoss());
752*61c4878aSAndroid Build Coastguard Worker
753*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
754*61c4878aSAndroid Build Coastguard Worker // submessage. Note that this will not read the data at all in this case.
755*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 3u);
756*61c4878aSAndroid Build Coastguard Worker }
757*61c4878aSAndroid Build Coastguard Worker }
758*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_Nested_SkipTruncatedFixed)759*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_Nested_SkipTruncatedFixed) {
760*61c4878aSAndroid Build Coastguard Worker // clang-format off
761*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
762*61c4878aSAndroid Build Coastguard Worker // Submessage key=1, length=2
763*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x03,
764*61c4878aSAndroid Build Coastguard Worker // type=fixed32 key=1, value=truncated...
765*61c4878aSAndroid Build Coastguard Worker 0x0d, 0x42, 0x00,
766*61c4878aSAndroid Build Coastguard Worker // End submessage
767*61c4878aSAndroid Build Coastguard Worker
768*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
769*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
770*61c4878aSAndroid Build Coastguard Worker };
771*61c4878aSAndroid Build Coastguard Worker // clang-format on
772*61c4878aSAndroid Build Coastguard Worker
773*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
774*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
775*61c4878aSAndroid Build Coastguard Worker
776*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
777*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
778*61c4878aSAndroid Build Coastguard Worker
779*61c4878aSAndroid Build Coastguard Worker {
780*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested = decoder.GetNestedDecoder();
781*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), OkStatus());
782*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*nested.FieldNumber(), 1u);
783*61c4878aSAndroid Build Coastguard Worker
784*61c4878aSAndroid Build Coastguard Worker // Skip without reading.
785*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested.Next(), Status::DataLoss());
786*61c4878aSAndroid Build Coastguard Worker
787*61c4878aSAndroid Build Coastguard Worker // Make sure that the nested decoder didn't run off the end of the
788*61c4878aSAndroid Build Coastguard Worker // submessage. Note that this will be unable to skip the field without
789*61c4878aSAndroid Build Coastguard Worker // exceeding the range of the nested decoder, so it won't move the cursor.
790*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(reader.Tell(), 3u);
791*61c4878aSAndroid Build Coastguard Worker }
792*61c4878aSAndroid Build Coastguard Worker }
793*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BytesReader)794*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BytesReader) {
795*61c4878aSAndroid Build Coastguard Worker // clang-format off
796*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
797*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=14
798*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0e,
799*61c4878aSAndroid Build Coastguard Worker
800*61c4878aSAndroid Build Coastguard Worker 0x00, 0x01, 0x02, 0x03,
801*61c4878aSAndroid Build Coastguard Worker 0x04, 0x05, 0x06, 0x07,
802*61c4878aSAndroid Build Coastguard Worker 0x08, 0x09, 0x0a, 0x0b,
803*61c4878aSAndroid Build Coastguard Worker 0x0c, 0x0d,
804*61c4878aSAndroid Build Coastguard Worker };
805*61c4878aSAndroid Build Coastguard Worker // clang-format on
806*61c4878aSAndroid Build Coastguard Worker
807*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
808*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
809*61c4878aSAndroid Build Coastguard Worker
810*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
811*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 1u);
812*61c4878aSAndroid Build Coastguard Worker {
813*61c4878aSAndroid Build Coastguard Worker StreamDecoder::BytesReader bytes = decoder.GetBytesReader();
814*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.field_size(), 14u);
815*61c4878aSAndroid Build Coastguard Worker
816*61c4878aSAndroid Build Coastguard Worker std::byte buffer[7];
817*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
818*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 2, sizeof(buffer)), 0);
819*61c4878aSAndroid Build Coastguard Worker
820*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
821*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 9, sizeof(buffer)), 0);
822*61c4878aSAndroid Build Coastguard Worker
823*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), Status::OutOfRange());
824*61c4878aSAndroid Build Coastguard Worker }
825*61c4878aSAndroid Build Coastguard Worker
826*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
827*61c4878aSAndroid Build Coastguard Worker }
828*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BytesReader_Seek)829*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BytesReader_Seek) {
830*61c4878aSAndroid Build Coastguard Worker // clang-format off
831*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
832*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=14
833*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0e,
834*61c4878aSAndroid Build Coastguard Worker
835*61c4878aSAndroid Build Coastguard Worker 0x00, 0x01, 0x02, 0x03,
836*61c4878aSAndroid Build Coastguard Worker 0x04, 0x05, 0x06, 0x07,
837*61c4878aSAndroid Build Coastguard Worker 0x08, 0x09, 0x0a, 0x0b,
838*61c4878aSAndroid Build Coastguard Worker 0x0c, 0x0d,
839*61c4878aSAndroid Build Coastguard Worker };
840*61c4878aSAndroid Build Coastguard Worker // clang-format on
841*61c4878aSAndroid Build Coastguard Worker
842*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
843*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
844*61c4878aSAndroid Build Coastguard Worker
845*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
846*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 1u);
847*61c4878aSAndroid Build Coastguard Worker {
848*61c4878aSAndroid Build Coastguard Worker StreamDecoder::BytesReader bytes = decoder.GetBytesReader();
849*61c4878aSAndroid Build Coastguard Worker
850*61c4878aSAndroid Build Coastguard Worker std::byte buffer[2];
851*61c4878aSAndroid Build Coastguard Worker
852*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(3), OkStatus());
853*61c4878aSAndroid Build Coastguard Worker
854*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
855*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 5, sizeof(buffer)), 0);
856*61c4878aSAndroid Build Coastguard Worker
857*61c4878aSAndroid Build Coastguard Worker // Bad seek offset (absolute).
858*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(15), Status::OutOfRange());
859*61c4878aSAndroid Build Coastguard Worker
860*61c4878aSAndroid Build Coastguard Worker // Seek back from current position.
861*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(-4, stream::Stream::kCurrent), OkStatus());
862*61c4878aSAndroid Build Coastguard Worker
863*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
864*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 3, sizeof(buffer)), 0);
865*61c4878aSAndroid Build Coastguard Worker
866*61c4878aSAndroid Build Coastguard Worker // Bad seek offset (relative).
867*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(-4, stream::Stream::kCurrent), Status::OutOfRange());
868*61c4878aSAndroid Build Coastguard Worker
869*61c4878aSAndroid Build Coastguard Worker // Seek from the end of the bytes field.
870*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(-2, stream::Stream::kEnd), OkStatus());
871*61c4878aSAndroid Build Coastguard Worker
872*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
873*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 14, sizeof(buffer)), 0);
874*61c4878aSAndroid Build Coastguard Worker
875*61c4878aSAndroid Build Coastguard Worker // Bad seek offset (end).
876*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(bytes.Seek(-15, stream::Stream::kEnd), Status::OutOfRange());
877*61c4878aSAndroid Build Coastguard Worker }
878*61c4878aSAndroid Build Coastguard Worker
879*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
880*61c4878aSAndroid Build Coastguard Worker }
881*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BytesReader_Close)882*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BytesReader_Close) {
883*61c4878aSAndroid Build Coastguard Worker // clang-format off
884*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
885*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=14
886*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0e,
887*61c4878aSAndroid Build Coastguard Worker
888*61c4878aSAndroid Build Coastguard Worker 0x00, 0x01, 0x02, 0x03,
889*61c4878aSAndroid Build Coastguard Worker 0x04, 0x05, 0x06, 0x07,
890*61c4878aSAndroid Build Coastguard Worker 0x08, 0x09, 0x0a, 0x0b,
891*61c4878aSAndroid Build Coastguard Worker 0x0c, 0x0d,
892*61c4878aSAndroid Build Coastguard Worker // End bytes
893*61c4878aSAndroid Build Coastguard Worker
894*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
895*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
896*61c4878aSAndroid Build Coastguard Worker };
897*61c4878aSAndroid Build Coastguard Worker // clang-format on
898*61c4878aSAndroid Build Coastguard Worker
899*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
900*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
901*61c4878aSAndroid Build Coastguard Worker
902*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
903*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 1u);
904*61c4878aSAndroid Build Coastguard Worker {
905*61c4878aSAndroid Build Coastguard Worker // Partially consume the bytes field.
906*61c4878aSAndroid Build Coastguard Worker StreamDecoder::BytesReader bytes = decoder.GetBytesReader();
907*61c4878aSAndroid Build Coastguard Worker
908*61c4878aSAndroid Build Coastguard Worker std::byte buffer[2];
909*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
910*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 2, sizeof(buffer)), 0);
911*61c4878aSAndroid Build Coastguard Worker }
912*61c4878aSAndroid Build Coastguard Worker
913*61c4878aSAndroid Build Coastguard Worker // Continue reading the top-level message.
914*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
915*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 2u);
916*61c4878aSAndroid Build Coastguard Worker
917*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
918*61c4878aSAndroid Build Coastguard Worker }
919*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BytesReader_NonSeekable_Close)920*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BytesReader_NonSeekable_Close) {
921*61c4878aSAndroid Build Coastguard Worker // clang-format off
922*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
923*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=14
924*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0e,
925*61c4878aSAndroid Build Coastguard Worker
926*61c4878aSAndroid Build Coastguard Worker 0x00, 0x01, 0x02, 0x03,
927*61c4878aSAndroid Build Coastguard Worker 0x04, 0x05, 0x06, 0x07,
928*61c4878aSAndroid Build Coastguard Worker 0x08, 0x09, 0x0a, 0x0b,
929*61c4878aSAndroid Build Coastguard Worker 0x0c, 0x0d,
930*61c4878aSAndroid Build Coastguard Worker // End bytes
931*61c4878aSAndroid Build Coastguard Worker
932*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
933*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
934*61c4878aSAndroid Build Coastguard Worker };
935*61c4878aSAndroid Build Coastguard Worker // clang-format on
936*61c4878aSAndroid Build Coastguard Worker
937*61c4878aSAndroid Build Coastguard Worker // Test with a non-seekable memory reader
938*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader wrapped_reader(as_bytes(span(encoded_proto)));
939*61c4878aSAndroid Build Coastguard Worker NonSeekableMemoryReader reader(wrapped_reader);
940*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
941*61c4878aSAndroid Build Coastguard Worker
942*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
943*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 1u);
944*61c4878aSAndroid Build Coastguard Worker {
945*61c4878aSAndroid Build Coastguard Worker // Partially consume the bytes field.
946*61c4878aSAndroid Build Coastguard Worker StreamDecoder::BytesReader bytes = decoder.GetBytesReader();
947*61c4878aSAndroid Build Coastguard Worker
948*61c4878aSAndroid Build Coastguard Worker std::byte buffer[2];
949*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), OkStatus());
950*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(std::memcmp(buffer, encoded_proto + 2, sizeof(buffer)), 0);
951*61c4878aSAndroid Build Coastguard Worker }
952*61c4878aSAndroid Build Coastguard Worker
953*61c4878aSAndroid Build Coastguard Worker // Continue reading the top-level message.
954*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
955*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*decoder.FieldNumber(), 2u);
956*61c4878aSAndroid Build Coastguard Worker
957*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
958*61c4878aSAndroid Build Coastguard Worker }
959*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_BytesReader_InvalidField)960*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_BytesReader_InvalidField) {
961*61c4878aSAndroid Build Coastguard Worker // clang-format off
962*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
963*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=4
964*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x04,
965*61c4878aSAndroid Build Coastguard Worker
966*61c4878aSAndroid Build Coastguard Worker // Oops. No data!
967*61c4878aSAndroid Build Coastguard Worker };
968*61c4878aSAndroid Build Coastguard Worker
969*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
970*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
971*61c4878aSAndroid Build Coastguard Worker
972*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
973*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(*decoder.FieldNumber(), 1u);
974*61c4878aSAndroid Build Coastguard Worker {
975*61c4878aSAndroid Build Coastguard Worker StreamDecoder::BytesReader bytes = decoder.GetBytesReader();
976*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Seek(0), Status::DataLoss());
977*61c4878aSAndroid Build Coastguard Worker
978*61c4878aSAndroid Build Coastguard Worker std::byte buffer[2];
979*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(bytes.Read(buffer).status(), Status::DataLoss());
980*61c4878aSAndroid Build Coastguard Worker }
981*61c4878aSAndroid Build Coastguard Worker
982*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::DataLoss());
983*61c4878aSAndroid Build Coastguard Worker }
984*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,GetLengthDelimitedPayloadBounds)985*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, GetLengthDelimitedPayloadBounds) {
986*61c4878aSAndroid Build Coastguard Worker // clang-format off
987*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
988*61c4878aSAndroid Build Coastguard Worker // bytes key=1, length=14
989*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0e,
990*61c4878aSAndroid Build Coastguard Worker
991*61c4878aSAndroid Build Coastguard Worker 0x00, 0x01, 0x02, 0x03,
992*61c4878aSAndroid Build Coastguard Worker 0x04, 0x05, 0x06, 0x07,
993*61c4878aSAndroid Build Coastguard Worker 0x08, 0x09, 0x0a, 0x0b,
994*61c4878aSAndroid Build Coastguard Worker 0x0c, 0x0d,
995*61c4878aSAndroid Build Coastguard Worker // End bytes
996*61c4878aSAndroid Build Coastguard Worker
997*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
998*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
999*61c4878aSAndroid Build Coastguard Worker };
1000*61c4878aSAndroid Build Coastguard Worker // clang-format on
1001*61c4878aSAndroid Build Coastguard Worker
1002*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1003*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1004*61c4878aSAndroid Build Coastguard Worker
1005*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), decoder.Next());
1006*61c4878aSAndroid Build Coastguard Worker Result<StreamDecoder::Bounds> field_bound =
1007*61c4878aSAndroid Build Coastguard Worker decoder.GetLengthDelimitedPayloadBounds();
1008*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), field_bound.status());
1009*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(field_bound.value().low, 2ULL);
1010*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(field_bound.value().high, 16ULL);
1011*61c4878aSAndroid Build Coastguard Worker
1012*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), decoder.Next());
1013*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::NotFound(),
1014*61c4878aSAndroid Build Coastguard Worker decoder.GetLengthDelimitedPayloadBounds().status());
1015*61c4878aSAndroid Build Coastguard Worker }
1016*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,ReadDelimitedField_DoesntOverConsume)1017*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, ReadDelimitedField_DoesntOverConsume) {
1018*61c4878aSAndroid Build Coastguard Worker // clang-format off
1019*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1020*61c4878aSAndroid Build Coastguard Worker // type=string, k=1, v="Hello world"
1021*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
1022*61c4878aSAndroid Build Coastguard Worker // type=int32, k=2, v=42
1023*61c4878aSAndroid Build Coastguard Worker 0x10, 0x2a,
1024*61c4878aSAndroid Build Coastguard Worker };
1025*61c4878aSAndroid Build Coastguard Worker // clang-format on
1026*61c4878aSAndroid Build Coastguard Worker
1027*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1028*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1029*61c4878aSAndroid Build Coastguard Worker
1030*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), decoder.Next());
1031*61c4878aSAndroid Build Coastguard Worker
1032*61c4878aSAndroid Build Coastguard Worker // This buffer is much larger than the string.
1033*61c4878aSAndroid Build Coastguard Worker char buffer[128];
1034*61c4878aSAndroid Build Coastguard Worker const StatusWithSize size = decoder.ReadString(buffer);
1035*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.status(), OkStatus());
1036*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 11u);
1037*61c4878aSAndroid Build Coastguard Worker
1038*61c4878aSAndroid Build Coastguard Worker // Make sure we can still read the next field.
1039*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), decoder.Next());
1040*61c4878aSAndroid Build Coastguard Worker const pw::Result<int32_t> result = decoder.ReadInt32();
1041*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(result.status(), OkStatus());
1042*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(result.value(), 42);
1043*61c4878aSAndroid Build Coastguard Worker }
1044*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_WithLength)1045*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_WithLength) {
1046*61c4878aSAndroid Build Coastguard Worker // clang-format off
1047*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1048*61c4878aSAndroid Build Coastguard Worker // type=int32, k=1, v=42
1049*61c4878aSAndroid Build Coastguard Worker 0x08, 0x2a,
1050*61c4878aSAndroid Build Coastguard Worker // This field is beyond the range of the protobuf:
1051*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
1052*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
1053*61c4878aSAndroid Build Coastguard Worker };
1054*61c4878aSAndroid Build Coastguard Worker // clang-format on
1055*61c4878aSAndroid Build Coastguard Worker
1056*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1057*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader, /*length=*/2u);
1058*61c4878aSAndroid Build Coastguard Worker
1059*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1060*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1061*61c4878aSAndroid Build Coastguard Worker Result<int32_t> int32 = decoder.ReadInt32();
1062*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(int32.status(), OkStatus());
1063*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(int32.value(), 42);
1064*61c4878aSAndroid Build Coastguard Worker
1065*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
1066*61c4878aSAndroid Build Coastguard Worker }
1067*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,Decode_WithLength_SkipsToEnd)1068*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, Decode_WithLength_SkipsToEnd) {
1069*61c4878aSAndroid Build Coastguard Worker // clang-format off
1070*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1071*61c4878aSAndroid Build Coastguard Worker // type=string, k=1, v="Hello world"
1072*61c4878aSAndroid Build Coastguard Worker 0x08, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
1073*61c4878aSAndroid Build Coastguard Worker // This field is beyond the range of the protobuf:
1074*61c4878aSAndroid Build Coastguard Worker // type=sint32, k=2, v=-13
1075*61c4878aSAndroid Build Coastguard Worker 0x10, 0x19,
1076*61c4878aSAndroid Build Coastguard Worker };
1077*61c4878aSAndroid Build Coastguard Worker // clang-format on
1078*61c4878aSAndroid Build Coastguard Worker
1079*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1080*61c4878aSAndroid Build Coastguard Worker {
1081*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader, /*length=*/13u);
1082*61c4878aSAndroid Build Coastguard Worker
1083*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1084*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1085*61c4878aSAndroid Build Coastguard Worker // Don't read the value out, or advance further. Destructing the object
1086*61c4878aSAndroid Build Coastguard Worker // should advance to the end of the length given.
1087*61c4878aSAndroid Build Coastguard Worker }
1088*61c4878aSAndroid Build Coastguard Worker
1089*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(reader.Tell(), 13u);
1090*61c4878aSAndroid Build Coastguard Worker }
1091*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,RepeatedField)1092*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, RepeatedField) {
1093*61c4878aSAndroid Build Coastguard Worker // clang-format off
1094*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1095*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=0
1096*61c4878aSAndroid Build Coastguard Worker 0x08, 0x00,
1097*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=50
1098*61c4878aSAndroid Build Coastguard Worker 0x08, 0x32,
1099*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=100
1100*61c4878aSAndroid Build Coastguard Worker 0x08, 0x64,
1101*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=150
1102*61c4878aSAndroid Build Coastguard Worker 0x08, 0x96, 0x01,
1103*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=200
1104*61c4878aSAndroid Build Coastguard Worker 0x08, 0xc8, 0x01
1105*61c4878aSAndroid Build Coastguard Worker };
1106*61c4878aSAndroid Build Coastguard Worker // clang-format on
1107*61c4878aSAndroid Build Coastguard Worker
1108*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1109*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1110*61c4878aSAndroid Build Coastguard Worker
1111*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1112*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1113*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> uint32 = decoder.ReadUint32();
1114*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
1115*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 0u);
1116*61c4878aSAndroid Build Coastguard Worker
1117*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1118*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1119*61c4878aSAndroid Build Coastguard Worker uint32 = decoder.ReadUint32();
1120*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
1121*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 50u);
1122*61c4878aSAndroid Build Coastguard Worker
1123*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1124*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1125*61c4878aSAndroid Build Coastguard Worker uint32 = decoder.ReadUint32();
1126*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
1127*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 100u);
1128*61c4878aSAndroid Build Coastguard Worker
1129*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1130*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1131*61c4878aSAndroid Build Coastguard Worker uint32 = decoder.ReadUint32();
1132*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
1133*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 150u);
1134*61c4878aSAndroid Build Coastguard Worker
1135*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1136*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1137*61c4878aSAndroid Build Coastguard Worker uint32 = decoder.ReadUint32();
1138*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(uint32.status(), OkStatus());
1139*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.value(), 200u);
1140*61c4878aSAndroid Build Coastguard Worker
1141*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
1142*61c4878aSAndroid Build Coastguard Worker }
1143*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,RepeatedFieldVector)1144*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, RepeatedFieldVector) {
1145*61c4878aSAndroid Build Coastguard Worker // clang-format off
1146*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1147*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=0
1148*61c4878aSAndroid Build Coastguard Worker 0x08, 0x00,
1149*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=50
1150*61c4878aSAndroid Build Coastguard Worker 0x08, 0x32,
1151*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=100
1152*61c4878aSAndroid Build Coastguard Worker 0x08, 0x64,
1153*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=150
1154*61c4878aSAndroid Build Coastguard Worker 0x08, 0x96, 0x01,
1155*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=200
1156*61c4878aSAndroid Build Coastguard Worker 0x08, 0xc8, 0x01
1157*61c4878aSAndroid Build Coastguard Worker };
1158*61c4878aSAndroid Build Coastguard Worker // clang-format on
1159*61c4878aSAndroid Build Coastguard Worker
1160*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1161*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1162*61c4878aSAndroid Build Coastguard Worker
1163*61c4878aSAndroid Build Coastguard Worker pw::Vector<uint32_t, 8> uint32{};
1164*61c4878aSAndroid Build Coastguard Worker
1165*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1166*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1167*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedUint32(uint32);
1168*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1169*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 1u);
1170*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1171*61c4878aSAndroid Build Coastguard Worker
1172*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1173*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1174*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1175*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1176*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 2u);
1177*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1178*61c4878aSAndroid Build Coastguard Worker
1179*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1180*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1181*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1182*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1183*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 3u);
1184*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[2], 100u);
1185*61c4878aSAndroid Build Coastguard Worker
1186*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1187*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1188*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1189*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1190*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 4u);
1191*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[3], 150u);
1192*61c4878aSAndroid Build Coastguard Worker
1193*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1194*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1195*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1196*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1197*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 5u);
1198*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[4], 200u);
1199*61c4878aSAndroid Build Coastguard Worker
1200*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
1201*61c4878aSAndroid Build Coastguard Worker }
1202*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,RepeatedFieldVectorFull)1203*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, RepeatedFieldVectorFull) {
1204*61c4878aSAndroid Build Coastguard Worker // clang-format off
1205*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1206*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=0
1207*61c4878aSAndroid Build Coastguard Worker 0x08, 0x00,
1208*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=50
1209*61c4878aSAndroid Build Coastguard Worker 0x08, 0x32,
1210*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=100
1211*61c4878aSAndroid Build Coastguard Worker 0x08, 0x64,
1212*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=150
1213*61c4878aSAndroid Build Coastguard Worker 0x08, 0x96, 0x01,
1214*61c4878aSAndroid Build Coastguard Worker // type=uint32, k=1, v=200
1215*61c4878aSAndroid Build Coastguard Worker 0x08, 0xc8, 0x01
1216*61c4878aSAndroid Build Coastguard Worker };
1217*61c4878aSAndroid Build Coastguard Worker // clang-format on
1218*61c4878aSAndroid Build Coastguard Worker
1219*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1220*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1221*61c4878aSAndroid Build Coastguard Worker
1222*61c4878aSAndroid Build Coastguard Worker pw::Vector<uint32_t, 2> uint32{};
1223*61c4878aSAndroid Build Coastguard Worker
1224*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1225*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1226*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedUint32(uint32);
1227*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1228*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 1u);
1229*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1230*61c4878aSAndroid Build Coastguard Worker
1231*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1232*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1233*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1234*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1235*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 2u);
1236*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1237*61c4878aSAndroid Build Coastguard Worker
1238*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1239*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1240*61c4878aSAndroid Build Coastguard Worker status = decoder.ReadRepeatedUint32(uint32);
1241*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, Status::ResourceExhausted());
1242*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 2u);
1243*61c4878aSAndroid Build Coastguard Worker }
1244*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedVarint)1245*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedVarint) {
1246*61c4878aSAndroid Build Coastguard Worker // clang-format off
1247*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1248*61c4878aSAndroid Build Coastguard Worker // type=uint32[], k=1, v={0, 50, 100, 150, 200}
1249*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x07,
1250*61c4878aSAndroid Build Coastguard Worker 0x00,
1251*61c4878aSAndroid Build Coastguard Worker 0x32,
1252*61c4878aSAndroid Build Coastguard Worker 0x64,
1253*61c4878aSAndroid Build Coastguard Worker 0x96, 0x01,
1254*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1255*61c4878aSAndroid Build Coastguard Worker };
1256*61c4878aSAndroid Build Coastguard Worker // clang-format on
1257*61c4878aSAndroid Build Coastguard Worker
1258*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1259*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1260*61c4878aSAndroid Build Coastguard Worker
1261*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1262*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1263*61c4878aSAndroid Build Coastguard Worker std::array<uint32_t, 8> uint32{};
1264*61c4878aSAndroid Build Coastguard Worker StatusWithSize size = decoder.ReadPackedUint32(uint32);
1265*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1266*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 5u);
1267*61c4878aSAndroid Build Coastguard Worker
1268*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1269*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1270*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[2], 100u);
1271*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[3], 150u);
1272*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[4], 200u);
1273*61c4878aSAndroid Build Coastguard Worker }
1274*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedVarintInsufficientSpace)1275*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedVarintInsufficientSpace) {
1276*61c4878aSAndroid Build Coastguard Worker // clang-format off
1277*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1278*61c4878aSAndroid Build Coastguard Worker // type=uint32[], k=1, v={0, 50, 100, 150, 200}
1279*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x07,
1280*61c4878aSAndroid Build Coastguard Worker 0x00,
1281*61c4878aSAndroid Build Coastguard Worker 0x32,
1282*61c4878aSAndroid Build Coastguard Worker 0x64,
1283*61c4878aSAndroid Build Coastguard Worker 0x96, 0x01,
1284*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1285*61c4878aSAndroid Build Coastguard Worker };
1286*61c4878aSAndroid Build Coastguard Worker // clang-format on
1287*61c4878aSAndroid Build Coastguard Worker
1288*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1289*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1290*61c4878aSAndroid Build Coastguard Worker
1291*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1292*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1293*61c4878aSAndroid Build Coastguard Worker std::array<uint32_t, 2> uint32{};
1294*61c4878aSAndroid Build Coastguard Worker StatusWithSize size = decoder.ReadPackedUint32(uint32);
1295*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), Status::ResourceExhausted());
1296*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 2u);
1297*61c4878aSAndroid Build Coastguard Worker
1298*61c4878aSAndroid Build Coastguard Worker // Still returns values in case of error.
1299*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1300*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1301*61c4878aSAndroid Build Coastguard Worker }
1302*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedVarintVector)1303*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedVarintVector) {
1304*61c4878aSAndroid Build Coastguard Worker // clang-format off
1305*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1306*61c4878aSAndroid Build Coastguard Worker // type=uint32[], k=1, v={0, 50, 100, 150, 200}
1307*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x07,
1308*61c4878aSAndroid Build Coastguard Worker 0x00,
1309*61c4878aSAndroid Build Coastguard Worker 0x32,
1310*61c4878aSAndroid Build Coastguard Worker 0x64,
1311*61c4878aSAndroid Build Coastguard Worker 0x96, 0x01,
1312*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1313*61c4878aSAndroid Build Coastguard Worker };
1314*61c4878aSAndroid Build Coastguard Worker // clang-format on
1315*61c4878aSAndroid Build Coastguard Worker
1316*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1317*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1318*61c4878aSAndroid Build Coastguard Worker
1319*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1320*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1321*61c4878aSAndroid Build Coastguard Worker pw::Vector<uint32_t, 8> uint32{};
1322*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedUint32(uint32);
1323*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1324*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 5u);
1325*61c4878aSAndroid Build Coastguard Worker
1326*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1327*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1328*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[2], 100u);
1329*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[3], 150u);
1330*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[4], 200u);
1331*61c4878aSAndroid Build Coastguard Worker }
1332*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedVarintVectorFull)1333*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedVarintVectorFull) {
1334*61c4878aSAndroid Build Coastguard Worker // clang-format off
1335*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1336*61c4878aSAndroid Build Coastguard Worker // type=uint32[], k=1, v={0, 50, 100, 150, 200}
1337*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x07,
1338*61c4878aSAndroid Build Coastguard Worker 0x00,
1339*61c4878aSAndroid Build Coastguard Worker 0x32,
1340*61c4878aSAndroid Build Coastguard Worker 0x64,
1341*61c4878aSAndroid Build Coastguard Worker 0x96, 0x01,
1342*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1343*61c4878aSAndroid Build Coastguard Worker };
1344*61c4878aSAndroid Build Coastguard Worker // clang-format on
1345*61c4878aSAndroid Build Coastguard Worker
1346*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1347*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1348*61c4878aSAndroid Build Coastguard Worker
1349*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1350*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1351*61c4878aSAndroid Build Coastguard Worker pw::Vector<uint32_t, 2> uint32{};
1352*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedUint32(uint32);
1353*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, Status::ResourceExhausted());
1354*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32.size(), 2u);
1355*61c4878aSAndroid Build Coastguard Worker
1356*61c4878aSAndroid Build Coastguard Worker // Still returns values in case of error.
1357*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[0], 0u);
1358*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(uint32[1], 50u);
1359*61c4878aSAndroid Build Coastguard Worker }
1360*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedZigZag)1361*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedZigZag) {
1362*61c4878aSAndroid Build Coastguard Worker // clang-format off
1363*61c4878aSAndroid Build Coastguard Worker constexpr uint8_t encoded_proto[] = {
1364*61c4878aSAndroid Build Coastguard Worker // type=sint32[], k=1, v={-100, -25, -1, 0, 1, 25, 100}
1365*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x09,
1366*61c4878aSAndroid Build Coastguard Worker 0xc7, 0x01,
1367*61c4878aSAndroid Build Coastguard Worker 0x31,
1368*61c4878aSAndroid Build Coastguard Worker 0x01,
1369*61c4878aSAndroid Build Coastguard Worker 0x00,
1370*61c4878aSAndroid Build Coastguard Worker 0x02,
1371*61c4878aSAndroid Build Coastguard Worker 0x32,
1372*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1373*61c4878aSAndroid Build Coastguard Worker };
1374*61c4878aSAndroid Build Coastguard Worker // clang-format on
1375*61c4878aSAndroid Build Coastguard Worker
1376*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1377*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1378*61c4878aSAndroid Build Coastguard Worker
1379*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1380*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1381*61c4878aSAndroid Build Coastguard Worker std::array<int32_t, 8> sint32{};
1382*61c4878aSAndroid Build Coastguard Worker StatusWithSize size = decoder.ReadPackedSint32(sint32);
1383*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1384*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 7u);
1385*61c4878aSAndroid Build Coastguard Worker
1386*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[0], -100);
1387*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[1], -25);
1388*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[2], -1);
1389*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[3], 0);
1390*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[4], 1);
1391*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[5], 25);
1392*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[6], 100);
1393*61c4878aSAndroid Build Coastguard Worker }
1394*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedZigZagVector)1395*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedZigZagVector) {
1396*61c4878aSAndroid Build Coastguard Worker // clang-format off
1397*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1398*61c4878aSAndroid Build Coastguard Worker // type=sint32[], k=1, v={-100, -25, -1, 0, 1, 25, 100}
1399*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x09,
1400*61c4878aSAndroid Build Coastguard Worker 0xc7, 0x01,
1401*61c4878aSAndroid Build Coastguard Worker 0x31,
1402*61c4878aSAndroid Build Coastguard Worker 0x01,
1403*61c4878aSAndroid Build Coastguard Worker 0x00,
1404*61c4878aSAndroid Build Coastguard Worker 0x02,
1405*61c4878aSAndroid Build Coastguard Worker 0x32,
1406*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x01
1407*61c4878aSAndroid Build Coastguard Worker };
1408*61c4878aSAndroid Build Coastguard Worker // clang-format on
1409*61c4878aSAndroid Build Coastguard Worker
1410*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1411*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1412*61c4878aSAndroid Build Coastguard Worker
1413*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1414*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1415*61c4878aSAndroid Build Coastguard Worker pw::Vector<int32_t, 8> sint32{};
1416*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedSint32(sint32);
1417*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1418*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32.size(), 7u);
1419*61c4878aSAndroid Build Coastguard Worker
1420*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[0], -100);
1421*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[1], -25);
1422*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[2], -1);
1423*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[3], 0);
1424*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[4], 1);
1425*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[5], 25);
1426*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sint32[6], 100);
1427*61c4878aSAndroid Build Coastguard Worker }
1428*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedFixed)1429*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedFixed) {
1430*61c4878aSAndroid Build Coastguard Worker // clang-format off
1431*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1432*61c4878aSAndroid Build Coastguard Worker // type=fixed32[], k=1, v={0, 50, 100, 150, 200}
1433*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x14,
1434*61c4878aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00,
1435*61c4878aSAndroid Build Coastguard Worker 0x32, 0x00, 0x00, 0x00,
1436*61c4878aSAndroid Build Coastguard Worker 0x64, 0x00, 0x00, 0x00,
1437*61c4878aSAndroid Build Coastguard Worker 0x96, 0x00, 0x00, 0x00,
1438*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x00, 0x00, 0x00,
1439*61c4878aSAndroid Build Coastguard Worker // type=fixed64[], v=2, v={0x0102030405060708}
1440*61c4878aSAndroid Build Coastguard Worker 0x12, 0x08,
1441*61c4878aSAndroid Build Coastguard Worker 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
1442*61c4878aSAndroid Build Coastguard Worker // type=sfixed32[], k=3, v={0, -50, 100, -150, 200}
1443*61c4878aSAndroid Build Coastguard Worker 0x1a, 0x14,
1444*61c4878aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00,
1445*61c4878aSAndroid Build Coastguard Worker 0xce, 0xff, 0xff, 0xff,
1446*61c4878aSAndroid Build Coastguard Worker 0x64, 0x00, 0x00, 0x00,
1447*61c4878aSAndroid Build Coastguard Worker 0x6a, 0xff, 0xff, 0xff,
1448*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x00, 0x00, 0x00,
1449*61c4878aSAndroid Build Coastguard Worker // type=sfixed64[], v=4, v={-1647993274}
1450*61c4878aSAndroid Build Coastguard Worker 0x22, 0x08,
1451*61c4878aSAndroid Build Coastguard Worker 0x46, 0x9e, 0xc5, 0x9d, 0xff, 0xff, 0xff, 0xff,
1452*61c4878aSAndroid Build Coastguard Worker // type=double[], k=5, v=3.14159
1453*61c4878aSAndroid Build Coastguard Worker 0x2a, 0x08,
1454*61c4878aSAndroid Build Coastguard Worker 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
1455*61c4878aSAndroid Build Coastguard Worker // type=float[], k=6, v=2.718
1456*61c4878aSAndroid Build Coastguard Worker 0x32, 0x04,
1457*61c4878aSAndroid Build Coastguard Worker 0xb6, 0xf3, 0x2d, 0x40,
1458*61c4878aSAndroid Build Coastguard Worker };
1459*61c4878aSAndroid Build Coastguard Worker // clang-format on
1460*61c4878aSAndroid Build Coastguard Worker
1461*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1462*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1463*61c4878aSAndroid Build Coastguard Worker
1464*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1465*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1466*61c4878aSAndroid Build Coastguard Worker std::array<uint32_t, 8> fixed32{};
1467*61c4878aSAndroid Build Coastguard Worker StatusWithSize size = decoder.ReadPackedFixed32(fixed32);
1468*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1469*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 5u);
1470*61c4878aSAndroid Build Coastguard Worker
1471*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32[0], 0u);
1472*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32[1], 50u);
1473*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32[2], 100u);
1474*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32[3], 150u);
1475*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed32[4], 200u);
1476*61c4878aSAndroid Build Coastguard Worker
1477*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1478*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 2u);
1479*61c4878aSAndroid Build Coastguard Worker std::array<uint64_t, 8> fixed64{};
1480*61c4878aSAndroid Build Coastguard Worker size = decoder.ReadPackedFixed64(fixed64);
1481*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1482*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 1u);
1483*61c4878aSAndroid Build Coastguard Worker
1484*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(fixed64[0], 0x0102030405060708u);
1485*61c4878aSAndroid Build Coastguard Worker
1486*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1487*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 3u);
1488*61c4878aSAndroid Build Coastguard Worker std::array<int32_t, 8> sfixed32{};
1489*61c4878aSAndroid Build Coastguard Worker size = decoder.ReadPackedSfixed32(sfixed32);
1490*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1491*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 5u);
1492*61c4878aSAndroid Build Coastguard Worker
1493*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[0], 0);
1494*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[1], -50);
1495*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[2], 100);
1496*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[3], -150);
1497*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[4], 200);
1498*61c4878aSAndroid Build Coastguard Worker
1499*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1500*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 4u);
1501*61c4878aSAndroid Build Coastguard Worker std::array<int64_t, 8> sfixed64{};
1502*61c4878aSAndroid Build Coastguard Worker size = decoder.ReadPackedSfixed64(sfixed64);
1503*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1504*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 1u);
1505*61c4878aSAndroid Build Coastguard Worker
1506*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed64[0], -1647993274);
1507*61c4878aSAndroid Build Coastguard Worker
1508*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1509*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 5u);
1510*61c4878aSAndroid Build Coastguard Worker std::array<double, 8> dbl{};
1511*61c4878aSAndroid Build Coastguard Worker size = decoder.ReadPackedDouble(dbl);
1512*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1513*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 1u);
1514*61c4878aSAndroid Build Coastguard Worker
1515*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(dbl[0], 3.14159);
1516*61c4878aSAndroid Build Coastguard Worker
1517*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1518*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 6u);
1519*61c4878aSAndroid Build Coastguard Worker std::array<float, 8> flt{};
1520*61c4878aSAndroid Build Coastguard Worker size = decoder.ReadPackedFloat(flt);
1521*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), OkStatus());
1522*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(size.size(), 1u);
1523*61c4878aSAndroid Build Coastguard Worker
1524*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(flt[0], 2.718f);
1525*61c4878aSAndroid Build Coastguard Worker
1526*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
1527*61c4878aSAndroid Build Coastguard Worker }
1528*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedFixedInsufficientSpace)1529*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedFixedInsufficientSpace) {
1530*61c4878aSAndroid Build Coastguard Worker // clang-format off
1531*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1532*61c4878aSAndroid Build Coastguard Worker // type=fixed32[], k=1, v={0, 50, 100, 150, 200}
1533*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x14,
1534*61c4878aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00,
1535*61c4878aSAndroid Build Coastguard Worker 0x32, 0x00, 0x00, 0x00,
1536*61c4878aSAndroid Build Coastguard Worker 0x64, 0x00, 0x00, 0x00,
1537*61c4878aSAndroid Build Coastguard Worker 0x96, 0x00, 0x00, 0x00,
1538*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x00, 0x00, 0x00,
1539*61c4878aSAndroid Build Coastguard Worker };
1540*61c4878aSAndroid Build Coastguard Worker // clang-format on
1541*61c4878aSAndroid Build Coastguard Worker
1542*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1543*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1544*61c4878aSAndroid Build Coastguard Worker
1545*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1546*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1547*61c4878aSAndroid Build Coastguard Worker std::array<uint32_t, 2> fixed32{};
1548*61c4878aSAndroid Build Coastguard Worker StatusWithSize size = decoder.ReadPackedFixed32(fixed32);
1549*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(size.status(), Status::ResourceExhausted());
1550*61c4878aSAndroid Build Coastguard Worker }
1551*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedFixedVector)1552*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedFixedVector) {
1553*61c4878aSAndroid Build Coastguard Worker // clang-format off
1554*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1555*61c4878aSAndroid Build Coastguard Worker // type=sfixed32[], k=1, v={0, -50, 100, -150, 200}
1556*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x14,
1557*61c4878aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00,
1558*61c4878aSAndroid Build Coastguard Worker 0xce, 0xff, 0xff, 0xff,
1559*61c4878aSAndroid Build Coastguard Worker 0x64, 0x00, 0x00, 0x00,
1560*61c4878aSAndroid Build Coastguard Worker 0x6a, 0xff, 0xff, 0xff,
1561*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x00, 0x00, 0x00,
1562*61c4878aSAndroid Build Coastguard Worker };
1563*61c4878aSAndroid Build Coastguard Worker // clang-format on
1564*61c4878aSAndroid Build Coastguard Worker
1565*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1566*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1567*61c4878aSAndroid Build Coastguard Worker
1568*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1569*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1570*61c4878aSAndroid Build Coastguard Worker pw::Vector<int32_t, 8> sfixed32{};
1571*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedSfixed32(sfixed32);
1572*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, OkStatus());
1573*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32.size(), 5u);
1574*61c4878aSAndroid Build Coastguard Worker
1575*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[0], 0);
1576*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[1], -50);
1577*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[2], 100);
1578*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[3], -150);
1579*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32[4], 200);
1580*61c4878aSAndroid Build Coastguard Worker
1581*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), Status::OutOfRange());
1582*61c4878aSAndroid Build Coastguard Worker }
1583*61c4878aSAndroid Build Coastguard Worker
TEST(StreamDecoder,PackedFixedVectorFull)1584*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, PackedFixedVectorFull) {
1585*61c4878aSAndroid Build Coastguard Worker // clang-format off
1586*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1587*61c4878aSAndroid Build Coastguard Worker // type=sfixed32[], k=1, v={0, -50, 100, -150, 200}
1588*61c4878aSAndroid Build Coastguard Worker 0x0a, 0x14,
1589*61c4878aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00,
1590*61c4878aSAndroid Build Coastguard Worker 0xce, 0xff, 0xff, 0xff,
1591*61c4878aSAndroid Build Coastguard Worker 0x64, 0x00, 0x00, 0x00,
1592*61c4878aSAndroid Build Coastguard Worker 0x6a, 0xff, 0xff, 0xff,
1593*61c4878aSAndroid Build Coastguard Worker 0xc8, 0x00, 0x00, 0x00,
1594*61c4878aSAndroid Build Coastguard Worker };
1595*61c4878aSAndroid Build Coastguard Worker // clang-format on
1596*61c4878aSAndroid Build Coastguard Worker
1597*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1598*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1599*61c4878aSAndroid Build Coastguard Worker
1600*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1601*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(decoder.FieldNumber().value(), 1u);
1602*61c4878aSAndroid Build Coastguard Worker pw::Vector<int32_t, 2> sfixed32{};
1603*61c4878aSAndroid Build Coastguard Worker Status status = decoder.ReadRepeatedSfixed32(sfixed32);
1604*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(status, Status::ResourceExhausted());
1605*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sfixed32.size(), 0u);
1606*61c4878aSAndroid Build Coastguard Worker }
1607*61c4878aSAndroid Build Coastguard Worker
1608*61c4878aSAndroid Build Coastguard Worker // See b/314803709.
TEST(StreamDecoder,NestedIncompleteVarint)1609*61c4878aSAndroid Build Coastguard Worker TEST(StreamDecoder, NestedIncompleteVarint) {
1610*61c4878aSAndroid Build Coastguard Worker // clang-format off
1611*61c4878aSAndroid Build Coastguard Worker static constexpr const uint8_t encoded_proto[] = {
1612*61c4878aSAndroid Build Coastguard Worker 0x4a, 0x02, 0x20, 0xff,
1613*61c4878aSAndroid Build Coastguard Worker };
1614*61c4878aSAndroid Build Coastguard Worker // clang-format on
1615*61c4878aSAndroid Build Coastguard Worker
1616*61c4878aSAndroid Build Coastguard Worker stream::MemoryReader reader(as_bytes(span(encoded_proto)));
1617*61c4878aSAndroid Build Coastguard Worker StreamDecoder decoder(reader);
1618*61c4878aSAndroid Build Coastguard Worker
1619*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(decoder.Next(), OkStatus());
1620*61c4878aSAndroid Build Coastguard Worker StreamDecoder nested_decoder = decoder.GetNestedDecoder();
1621*61c4878aSAndroid Build Coastguard Worker
1622*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested_decoder.Next(), OkStatus());
1623*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(nested_decoder.ReadInt32().status(), Status::DataLoss());
1624*61c4878aSAndroid Build Coastguard Worker }
1625*61c4878aSAndroid Build Coastguard Worker
1626*61c4878aSAndroid Build Coastguard Worker } // namespace
1627*61c4878aSAndroid Build Coastguard Worker } // namespace pw::protobuf
1628