• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #include "gtest/gtest.h"
15 #include "pw_protobuf/encoder.h"
16 #include "pw_span/span.h"
17 #include "pw_stream/memory_stream.h"
18 
19 // These header files contain the code generated by the pw_protobuf plugin.
20 // They are re-generated every time the tests are built and are used by the
21 // tests to ensure that the interface remains consistent.
22 //
23 // The purpose of the tests in this file is primarily to verify that the
24 // generated C++ interface is valid rather than the correctness of the
25 // low-level encoder.
26 #include "pw_protobuf_test_protos/full_test.pwpb.h"
27 #include "pw_protobuf_test_protos/importer.pwpb.h"
28 #include "pw_protobuf_test_protos/non_pw_package.pwpb.h"
29 #include "pw_protobuf_test_protos/proto2.pwpb.h"
30 #include "pw_protobuf_test_protos/repeated.pwpb.h"
31 
32 namespace pw::protobuf {
33 namespace {
34 
35 using test::pwpb::Bool;
36 using test::pwpb::Enum;
37 
38 namespace Bar = test::pwpb::Bar;
39 namespace BaseMessage = test::pwpb::BaseMessage;
40 namespace Crate = test::pwpb::Crate;
41 namespace DeviceInfo = test::pwpb::DeviceInfo;
42 namespace Foo = test::pwpb::Foo;
43 namespace IntegerMetadata = test::pwpb::IntegerMetadata;
44 namespace KeyValuePair = test::pwpb::KeyValuePair;
45 namespace Overlay = test::pwpb::Overlay;
46 namespace Period = test::pwpb::Period;
47 namespace Pigweed = test::pwpb::Pigweed;
48 namespace Proto = test::pwpb::Proto;
49 namespace RepeatedTest = test::pwpb::RepeatedTest;
50 
51 namespace imported {
52 namespace Timestamp = ::pw::protobuf::test::imported::pwpb::Timestamp;
53 }  // namespace imported
54 
TEST(Codegen,Codegen)55 TEST(Codegen, Codegen) {
56   std::byte encode_buffer[Pigweed::kMaxEncodedSizeBytes +
57                           DeviceInfo::kMaxEncodedSizeBytes];
58   std::byte temp_buffer[Pigweed::kScratchBufferSizeBytes +
59                         DeviceInfo::kMaxEncodedSizeBytes];
60   stream::MemoryWriter writer(encode_buffer);
61 
62   Pigweed::StreamEncoder pigweed(writer, temp_buffer);
63   ASSERT_EQ(OkStatus(), pigweed.WriteMagicNumber(73));
64   ASSERT_EQ(OkStatus(), pigweed.WriteZiggy(-111));
65   ASSERT_EQ(OkStatus(), pigweed.WriteErrorMessage("not a typewriter"));
66   ASSERT_EQ(OkStatus(), pigweed.WriteBin(Pigweed::Protobuf::Binary::ZERO));
67 
68   {
69     Pigweed::Pigweed::StreamEncoder pigweed_pigweed =
70         pigweed.GetPigweedEncoder();
71     ASSERT_EQ(OkStatus(), pigweed_pigweed.WriteStatus(Bool::FILE_NOT_FOUND));
72 
73     ASSERT_EQ(pigweed_pigweed.status(), OkStatus());
74   }
75 
76   {
77     Proto::StreamEncoder proto = pigweed.GetProtoEncoder();
78     ASSERT_EQ(OkStatus(), proto.WriteBin(Proto::Binary::OFF));
79     ASSERT_EQ(OkStatus(),
80               proto.WritePigweedPigweedBin(Pigweed::Pigweed::Binary::ZERO));
81     ASSERT_EQ(OkStatus(),
82               proto.WritePigweedProtobufBin(Pigweed::Protobuf::Binary::ZERO));
83 
84     {
85       Pigweed::Protobuf::Compiler::StreamEncoder meta = proto.GetMetaEncoder();
86       ASSERT_EQ(OkStatus(), meta.WriteFileName("/etc/passwd"));
87       ASSERT_EQ(OkStatus(),
88                 meta.WriteStatus(Pigweed::Protobuf::Compiler::Status::FUBAR));
89     }
90 
91     {
92       Pigweed::StreamEncoder nested_pigweed = proto.GetPigweedEncoder();
93       ASSERT_EQ(OkStatus(),
94                 nested_pigweed.WriteErrorMessage("here we go again"));
95       ASSERT_EQ(OkStatus(), nested_pigweed.WriteMagicNumber(616));
96 
97       {
98         DeviceInfo::StreamEncoder device_info =
99             nested_pigweed.GetDeviceInfoEncoder();
100 
101         {
102           KeyValuePair::StreamEncoder attributes =
103               device_info.GetAttributesEncoder();
104           ASSERT_EQ(OkStatus(), attributes.WriteKey("version"));
105           ASSERT_EQ(OkStatus(), attributes.WriteValue("5.3.1"));
106         }
107 
108         {
109           KeyValuePair::StreamEncoder attributes =
110               device_info.GetAttributesEncoder();
111           ASSERT_EQ(OkStatus(), attributes.WriteKey("chip"));
112           ASSERT_EQ(OkStatus(), attributes.WriteValue("left-soc"));
113         }
114 
115         ASSERT_EQ(OkStatus(),
116                   device_info.WriteStatus(DeviceInfo::DeviceStatus::PANIC));
117       }
118     }
119   }
120 
121   for (int i = 0; i < 5; ++i) {
122     Proto::ID::StreamEncoder id = pigweed.GetIdEncoder();
123     ASSERT_EQ(OkStatus(), id.WriteId(5 * i * i + 3 * i + 49));
124   }
125 
126   // clang-format off
127   constexpr uint8_t expected_proto[] = {
128     // pigweed.magic_number
129     0x08, 0x49,
130     // pigweed.ziggy
131     0x10, 0xdd, 0x01,
132     // pigweed.error_message
133     0x2a, 0x10, 'n', 'o', 't', ' ', 'a', ' ',
134     't', 'y', 'p', 'e', 'w', 'r', 'i', 't', 'e', 'r',
135     // pigweed.bin
136     0x40, 0x01,
137     // pigweed.pigweed
138     0x3a, 0x02,
139     // pigweed.pigweed.status
140     0x08, 0x02,
141     // pigweed.proto
142     0x4a, 0x56,
143     // pigweed.proto.bin
144     0x10, 0x00,
145     // pigweed.proto.pigweed_pigweed_bin
146     0x18, 0x00,
147     // pigweed.proto.pigweed_protobuf_bin
148     0x20, 0x01,
149     // pigweed.proto.meta
150     0x2a, 0x0f,
151     // pigweed.proto.meta.file_name
152     0x0a, 0x0b, '/', 'e', 't', 'c', '/', 'p', 'a', 's', 's', 'w', 'd',
153     // pigweed.proto.meta.status
154     0x10, 0x02,
155     // pigweed.proto.nested_pigweed
156     0x0a, 0x3d,
157     // pigweed.proto.nested_pigweed.error_message
158     0x2a, 0x10, 'h', 'e', 'r', 'e', ' ', 'w', 'e', ' ',
159     'g', 'o', ' ', 'a', 'g', 'a', 'i', 'n',
160     // pigweed.proto.nested_pigweed.magic_number
161     0x08, 0xe8, 0x04,
162     // pigweed.proto.nested_pigweed.device_info
163     0x32, 0x26,
164     // pigweed.proto.nested_pigweed.device_info.attributes[0]
165     0x22, 0x10,
166     // pigweed.proto.nested_pigweed.device_info.attributes[0].key
167     0x0a, 0x07, 'v', 'e', 'r', 's', 'i', 'o', 'n',
168     // pigweed.proto.nested_pigweed.device_info.attributes[0].value
169     0x12, 0x05, '5', '.', '3', '.', '1',
170     // pigweed.proto.nested_pigweed.device_info.attributes[1]
171     0x22, 0x10,
172     // pigweed.proto.nested_pigweed.device_info.attributes[1].key
173     0x0a, 0x04, 'c', 'h', 'i', 'p',
174     // pigweed.proto.nested_pigweed.device_info.attributes[1].value
175     0x12, 0x08, 'l', 'e', 'f', 't', '-', 's', 'o', 'c',
176     // pigweed.proto.nested_pigweed.device_info.status
177     0x18, 0x03,
178     // pigweed.id[0]
179     0x52, 0x02,
180     // pigweed.id[0].id
181     0x08, 0x31,
182     // pigweed.id[1]
183     0x52, 0x02,
184     // pigweed.id[1].id
185     0x08, 0x39,
186     // pigweed.id[2]
187     0x52, 0x02,
188     // pigweed.id[2].id
189     0x08, 0x4b,
190     // pigweed.id[3]
191     0x52, 0x02,
192     // pigweed.id[3].id
193     0x08, 0x67,
194     // pigweed.id[4]
195     0x52, 0x03,
196     // pigweed.id[4].id
197     0x08, 0x8d, 0x01
198   };
199   // clang-format on
200 
201   ConstByteSpan result = writer.WrittenData();
202   ASSERT_EQ(pigweed.status(), OkStatus());
203   EXPECT_EQ(result.size(), sizeof(expected_proto));
204   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
205             0);
206 }
207 
TEST(Codegen,RecursiveSubmessage)208 TEST(Codegen, RecursiveSubmessage) {
209   // 12 here represents the longest name. Note that all field structure is taken
210   // care of, we just have to multiply by how many crates we're encoding, ie. 4.
211   std::byte encode_buffer[(Crate::kMaxEncodedSizeBytes + 12) * 4];
212 
213   Crate::MemoryEncoder biggest_crate(encode_buffer);
214   ASSERT_EQ(OkStatus(), biggest_crate.WriteName("Huge crate"));
215 
216   {
217     Crate::StreamEncoder medium_crate = biggest_crate.GetSmallerCratesEncoder();
218     ASSERT_EQ(OkStatus(), medium_crate.WriteName("Medium crate"));
219     {
220       Crate::StreamEncoder small_crate = medium_crate.GetSmallerCratesEncoder();
221       ASSERT_EQ(OkStatus(), small_crate.WriteName("Small crate"));
222     }
223     {
224       Crate::StreamEncoder tiny_crate = medium_crate.GetSmallerCratesEncoder();
225       ASSERT_EQ(OkStatus(), tiny_crate.WriteName("Tiny crate"));
226     }
227   }
228 
229   // clang-format off
230   constexpr uint8_t expected_proto[] = {
231     // crate.name
232     0x0a, 0x0a, 'H', 'u', 'g', 'e', ' ', 'c', 'r', 'a', 't', 'e',
233     // crate.smaller_crate[0]
234     0x12, 0x2b,
235     // crate.smaller_crate[0].name
236     0x0a, 0x0c, 'M', 'e', 'd', 'i', 'u', 'm', ' ', 'c', 'r', 'a', 't', 'e',
237     // crate.smaller_crate[0].smaller_crate[0]
238     0x12, 0x0d,
239     // crate.smaller_crate[0].smaller_crate[0].name
240     0x0a, 0x0b, 'S', 'm', 'a', 'l', 'l', ' ', 'c', 'r', 'a', 't', 'e',
241     // crate.smaller_crate[0].smaller_crate[1]
242     0x12, 0x0c,
243     // crate.smaller_crate[0].smaller_crate[1].name
244     0x0a, 0x0a, 'T', 'i', 'n', 'y', ' ', 'c', 'r', 'a', 't', 'e',
245   };
246   // clang-format on
247 
248   ConstByteSpan result(biggest_crate);
249   ASSERT_EQ(biggest_crate.status(), OkStatus());
250   EXPECT_EQ(result.size(), sizeof(expected_proto));
251   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
252             0);
253 }
254 
TEST(CodegenRepeated,NonPackedScalar)255 TEST(CodegenRepeated, NonPackedScalar) {
256   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
257 
258   stream::MemoryWriter writer(encode_buffer);
259   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
260   for (int i = 0; i < 4; ++i) {
261     ASSERT_EQ(OkStatus(), repeated_test.WriteUint32s(i * 16));
262   }
263 
264   for (int i = 0; i < 4; ++i) {
265     ASSERT_EQ(OkStatus(), repeated_test.WriteFixed32s(i * 16));
266   }
267 
268   // clang-format off
269   constexpr uint8_t expected_proto[] = {
270     // uint32s[], v={0, 16, 32, 48}
271     0x08, 0x00,
272     0x08, 0x10,
273     0x08, 0x20,
274     0x08, 0x30,
275     // fixed32s[]. v={0, 16, 32, 48}
276     0x35, 0x00, 0x00, 0x00, 0x00,
277     0x35, 0x10, 0x00, 0x00, 0x00,
278     0x35, 0x20, 0x00, 0x00, 0x00,
279     0x35, 0x30, 0x00, 0x00, 0x00,
280   };
281   // clang-format on
282 
283   ConstByteSpan result = writer.WrittenData();
284   ASSERT_EQ(repeated_test.status(), OkStatus());
285   EXPECT_EQ(result.size(), sizeof(expected_proto));
286   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
287             0);
288 }
289 
TEST(CodegenRepeated,PackedScalar)290 TEST(CodegenRepeated, PackedScalar) {
291   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
292 
293   stream::MemoryWriter writer(encode_buffer);
294   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
295   constexpr uint32_t values[] = {0, 16, 32, 48};
296   ASSERT_EQ(OkStatus(), repeated_test.WriteUint32s(values));
297   ASSERT_EQ(OkStatus(), repeated_test.WriteFixed32s(values));
298 
299   // clang-format off
300   constexpr uint8_t expected_proto[] = {
301     // uint32s[], v={0, 16, 32, 48}
302     0x0a, 0x04,
303     0x00,
304     0x10,
305     0x20,
306     0x30,
307     // fixed32s[]. v={0, 16, 32, 48}
308     0x32, 0x10,
309     0x00, 0x00, 0x00, 0x00,
310     0x10, 0x00, 0x00, 0x00,
311     0x20, 0x00, 0x00, 0x00,
312     0x30, 0x00, 0x00, 0x00,
313   };
314   // clang-format on
315 
316   ConstByteSpan result = writer.WrittenData();
317   ASSERT_EQ(repeated_test.status(), OkStatus());
318   EXPECT_EQ(result.size(), sizeof(expected_proto));
319   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
320             0);
321 }
322 
TEST(CodegenRepeated,PackedBool)323 TEST(CodegenRepeated, PackedBool) {
324   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
325 
326   stream::MemoryWriter writer(encode_buffer);
327   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
328   constexpr bool values[] = {true, false, true, true, false};
329   ASSERT_EQ(OkStatus(), repeated_test.WriteBools(span(values)));
330 
331   // clang-format off
332   constexpr uint8_t expected_proto[] = {
333     // bools[], v={true, false, true, true, false}
334     0x3a, 0x05, 0x01, 0x00, 0x01, 0x01, 0x00,
335   };
336   // clang-format on
337 
338   ConstByteSpan result = writer.WrittenData();
339   ASSERT_EQ(repeated_test.status(), OkStatus());
340   EXPECT_EQ(result.size(), sizeof(expected_proto));
341   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
342             0);
343 }
344 
TEST(CodegenRepeated,PackedScalarVector)345 TEST(CodegenRepeated, PackedScalarVector) {
346   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
347 
348   stream::MemoryWriter writer(encode_buffer);
349   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
350   const pw::Vector<uint32_t, 4> values = {0, 16, 32, 48};
351   ASSERT_EQ(OkStatus(), repeated_test.WriteUint32s(values));
352   ASSERT_EQ(OkStatus(), repeated_test.WriteFixed32s(values));
353 
354   // clang-format off
355   constexpr uint8_t expected_proto[] = {
356     // uint32s[], v={0, 16, 32, 48}
357     0x0a, 0x04,
358     0x00,
359     0x10,
360     0x20,
361     0x30,
362     // fixed32s[]. v={0, 16, 32, 48}
363     0x32, 0x10,
364     0x00, 0x00, 0x00, 0x00,
365     0x10, 0x00, 0x00, 0x00,
366     0x20, 0x00, 0x00, 0x00,
367     0x30, 0x00, 0x00, 0x00,
368   };
369   // clang-format on
370 
371   ConstByteSpan result = writer.WrittenData();
372   ASSERT_EQ(repeated_test.status(), OkStatus());
373   EXPECT_EQ(result.size(), sizeof(expected_proto));
374   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
375             0);
376 }
377 
TEST(CodegenRepeated,PackedEnum)378 TEST(CodegenRepeated, PackedEnum) {
379   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
380 
381   stream::MemoryWriter writer(encode_buffer);
382   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
383   constexpr Enum values[] = {Enum::RED, Enum::GREEN, Enum::AMBER, Enum::RED};
384   ASSERT_EQ(repeated_test.WriteEnums(span(values)), OkStatus());
385 
386   // clang-format off
387   constexpr uint8_t expected_proto[] = {
388     // enums[], v={RED, GREEN, AMBER, RED}
389     0x4a, 0x04, 0x00, 0x02, 0x01, 0x00
390   };
391   // clang-format on
392 
393   ConstByteSpan result = writer.WrittenData();
394   ASSERT_EQ(repeated_test.status(), OkStatus());
395   EXPECT_EQ(result.size(), sizeof(expected_proto));
396   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
397             0);
398 }
399 
TEST(CodegenRepeated,PackedEnumVector)400 TEST(CodegenRepeated, PackedEnumVector) {
401   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
402 
403   stream::MemoryWriter writer(encode_buffer);
404   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
405   const pw::Vector<Enum, 4> values = {
406       Enum::RED, Enum::GREEN, Enum::AMBER, Enum::RED};
407   ASSERT_EQ(repeated_test.WriteEnums(values), OkStatus());
408 
409   // clang-format off
410   constexpr uint8_t expected_proto[] = {
411     // enums[], v={RED, GREEN, AMBER, RED}
412     0x4a, 0x04, 0x00, 0x02, 0x01, 0x00
413   };
414   // clang-format on
415 
416   ConstByteSpan result = writer.WrittenData();
417   ASSERT_EQ(repeated_test.status(), OkStatus());
418   EXPECT_EQ(result.size(), sizeof(expected_proto));
419   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
420             0);
421 }
422 
TEST(CodegenRepeated,NonScalar)423 TEST(CodegenRepeated, NonScalar) {
424   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
425 
426   stream::MemoryWriter writer(encode_buffer);
427   RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan());
428   constexpr const char* strings[] = {"the", "quick", "brown", "fox"};
429   for (const char* s : strings) {
430     ASSERT_EQ(OkStatus(), repeated_test.WriteStrings(s));
431   }
432 
433   constexpr uint8_t expected_proto[] = {
434       0x1a, 0x03, 't', 'h', 'e', 0x1a, 0x5, 'q',  'u', 'i', 'c', 'k',
435       0x1a, 0x5,  'b', 'r', 'o', 'w',  'n', 0x1a, 0x3, 'f', 'o', 'x'};
436   ConstByteSpan result = writer.WrittenData();
437   ASSERT_EQ(repeated_test.status(), OkStatus());
438   EXPECT_EQ(result.size(), sizeof(expected_proto));
439   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
440             0);
441 }
442 
TEST(CodegenRepeated,Message)443 TEST(CodegenRepeated, Message) {
444   std::byte encode_buffer[RepeatedTest::kMaxEncodedSizeBytes];
445 
446   RepeatedTest::MemoryEncoder repeated_test(encode_buffer);
447   for (int i = 0; i < 3; ++i) {
448     auto structs = repeated_test.GetStructsEncoder();
449     ASSERT_EQ(OkStatus(), structs.WriteOne(i * 1));
450     ASSERT_EQ(OkStatus(), structs.WriteTwo(i * 2));
451   }
452 
453   // clang-format off
454   constexpr uint8_t expected_proto[] = {
455     0x2a, 0x04, 0x08, 0x00, 0x10, 0x00, 0x2a, 0x04, 0x08,
456     0x01, 0x10, 0x02, 0x2a, 0x04, 0x08, 0x02, 0x10, 0x04};
457   // clang-format on
458 
459   ConstByteSpan result(repeated_test);
460   ASSERT_EQ(repeated_test.status(), OkStatus());
461   EXPECT_EQ(result.size(), sizeof(expected_proto));
462   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
463             0);
464 }
465 
TEST(Codegen,Proto2)466 TEST(Codegen, Proto2) {
467   std::byte encode_buffer[Foo::kMaxEncodedSizeBytes];
468 
469   Foo::MemoryEncoder foo(encode_buffer);
470   ASSERT_EQ(OkStatus(), foo.WriteInteger(3));
471 
472   {
473     constexpr std::byte data[] = {
474         std::byte(0xde), std::byte(0xad), std::byte(0xbe), std::byte(0xef)};
475     Bar::StreamEncoder bar = foo.GetBarEncoder();
476     ASSERT_EQ(OkStatus(), bar.WriteData(data));
477   }
478 
479   constexpr uint8_t expected_proto[] = {
480       0x08, 0x03, 0x1a, 0x06, 0x0a, 0x04, 0xde, 0xad, 0xbe, 0xef};
481 
482   ConstByteSpan result(foo);
483   ASSERT_EQ(foo.status(), OkStatus());
484   EXPECT_EQ(result.size(), sizeof(expected_proto));
485   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
486             0);
487 }
488 
TEST(Codegen,Import)489 TEST(Codegen, Import) {
490   std::byte encode_buffer[Period::kMaxEncodedSizeBytes];
491 
492   Period::MemoryEncoder period(encode_buffer);
493   {
494     imported::Timestamp::StreamEncoder start = period.GetStartEncoder();
495     ASSERT_EQ(OkStatus(), start.WriteSeconds(1589501793));
496     ASSERT_EQ(OkStatus(), start.WriteNanoseconds(511613110));
497   }
498 
499   {
500     imported::Timestamp::StreamEncoder end = period.GetEndEncoder();
501     ASSERT_EQ(OkStatus(), end.WriteSeconds(1589501841));
502     ASSERT_EQ(OkStatus(), end.WriteNanoseconds(490367432));
503   }
504 
505   EXPECT_EQ(period.status(), OkStatus());
506 }
507 
TEST(Codegen,NonPigweedPackage)508 TEST(Codegen, NonPigweedPackage) {
509   namespace Packed = ::non::pigweed::package::name::pwpb::Packed;
510 
511   std::byte encode_buffer[Packed::kMaxEncodedSizeBytes];
512   std::array<const int64_t, 2> repeated = {0, 1};
513   stream::MemoryWriter writer(encode_buffer);
514   Packed::StreamEncoder packed(writer, ByteSpan());
515   ASSERT_EQ(OkStatus(), packed.WriteRep(span<const int64_t>(repeated)));
516   ASSERT_EQ(OkStatus(), packed.WritePacked("packed"));
517 
518   EXPECT_EQ(packed.status(), OkStatus());
519 }
520 
TEST(Codegen,MemoryToStreamConversion)521 TEST(Codegen, MemoryToStreamConversion) {
522   std::byte encode_buffer[IntegerMetadata::kMaxEncodedSizeBytes];
523   IntegerMetadata::MemoryEncoder metadata(encode_buffer);
524   IntegerMetadata::StreamEncoder& streamed_metadata = metadata;
525   EXPECT_EQ(streamed_metadata.WriteBits(3), OkStatus());
526 
527   constexpr uint8_t expected_proto[] = {0x08, 0x03};
528 
529   ConstByteSpan result(metadata);
530   ASSERT_EQ(metadata.status(), OkStatus());
531   EXPECT_EQ(result.size(), sizeof(expected_proto));
532   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
533             0);
534 }
535 
TEST(Codegen,OverlayConversion)536 TEST(Codegen, OverlayConversion) {
537   std::byte encode_buffer[BaseMessage::kMaxEncodedSizeBytes +
538                           Overlay::kMaxEncodedSizeBytes];
539   BaseMessage::MemoryEncoder base(encode_buffer);
540   Overlay::StreamEncoder& overlay =
541       StreamEncoderCast<Overlay::StreamEncoder>(base);
542   EXPECT_EQ(overlay.WriteHeight(15), OkStatus());
543   EXPECT_EQ(base.WriteLength(7), OkStatus());
544 
545   constexpr uint8_t expected_proto[] = {0x10, 0x0f, 0x08, 0x07};
546 
547   ConstByteSpan result(base);
548   ASSERT_EQ(base.status(), OkStatus());
549   EXPECT_EQ(result.size(), sizeof(expected_proto));
550   EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)),
551             0);
552 }
553 
TEST(Codegen,EnumToString)554 TEST(Codegen, EnumToString) {
555   EXPECT_STREQ(test::pwpb::BoolToString(test::pwpb::Bool::kTrue), "TRUE");
556   EXPECT_STREQ(test::pwpb::BoolToString(test::pwpb::Bool::kFalse), "FALSE");
557   EXPECT_STREQ(test::pwpb::BoolToString(test::pwpb::Bool::kFileNotFound),
558                "FILE_NOT_FOUND");
559   EXPECT_STREQ(test::pwpb::BoolToString(static_cast<test::pwpb::Bool>(12893)),
560                "");
561 }
562 
TEST(Codegen,NestedEnumToString)563 TEST(Codegen, NestedEnumToString) {
564   EXPECT_STREQ(test::pwpb::Pigweed::Pigweed::BinaryToString(
565                    test::pwpb::Pigweed::Pigweed::Binary::kZero),
566                "ZERO");
567   EXPECT_STREQ(test::pwpb::Pigweed::Pigweed::BinaryToString(
568                    test::pwpb::Pigweed::Pigweed::Binary::kOne),
569                "ONE");
570   EXPECT_STREQ(test::pwpb::Pigweed::Pigweed::BinaryToString(
571                    static_cast<test::pwpb::Pigweed::Pigweed::Binary>(12893)),
572                "");
573 }
574 
575 }  // namespace
576 }  // namespace pw::protobuf
577