xref: /aosp_15_r20/external/pigweed/pw_protobuf/encoder_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/encoder.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/span.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_span/span.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/memory_stream.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
21*61c4878aSAndroid Build Coastguard Worker 
22*61c4878aSAndroid Build Coastguard Worker namespace pw::protobuf {
23*61c4878aSAndroid Build Coastguard Worker namespace {
24*61c4878aSAndroid Build Coastguard Worker 
25*61c4878aSAndroid Build Coastguard Worker using stream::MemoryWriter;
26*61c4878aSAndroid Build Coastguard Worker 
27*61c4878aSAndroid Build Coastguard Worker // The tests in this file use the following proto message schemas.
28*61c4878aSAndroid Build Coastguard Worker //
29*61c4878aSAndroid Build Coastguard Worker //   message TestProto {
30*61c4878aSAndroid Build Coastguard Worker //     uint32 magic_number = 1;
31*61c4878aSAndroid Build Coastguard Worker //     sint32 ziggy = 2;
32*61c4878aSAndroid Build Coastguard Worker //     fixed64 cycles = 3;
33*61c4878aSAndroid Build Coastguard Worker //     float ratio = 4;
34*61c4878aSAndroid Build Coastguard Worker //     string error_message = 5;
35*61c4878aSAndroid Build Coastguard Worker //     NestedProto nested = 6;
36*61c4878aSAndroid Build Coastguard Worker //   }
37*61c4878aSAndroid Build Coastguard Worker //
38*61c4878aSAndroid Build Coastguard Worker //   message NestedProto {
39*61c4878aSAndroid Build Coastguard Worker //     string hello = 1;
40*61c4878aSAndroid Build Coastguard Worker //     uint32 id = 2;
41*61c4878aSAndroid Build Coastguard Worker //     repeated DoubleNestedProto pair = 3;
42*61c4878aSAndroid Build Coastguard Worker //   }
43*61c4878aSAndroid Build Coastguard Worker //
44*61c4878aSAndroid Build Coastguard Worker //   message DoubleNestedProto {
45*61c4878aSAndroid Build Coastguard Worker //     string key = 1;
46*61c4878aSAndroid Build Coastguard Worker //     string value = 2;
47*61c4878aSAndroid Build Coastguard Worker //   }
48*61c4878aSAndroid Build Coastguard Worker //
49*61c4878aSAndroid Build Coastguard Worker 
50*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoMagicNumberField = 1;
51*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoZiggyField = 2;
52*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoCyclesField = 3;
53*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoRatioField = 4;
54*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoErrorMessageField = 5;
55*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoNestedField = 6;
56*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kTestProtoPayloadFromStreamField = 7;
57*61c4878aSAndroid Build Coastguard Worker 
58*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kNestedProtoHelloField = 1;
59*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kNestedProtoIdField = 2;
60*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kNestedProtoPairField = 3;
61*61c4878aSAndroid Build Coastguard Worker 
62*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kDoubleNestedProtoKeyField = 1;
63*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kDoubleNestedProtoValueField = 2;
64*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,EncodePrimitives)65*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, EncodePrimitives) {
66*61c4878aSAndroid Build Coastguard Worker   // TestProto tp;
67*61c4878aSAndroid Build Coastguard Worker   // tp.magic_number = 42;
68*61c4878aSAndroid Build Coastguard Worker   // tp.ziggy = -13;
69*61c4878aSAndroid Build Coastguard Worker   // tp.cycles = 0xdeadbeef8badf00d;
70*61c4878aSAndroid Build Coastguard Worker   // tp.ratio = 1.618034;
71*61c4878aSAndroid Build Coastguard Worker   // tp.error_message = "broken ��";
72*61c4878aSAndroid Build Coastguard Worker   // tp.payload_from_stream = "byreader"
73*61c4878aSAndroid Build Coastguard Worker 
74*61c4878aSAndroid Build Coastguard Worker   // Hand-encoded version of the above.
75*61c4878aSAndroid Build Coastguard Worker   // clang-format off
76*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
77*61c4878aSAndroid Build Coastguard Worker     // magic_number [varint k=1]
78*61c4878aSAndroid Build Coastguard Worker     0x08, 0x2a,
79*61c4878aSAndroid Build Coastguard Worker     // ziggy [varint k=2]
80*61c4878aSAndroid Build Coastguard Worker     0x10, 0x19,
81*61c4878aSAndroid Build Coastguard Worker     // cycles [fixed64 k=3]
82*61c4878aSAndroid Build Coastguard Worker     0x19, 0x0d, 0xf0, 0xad, 0x8b, 0xef, 0xbe, 0xad, 0xde,
83*61c4878aSAndroid Build Coastguard Worker     // ratio [fixed32 k=4]
84*61c4878aSAndroid Build Coastguard Worker     0x25, 0xbd, 0x1b, 0xcf, 0x3f,
85*61c4878aSAndroid Build Coastguard Worker     // error_message [delimited k=5],
86*61c4878aSAndroid Build Coastguard Worker     0x2a, 0x0b, 'b', 'r', 'o', 'k', 'e', 'n', ' ',
87*61c4878aSAndroid Build Coastguard Worker     // poop!
88*61c4878aSAndroid Build Coastguard Worker     0xf0, 0x9f, 0x92, 0xa9,
89*61c4878aSAndroid Build Coastguard Worker     // payload_from_stream [delimited k=7]
90*61c4878aSAndroid Build Coastguard Worker     0x3a, 0x08, 'b', 'y', 'r', 'e', 'a', 'd', 'e', 'r',
91*61c4878aSAndroid Build Coastguard Worker   };
92*61c4878aSAndroid Build Coastguard Worker   // clang-format on
93*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[64];
94*61c4878aSAndroid Build Coastguard Worker   std::byte dest_buffer[64];
95*61c4878aSAndroid Build Coastguard Worker   // This writer isn't necessary, it's just the most testable way to exercise
96*61c4878aSAndroid Build Coastguard Worker   // a stream interface. Use a MemoryEncoder when encoding a proto directly to
97*61c4878aSAndroid Build Coastguard Worker   // an in-memory buffer.
98*61c4878aSAndroid Build Coastguard Worker   MemoryWriter writer(dest_buffer);
99*61c4878aSAndroid Build Coastguard Worker   StreamEncoder encoder(writer, encode_buffer);
100*61c4878aSAndroid Build Coastguard Worker 
101*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteUint32(kTestProtoMagicNumberField, 42), OkStatus());
102*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(writer.bytes_written(), 2u);
103*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteSint32(kTestProtoZiggyField, -13), OkStatus());
104*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteFixed64(kTestProtoCyclesField, 0xdeadbeef8badf00d),
105*61c4878aSAndroid Build Coastguard Worker             OkStatus());
106*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteFloat(kTestProtoRatioField, 1.618034f), OkStatus());
107*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteString(kTestProtoErrorMessageField, "broken ��"),
108*61c4878aSAndroid Build Coastguard Worker             OkStatus());
109*61c4878aSAndroid Build Coastguard Worker 
110*61c4878aSAndroid Build Coastguard Worker   const std::string_view kReaderMessage = "byreader";
111*61c4878aSAndroid Build Coastguard Worker   stream::MemoryReader msg_reader(as_bytes(span(kReaderMessage)));
112*61c4878aSAndroid Build Coastguard Worker   std::byte stream_pipe_buffer[1];
113*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteStringFromStream(kTestProtoPayloadFromStreamField,
114*61c4878aSAndroid Build Coastguard Worker                                           msg_reader,
115*61c4878aSAndroid Build Coastguard Worker                                           kReaderMessage.size(),
116*61c4878aSAndroid Build Coastguard Worker                                           stream_pipe_buffer),
117*61c4878aSAndroid Build Coastguard Worker             OkStatus());
118*61c4878aSAndroid Build Coastguard Worker 
119*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
120*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result = writer.WrittenData();
121*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
122*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
123*61c4878aSAndroid Build Coastguard Worker             0);
124*61c4878aSAndroid Build Coastguard Worker }
125*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,EncodeInsufficientSpace)126*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, EncodeInsufficientSpace) {
127*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[12];
128*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
129*61c4878aSAndroid Build Coastguard Worker 
130*61c4878aSAndroid Build Coastguard Worker   // 2 bytes.
131*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteUint32(kTestProtoMagicNumberField, 42), OkStatus());
132*61c4878aSAndroid Build Coastguard Worker   // 2 bytes.
133*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteSint32(kTestProtoZiggyField, -13), OkStatus());
134*61c4878aSAndroid Build Coastguard Worker   // 9 bytes; not enough space! The encoder will start writing the field but
135*61c4878aSAndroid Build Coastguard Worker   // should rollback when it realizes it doesn't have enough space.
136*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteFixed64(kTestProtoCyclesField, 0xdeadbeef8badf00d),
137*61c4878aSAndroid Build Coastguard Worker             Status::ResourceExhausted());
138*61c4878aSAndroid Build Coastguard Worker   // Any further write operations should fail.
139*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteFloat(kTestProtoRatioField, 1.618034f),
140*61c4878aSAndroid Build Coastguard Worker             Status::ResourceExhausted());
141*61c4878aSAndroid Build Coastguard Worker 
142*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), Status::ResourceExhausted());
143*61c4878aSAndroid Build Coastguard Worker }
144*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,EncodeInvalidArguments)145*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, EncodeInvalidArguments) {
146*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[12];
147*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
148*61c4878aSAndroid Build Coastguard Worker 
149*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteUint32(kTestProtoMagicNumberField, 42), OkStatus());
150*61c4878aSAndroid Build Coastguard Worker   // Invalid proto field numbers.
151*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteUint32(0, 1337), Status::InvalidArgument());
152*61c4878aSAndroid Build Coastguard Worker 
153*61c4878aSAndroid Build Coastguard Worker   // TODO(amontanez): Does it make sense to support this?
154*61c4878aSAndroid Build Coastguard Worker   // encoder.Clear();
155*61c4878aSAndroid Build Coastguard Worker 
156*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteString(1u << 31, "ha"), Status::InvalidArgument());
157*61c4878aSAndroid Build Coastguard Worker 
158*61c4878aSAndroid Build Coastguard Worker   // TODO(amontanez): Does it make sense to support this?
159*61c4878aSAndroid Build Coastguard Worker   // encoder.Clear();
160*61c4878aSAndroid Build Coastguard Worker 
161*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteBool(19091, false), Status::InvalidArgument());
162*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), Status::InvalidArgument());
163*61c4878aSAndroid Build Coastguard Worker }
164*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,Nested)165*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, Nested) {
166*61c4878aSAndroid Build Coastguard Worker   // This is the largest complete submessage in this test.
167*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kLargestSubmessageSize = 0x30;
168*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kScratchBufferSize =
169*61c4878aSAndroid Build Coastguard Worker       MaxScratchBufferSize(kLargestSubmessageSize, 2);
170*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[kScratchBufferSize];
171*61c4878aSAndroid Build Coastguard Worker   std::byte dest_buffer[128];
172*61c4878aSAndroid Build Coastguard Worker   MemoryWriter writer(dest_buffer);
173*61c4878aSAndroid Build Coastguard Worker   StreamEncoder encoder(writer, encode_buffer);
174*61c4878aSAndroid Build Coastguard Worker 
175*61c4878aSAndroid Build Coastguard Worker   // TestProto test_proto;
176*61c4878aSAndroid Build Coastguard Worker   // test_proto.magic_number = 42;
177*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteUint32(kTestProtoMagicNumberField, 42), OkStatus());
178*61c4878aSAndroid Build Coastguard Worker 
179*61c4878aSAndroid Build Coastguard Worker   {
180*61c4878aSAndroid Build Coastguard Worker     // NestedProto& nested_proto = test_proto.nested;
181*61c4878aSAndroid Build Coastguard Worker     StreamEncoder nested_proto =
182*61c4878aSAndroid Build Coastguard Worker         encoder.GetNestedEncoder(kTestProtoNestedField);
183*61c4878aSAndroid Build Coastguard Worker     // nested_proto.hello = "world";
184*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(nested_proto.WriteString(kNestedProtoHelloField, "world"),
185*61c4878aSAndroid Build Coastguard Worker               OkStatus());
186*61c4878aSAndroid Build Coastguard Worker 
187*61c4878aSAndroid Build Coastguard Worker     {
188*61c4878aSAndroid Build Coastguard Worker       // DoubleNestedProto& double_nested_proto = nested_proto.append_pair();
189*61c4878aSAndroid Build Coastguard Worker       StreamEncoder double_nested_proto =
190*61c4878aSAndroid Build Coastguard Worker           nested_proto.GetNestedEncoder(kNestedProtoPairField);
191*61c4878aSAndroid Build Coastguard Worker       // double_nested_proto.key = "version";
192*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(double_nested_proto.WriteString(kDoubleNestedProtoKeyField,
193*61c4878aSAndroid Build Coastguard Worker                                                 "version"),
194*61c4878aSAndroid Build Coastguard Worker                 OkStatus());
195*61c4878aSAndroid Build Coastguard Worker       // double_nested_proto.value = "2.9.1";
196*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(double_nested_proto.WriteString(kDoubleNestedProtoValueField,
197*61c4878aSAndroid Build Coastguard Worker                                                 "2.9.1"),
198*61c4878aSAndroid Build Coastguard Worker                 OkStatus());
199*61c4878aSAndroid Build Coastguard Worker     }  // end DoubleNestedProto
200*61c4878aSAndroid Build Coastguard Worker 
201*61c4878aSAndroid Build Coastguard Worker     // nested_proto.id = 999;
202*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(nested_proto.WriteUint32(kNestedProtoIdField, 999), OkStatus());
203*61c4878aSAndroid Build Coastguard Worker 
204*61c4878aSAndroid Build Coastguard Worker     {
205*61c4878aSAndroid Build Coastguard Worker       // DoubleNestedProto& double_nested_proto = nested_proto.append_pair();
206*61c4878aSAndroid Build Coastguard Worker       StreamEncoder double_nested_proto =
207*61c4878aSAndroid Build Coastguard Worker           nested_proto.GetNestedEncoder(kNestedProtoPairField);
208*61c4878aSAndroid Build Coastguard Worker       // double_nested_proto.key = "device";
209*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(
210*61c4878aSAndroid Build Coastguard Worker           double_nested_proto.WriteString(kDoubleNestedProtoKeyField, "device"),
211*61c4878aSAndroid Build Coastguard Worker           OkStatus());
212*61c4878aSAndroid Build Coastguard Worker       // double_nested_proto.value = "left-soc";
213*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(double_nested_proto.WriteString(kDoubleNestedProtoValueField,
214*61c4878aSAndroid Build Coastguard Worker                                                 "left-soc"),
215*61c4878aSAndroid Build Coastguard Worker                 OkStatus());
216*61c4878aSAndroid Build Coastguard Worker       // Rely on destructor for finalization.
217*61c4878aSAndroid Build Coastguard Worker     }  // end DoubleNestedProto
218*61c4878aSAndroid Build Coastguard Worker   }  // end NestedProto
219*61c4878aSAndroid Build Coastguard Worker 
220*61c4878aSAndroid Build Coastguard Worker   // test_proto.ziggy = -13;
221*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.WriteSint32(kTestProtoZiggyField, -13), OkStatus());
222*61c4878aSAndroid Build Coastguard Worker 
223*61c4878aSAndroid Build Coastguard Worker   // clang-format off
224*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
225*61c4878aSAndroid Build Coastguard Worker     // magic_number
226*61c4878aSAndroid Build Coastguard Worker     0x08, 0x2a,
227*61c4878aSAndroid Build Coastguard Worker     // nested header (key, size)
228*61c4878aSAndroid Build Coastguard Worker     0x32, 0x30,
229*61c4878aSAndroid Build Coastguard Worker     // nested.hello
230*61c4878aSAndroid Build Coastguard Worker     0x0a, 0x05, 'w', 'o', 'r', 'l', 'd',
231*61c4878aSAndroid Build Coastguard Worker     // nested.pair[0] header (key, size)
232*61c4878aSAndroid Build Coastguard Worker     0x1a, 0x10,
233*61c4878aSAndroid Build Coastguard Worker     // nested.pair[0].key
234*61c4878aSAndroid Build Coastguard Worker     0x0a, 0x07, 'v', 'e', 'r', 's', 'i', 'o', 'n',
235*61c4878aSAndroid Build Coastguard Worker     // nested.pair[0].value
236*61c4878aSAndroid Build Coastguard Worker     0x12, 0x05, '2', '.', '9', '.', '1',
237*61c4878aSAndroid Build Coastguard Worker     // nested.id
238*61c4878aSAndroid Build Coastguard Worker     0x10, 0xe7, 0x07,
239*61c4878aSAndroid Build Coastguard Worker     // nested.pair[1] header (key, size)
240*61c4878aSAndroid Build Coastguard Worker     0x1a, 0x12,
241*61c4878aSAndroid Build Coastguard Worker     // nested.pair[1].key
242*61c4878aSAndroid Build Coastguard Worker     0x0a, 0x06, 'd', 'e', 'v', 'i', 'c', 'e',
243*61c4878aSAndroid Build Coastguard Worker     // nested.pair[1].value
244*61c4878aSAndroid Build Coastguard Worker     0x12, 0x08, 'l', 'e', 'f', 't', '-', 's', 'o', 'c',
245*61c4878aSAndroid Build Coastguard Worker     // ziggy
246*61c4878aSAndroid Build Coastguard Worker     0x10, 0x19
247*61c4878aSAndroid Build Coastguard Worker   };
248*61c4878aSAndroid Build Coastguard Worker   // clang-format on
249*61c4878aSAndroid Build Coastguard Worker 
250*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
251*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result = ConstByteSpan(writer.data(), writer.bytes_written());
252*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
253*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
254*61c4878aSAndroid Build Coastguard Worker             0);
255*61c4878aSAndroid Build Coastguard Worker }
256*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,RepeatedField)257*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, RepeatedField) {
258*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
259*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
260*61c4878aSAndroid Build Coastguard Worker 
261*61c4878aSAndroid Build Coastguard Worker   // repeated uint32 values = 1;
262*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t values[] = {0, 50, 100, 150, 200};
263*61c4878aSAndroid Build Coastguard Worker   for (int i = 0; i < 5; ++i) {
264*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(OkStatus(), encoder.WriteUint32(1, values[i]));
265*61c4878aSAndroid Build Coastguard Worker   }
266*61c4878aSAndroid Build Coastguard Worker 
267*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
268*61c4878aSAndroid Build Coastguard Worker       0x08, 0x00, 0x08, 0x32, 0x08, 0x64, 0x08, 0x96, 0x01, 0x08, 0xc8, 0x01};
269*61c4878aSAndroid Build Coastguard Worker 
270*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
271*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
272*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
273*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
274*61c4878aSAndroid Build Coastguard Worker             0);
275*61c4878aSAndroid Build Coastguard Worker }
276*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedVarint)277*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedVarint) {
278*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
279*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
280*61c4878aSAndroid Build Coastguard Worker 
281*61c4878aSAndroid Build Coastguard Worker   // repeated uint32 values = 1;
282*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t values[] = {0, 50, 100, 150, 200};
283*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WritePackedUint32(1, values));
284*61c4878aSAndroid Build Coastguard Worker 
285*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
286*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x07, 0x00, 0x32, 0x64, 0x96, 0x01, 0xc8, 0x01};
287*61c4878aSAndroid Build Coastguard Worker   //  key   size  v[0]  v[1]  v[2]  v[3]        v[4]
288*61c4878aSAndroid Build Coastguard Worker 
289*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
290*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
291*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
292*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
293*61c4878aSAndroid Build Coastguard Worker             0);
294*61c4878aSAndroid Build Coastguard Worker }
295*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedVarintInsufficientSpace)296*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedVarintInsufficientSpace) {
297*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[8];
298*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
299*61c4878aSAndroid Build Coastguard Worker 
300*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t values[] = {0, 50, 100, 150, 200};
301*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(Status::ResourceExhausted(), encoder.WritePackedUint32(1, values));
302*61c4878aSAndroid Build Coastguard Worker 
303*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.status(), Status::ResourceExhausted());
304*61c4878aSAndroid Build Coastguard Worker }
305*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedVarintVector)306*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedVarintVector) {
307*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
308*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
309*61c4878aSAndroid Build Coastguard Worker 
310*61c4878aSAndroid Build Coastguard Worker   // repeated uint32 values = 1;
311*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<uint32_t, 5> values = {0, 50, 100, 150, 200};
312*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedUint32(1, values));
313*61c4878aSAndroid Build Coastguard Worker 
314*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
315*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x07, 0x00, 0x32, 0x64, 0x96, 0x01, 0xc8, 0x01};
316*61c4878aSAndroid Build Coastguard Worker   //  key   size  v[0]  v[1]  v[2]  v[3]        v[4]
317*61c4878aSAndroid Build Coastguard Worker 
318*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
319*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
320*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
321*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
322*61c4878aSAndroid Build Coastguard Worker             0);
323*61c4878aSAndroid Build Coastguard Worker }
324*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedVarintVectorInsufficientSpace)325*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedVarintVectorInsufficientSpace) {
326*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[8];
327*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
328*61c4878aSAndroid Build Coastguard Worker 
329*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<uint32_t, 5> values = {0, 50, 100, 150, 200};
330*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(Status::ResourceExhausted(),
331*61c4878aSAndroid Build Coastguard Worker             encoder.WriteRepeatedUint32(1, values));
332*61c4878aSAndroid Build Coastguard Worker 
333*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(encoder.status(), Status::ResourceExhausted());
334*61c4878aSAndroid Build Coastguard Worker }
335*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedBool)336*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedBool) {
337*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
338*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
339*61c4878aSAndroid Build Coastguard Worker 
340*61c4878aSAndroid Build Coastguard Worker   // repeated bool values = 1;
341*61c4878aSAndroid Build Coastguard Worker   constexpr bool values[] = {true, false, true, true, false};
342*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WritePackedBool(1, values));
343*61c4878aSAndroid Build Coastguard Worker 
344*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
345*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x05, 0x01, 0x00, 0x01, 0x01, 0x00};
346*61c4878aSAndroid Build Coastguard Worker   //  key   size  v[0]  v[1]  v[2]  v[3]  v[4]
347*61c4878aSAndroid Build Coastguard Worker 
348*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
349*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
350*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
351*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
352*61c4878aSAndroid Build Coastguard Worker             0);
353*61c4878aSAndroid Build Coastguard Worker }
354*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedFixed)355*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedFixed) {
356*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
357*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
358*61c4878aSAndroid Build Coastguard Worker 
359*61c4878aSAndroid Build Coastguard Worker   // repeated fixed32 values = 1;
360*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t values[] = {0, 50, 100, 150, 200};
361*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WritePackedFixed32(1, values));
362*61c4878aSAndroid Build Coastguard Worker 
363*61c4878aSAndroid Build Coastguard Worker   // repeated fixed64 values64 = 2;
364*61c4878aSAndroid Build Coastguard Worker   constexpr uint64_t values64[] = {0x0102030405060708};
365*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WritePackedFixed64(2, values64));
366*61c4878aSAndroid Build Coastguard Worker 
367*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
368*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x64,
369*61c4878aSAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
370*61c4878aSAndroid Build Coastguard Worker       0x12, 0x08, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
371*61c4878aSAndroid Build Coastguard Worker 
372*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
373*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
374*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
375*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
376*61c4878aSAndroid Build Coastguard Worker             0);
377*61c4878aSAndroid Build Coastguard Worker }
378*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedFixedVector)379*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedFixedVector) {
380*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
381*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
382*61c4878aSAndroid Build Coastguard Worker 
383*61c4878aSAndroid Build Coastguard Worker   // repeated fixed32 values = 1;
384*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<uint32_t, 5> values = {0, 50, 100, 150, 200};
385*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedFixed32(1, values));
386*61c4878aSAndroid Build Coastguard Worker 
387*61c4878aSAndroid Build Coastguard Worker   // repeated fixed64 values64 = 2;
388*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<uint64_t, 1> values64 = {0x0102030405060708};
389*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedFixed64(2, values64));
390*61c4878aSAndroid Build Coastguard Worker 
391*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
392*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x64,
393*61c4878aSAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
394*61c4878aSAndroid Build Coastguard Worker       0x12, 0x08, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
395*61c4878aSAndroid Build Coastguard Worker 
396*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
397*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
398*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
399*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
400*61c4878aSAndroid Build Coastguard Worker             0);
401*61c4878aSAndroid Build Coastguard Worker }
402*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedSfixedVector)403*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedSfixedVector) {
404*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
405*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
406*61c4878aSAndroid Build Coastguard Worker 
407*61c4878aSAndroid Build Coastguard Worker   // repeated fixed32 values = 1;
408*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<int32_t, 5> values = {0, 50, 100, 150, 200};
409*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedSfixed32(1, values));
410*61c4878aSAndroid Build Coastguard Worker 
411*61c4878aSAndroid Build Coastguard Worker   // repeated fixed64 values64 = 2;
412*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<int64_t, 1> values64 = {-2};
413*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedSfixed64(2, values64));
414*61c4878aSAndroid Build Coastguard Worker 
415*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
416*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x64,
417*61c4878aSAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
418*61c4878aSAndroid Build Coastguard Worker       0x12, 0x08, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
419*61c4878aSAndroid Build Coastguard Worker 
420*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
421*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
422*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
423*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
424*61c4878aSAndroid Build Coastguard Worker             0);
425*61c4878aSAndroid Build Coastguard Worker }
426*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedZigzag)427*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedZigzag) {
428*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
429*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
430*61c4878aSAndroid Build Coastguard Worker 
431*61c4878aSAndroid Build Coastguard Worker   // repeated sint32 values = 1;
432*61c4878aSAndroid Build Coastguard Worker   constexpr int32_t values[] = {-100, -25, -1, 0, 1, 25, 100};
433*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WritePackedSint32(1, values));
434*61c4878aSAndroid Build Coastguard Worker 
435*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
436*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x09, 0xc7, 0x01, 0x31, 0x01, 0x00, 0x02, 0x32, 0xc8, 0x01};
437*61c4878aSAndroid Build Coastguard Worker 
438*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
439*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
440*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
441*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
442*61c4878aSAndroid Build Coastguard Worker             0);
443*61c4878aSAndroid Build Coastguard Worker }
444*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,PackedZigzagVector)445*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, PackedZigzagVector) {
446*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
447*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
448*61c4878aSAndroid Build Coastguard Worker 
449*61c4878aSAndroid Build Coastguard Worker   // repeated sint32 values = 1;
450*61c4878aSAndroid Build Coastguard Worker   const pw::Vector<int32_t, 7> values = {-100, -25, -1, 0, 1, 25, 100};
451*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), encoder.WriteRepeatedSint32(1, values));
452*61c4878aSAndroid Build Coastguard Worker 
453*61c4878aSAndroid Build Coastguard Worker   constexpr uint8_t encoded_proto[] = {
454*61c4878aSAndroid Build Coastguard Worker       0x0a, 0x09, 0xc7, 0x01, 0x31, 0x01, 0x00, 0x02, 0x32, 0xc8, 0x01};
455*61c4878aSAndroid Build Coastguard Worker 
456*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.status(), OkStatus());
457*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan result(encoder);
458*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), sizeof(encoded_proto));
459*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)),
460*61c4878aSAndroid Build Coastguard Worker             0);
461*61c4878aSAndroid Build Coastguard Worker }
462*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,ParentUnavailable)463*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, ParentUnavailable) {
464*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
465*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent(encode_buffer);
466*61c4878aSAndroid Build Coastguard Worker   {
467*61c4878aSAndroid Build Coastguard Worker     StreamEncoder child = parent.GetNestedEncoder(kTestProtoNestedField);
468*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(child.status(), OkStatus());
469*61c4878aSAndroid Build Coastguard Worker   }
470*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.status(), OkStatus());
471*61c4878aSAndroid Build Coastguard Worker }
472*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,NestedEncoderRequiresBuffer)473*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, NestedEncoderRequiresBuffer) {
474*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent((ByteSpan()));
475*61c4878aSAndroid Build Coastguard Worker   {
476*61c4878aSAndroid Build Coastguard Worker     StreamEncoder child = parent.GetNestedEncoder(kTestProtoNestedField);
477*61c4878aSAndroid Build Coastguard Worker 
478*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(child.status(), Status::ResourceExhausted());
479*61c4878aSAndroid Build Coastguard Worker   }
480*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.status(), Status::ResourceExhausted());
481*61c4878aSAndroid Build Coastguard Worker }
482*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,WriteTooBig)483*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, WriteTooBig) {
484*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kTempBufferSize = 32;
485*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kWriteSize = 2;
486*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
487*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder encoder(encode_buffer);
488*61c4878aSAndroid Build Coastguard Worker   // Each write is 2 bytes. Ensure we can write 16 times.
489*61c4878aSAndroid Build Coastguard Worker   for (size_t i = 0; i < kTempBufferSize; i += kWriteSize) {
490*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(encoder.WriteUint32(1, 12), OkStatus());
491*61c4878aSAndroid Build Coastguard Worker   }
492*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.size(), kTempBufferSize);
493*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(encoder.WriteUint32(1, 12), Status::ResourceExhausted());
494*61c4878aSAndroid Build Coastguard Worker }
495*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,EmptyChildWrites)496*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, EmptyChildWrites) {
497*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
498*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent(encode_buffer);
499*61c4878aSAndroid Build Coastguard Worker   {
500*61c4878aSAndroid Build Coastguard Worker     StreamEncoder child = parent.GetNestedEncoder(kTestProtoNestedField);
501*61c4878aSAndroid Build Coastguard Worker   }
502*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.status(), OkStatus());
503*61c4878aSAndroid Build Coastguard Worker   const size_t kExpectedSize =
504*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(
505*61c4878aSAndroid Build Coastguard Worker           FieldKey(kTestProtoNestedField, WireType::kDelimited)) +
506*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(0);
507*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.size(), kExpectedSize);
508*61c4878aSAndroid Build Coastguard Worker }
509*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,InvalidChildFieldNumber)510*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, InvalidChildFieldNumber) {
511*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
512*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent(encode_buffer);
513*61c4878aSAndroid Build Coastguard Worker   {
514*61c4878aSAndroid Build Coastguard Worker     StreamEncoder child = parent.GetNestedEncoder(0);
515*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(child.status(), Status::InvalidArgument());
516*61c4878aSAndroid Build Coastguard Worker   }
517*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(parent.status(), Status::InvalidArgument());
518*61c4878aSAndroid Build Coastguard Worker }
519*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,NestedStatusPropagates)520*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, NestedStatusPropagates) {
521*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
522*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent(encode_buffer);
523*61c4878aSAndroid Build Coastguard Worker   {
524*61c4878aSAndroid Build Coastguard Worker     StreamEncoder child = parent.GetNestedEncoder(kTestProtoNestedField);
525*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(child.WriteUint32(0, 0), Status::InvalidArgument());
526*61c4878aSAndroid Build Coastguard Worker   }
527*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.status(), Status::InvalidArgument());
528*61c4878aSAndroid Build Coastguard Worker }
529*61c4878aSAndroid Build Coastguard Worker 
TEST(StreamEncoder,ManualCloseEncoderWrites)530*61c4878aSAndroid Build Coastguard Worker TEST(StreamEncoder, ManualCloseEncoderWrites) {
531*61c4878aSAndroid Build Coastguard Worker   std::byte encode_buffer[32];
532*61c4878aSAndroid Build Coastguard Worker   MemoryEncoder parent(encode_buffer);
533*61c4878aSAndroid Build Coastguard Worker   StreamEncoder child = parent.GetNestedEncoder(kTestProtoNestedField);
534*61c4878aSAndroid Build Coastguard Worker   child.CloseEncoder();
535*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.status(), OkStatus());
536*61c4878aSAndroid Build Coastguard Worker   const size_t kExpectedSize =
537*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(
538*61c4878aSAndroid Build Coastguard Worker           FieldKey(kTestProtoNestedField, WireType::kDelimited)) +
539*61c4878aSAndroid Build Coastguard Worker       varint::EncodedSize(0);
540*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(parent.size(), kExpectedSize);
541*61c4878aSAndroid Build Coastguard Worker }
542*61c4878aSAndroid Build Coastguard Worker 
543*61c4878aSAndroid Build Coastguard Worker }  // namespace
544*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::protobuf
545