Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_protobuf / codegen_test.cc
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 <span>
15
16 #include "gtest/gtest.h"
17 #include "pw_protobuf/encoder.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 namespace pw::protobuf::test;
36
37 TEST(Codegen, Codegen) {
38   std::byte encode_buffer[512];
39   NestedEncoder<20, 20> encoder(encode_buffer);
40
41   Pigweed::Encoder pigweed(&encoder);
42   pigweed.WriteMagicNumber(73);
43   pigweed.WriteZiggy(-111);
44   pigweed.WriteErrorMessage("not a typewriter");
45   pigweed.WriteBin(Pigweed::Protobuf::Binary::ZERO);
46
47   {
48     Pigweed::Pigweed::Encoder pigweed_pigweed = pigweed.GetPigweedEncoder();
49     pigweed_pigweed.WriteStatus(Bool::FILE_NOT_FOUND);
50   }
51
52   {
53     Proto::Encoder proto = pigweed.GetProtoEncoder();
54     proto.WriteBin(Proto::Binary::OFF);
55     proto.WritePigweedPigweedBin(Pigweed::Pigweed::Binary::ZERO);
56     proto.WritePigweedProtobufBin(Pigweed::Protobuf::Binary::ZERO);
57
58     {
59       Pigweed::Protobuf::Compiler::Encoder meta = proto.GetMetaEncoder();
60       meta.WriteFileName("/etc/passwd");
61       meta.WriteStatus(Pigweed::Protobuf::Compiler::Status::FUBAR);
62     }
63
64     {
65       Pigweed::Encoder nested_pigweed = proto.GetPigweedEncoder();
66       pigweed.WriteErrorMessage("here we go again");
67       pigweed.WriteMagicNumber(616);
68
69       {
70         DeviceInfo::Encoder device_info = nested_pigweed.GetDeviceInfoEncoder();
71
72         {
73           KeyValuePair::Encoder attributes = device_info.GetAttributesEncoder();
74           attributes.WriteKey("version");
75           attributes.WriteValue("5.3.1");
76         }
77
78         {
79           KeyValuePair::Encoder attributes = device_info.GetAttributesEncoder();
80           attributes.WriteKey("chip");
81           attributes.WriteValue("left-soc");
82         }
83
84         device_info.WriteStatus(DeviceInfo::DeviceStatus::PANIC);
85       }
86     }
87   }
88
89   for (int i = 0; i < 5; ++i) {
90     Proto::ID::Encoder id = pigweed.GetIdEncoder();
91     id.WriteId(5 * i * i + 3 * i + 49);
92   }
93
94   // clang-format off
95   constexpr uint8_t expected_proto[] = {
96     // pigweed.magic_number
97     0x08, 0x49,
98     // pigweed.ziggy
99     0x10, 0xdd, 0x01,
100     // pigweed.error_message
101     0x2a, 0x10, 'n', 'o', 't', ' ', 'a', ' ',
102     't', 'y', 'p', 'e', 'w', 'r', 'i', 't', 'e', 'r',
103     // pigweed.bin
104     0x40, 0x01,
105     // pigweed.pigweed
106     0x3a, 0x02,
107     // pigweed.pigweed.status
108     0x08, 0x02,
109     // pigweed.proto
110     0x4a, 0x56,
111     // pigweed.proto.bin
112     0x10, 0x00,
113     // pigweed.proto.pigweed_pigweed_bin
114     0x18, 0x00,
115     // pigweed.proto.pigweed_protobuf_bin
116     0x20, 0x01,
117     // pigweed.proto.meta
118     0x2a, 0x0f,
119     // pigweed.proto.meta.file_name
120     0x0a, 0x0b, '/', 'e', 't', 'c', '/', 'p', 'a', 's', 's', 'w', 'd',
121     // pigweed.proto.meta.status
122     0x10, 0x02,
123     // pigweed.proto.nested_pigweed
124     0x0a, 0x3d,
125     // pigweed.proto.nested_pigweed.error_message
126     0x2a, 0x10, 'h', 'e', 'r', 'e', ' ', 'w', 'e', ' ',
127     'g', 'o', ' ', 'a', 'g', 'a', 'i', 'n',
128     // pigweed.proto.nested_pigweed.magic_number
129     0x08, 0xe8, 0x04,
130     // pigweed.proto.nested_pigweed.device_info
131     0x32, 0x26,
132     // pigweed.proto.nested_pigweed.device_info.attributes[0]
133     0x22, 0x10,
134     // pigweed.proto.nested_pigweed.device_info.attributes[0].key
135     0x0a, 0x07, 'v', 'e', 'r', 's', 'i', 'o', 'n',
136     // pigweed.proto.nested_pigweed.device_info.attributes[0].value
137     0x12, 0x05, '5', '.', '3', '.', '1',
138     // pigweed.proto.nested_pigweed.device_info.attributes[1]
139     0x22, 0x10,
140     // pigweed.proto.nested_pigweed.device_info.attributes[1].key
141     0x0a, 0x04, 'c', 'h', 'i', 'p',
142     // pigweed.proto.nested_pigweed.device_info.attributes[1].value
143     0x12, 0x08, 'l', 'e', 'f', 't', '-', 's', 'o', 'c',
144     // pigweed.proto.nested_pigweed.device_info.status
145     0x18, 0x03,
146     // pigweed.id[0]
147     0x52, 0x02,
148     // pigweed.id[0].id
149     0x08, 0x31,
150     // pigweed.id[1]
151     0x52, 0x02,
152     // pigweed.id[1].id
153     0x08, 0x39,
154     // pigweed.id[2]
155     0x52, 0x02,
156     // pigweed.id[2].id
157     0x08, 0x4b,
158     // pigweed.id[3]
159     0x52, 0x02,
160     // pigweed.id[3].id
161     0x08, 0x67,
162     // pigweed.id[4]
163     0x52, 0x03,
164     // pigweed.id[4].id
165     0x08, 0x8d, 0x01
166   };
167   // clang-format on
168
169   Result result = encoder.Encode();
170   ASSERT_EQ(result.status(), OkStatus());
171   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
172   EXPECT_EQ(std::memcmp(
173                 result.value().data(), expected_proto, sizeof(expected_proto)),
174             0);
175 }
176
177 TEST(CodegenRepeated, NonPackedScalar) {
178   std::byte encode_buffer[32];
179   NestedEncoder encoder(encode_buffer);
180
181   RepeatedTest::Encoder repeated_test(&encoder);
182   for (int i = 0; i < 4; ++i) {
183     repeated_test.WriteUint32s(i * 16);
184   }
185
186   constexpr uint8_t expected_proto[] = {
187       0x08, 0x00, 0x08, 0x10, 0x08, 0x20, 0x08, 0x30};
188
189   Result result = encoder.Encode();
190   ASSERT_EQ(result.status(), OkStatus());
191   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
192   EXPECT_EQ(std::memcmp(
193                 result.value().data(), expected_proto, sizeof(expected_proto)),
194             0);
195 }
196
197 TEST(CodegenRepeated, PackedScalar) {
198   std::byte encode_buffer[32];
199   NestedEncoder encoder(encode_buffer);
200
201   RepeatedTest::Encoder repeated_test(&encoder);
202   constexpr uint32_t values[] = {0, 16, 32, 48};
203   repeated_test.WriteUint32s(values);
204
205   constexpr uint8_t expected_proto[] = {0x0a, 0x04, 0x00, 0x10, 0x20, 0x30};
206   Result result = encoder.Encode();
207   ASSERT_EQ(result.status(), OkStatus());
208   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
209   EXPECT_EQ(std::memcmp(
210                 result.value().data(), expected_proto, sizeof(expected_proto)),
211             0);
212 }
213
214 TEST(CodegenRepeated, NonScalar) {
215   std::byte encode_buffer[32];
216   NestedEncoder encoder(encode_buffer);
217
218   RepeatedTest::Encoder repeated_test(&encoder);
219   constexpr const char* strings[] = {"the", "quick", "brown", "fox"};
220   for (const char* s : strings) {
221     repeated_test.WriteStrings(s);
222   }
223
224   constexpr uint8_t expected_proto[] = {
225       0x1a, 0x03, 't', 'h', 'e', 0x1a, 0x5, 'q',  'u', 'i', 'c', 'k',
226       0x1a, 0x5,  'b', 'r', 'o', 'w',  'n', 0x1a, 0x3, 'f', 'o', 'x'};
227   Result result = encoder.Encode();
228   ASSERT_EQ(result.status(), OkStatus());
229   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
230   EXPECT_EQ(std::memcmp(
231                 result.value().data(), expected_proto, sizeof(expected_proto)),
232             0);
233 }
234
235 TEST(CodegenRepeated, Message) {
236   std::byte encode_buffer[64];
237   NestedEncoder<1, 3> encoder(encode_buffer);
238
239   RepeatedTest::Encoder repeated_test(&encoder);
240   for (int i = 0; i < 3; ++i) {
241     auto structs = repeated_test.GetStructsEncoder();
242     structs.WriteOne(i * 1);
243     structs.WriteTwo(i * 2);
244   }
245
246   // clang-format off
247   constexpr uint8_t expected_proto[] = {
248     0x2a, 0x04, 0x08, 0x00, 0x10, 0x00, 0x2a, 0x04, 0x08,
249     0x01, 0x10, 0x02, 0x2a, 0x04, 0x08, 0x02, 0x10, 0x04};
250   // clang-format on
251
252   Result result = encoder.Encode();
253   ASSERT_EQ(result.status(), OkStatus());
254   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
255   EXPECT_EQ(std::memcmp(
256                 result.value().data(), expected_proto, sizeof(expected_proto)),
257             0);
258 }
259
260 TEST(Codegen, Proto2) {
261   std::byte encode_buffer[64];
262   NestedEncoder<1, 3> encoder(encode_buffer);
263
264   Foo::Encoder foo(&encoder);
265   foo.WriteInt(3);
266
267   {
268     constexpr std::byte data[] = {
269         std::byte(0xde), std::byte(0xad), std::byte(0xbe), std::byte(0xef)};
270     Bar::Encoder bar = foo.GetBarEncoder();
271     bar.WriteData(data);
272   }
273
274   constexpr uint8_t expected_proto[] = {
275       0x08, 0x03, 0x1a, 0x06, 0x0a, 0x04, 0xde, 0xad, 0xbe, 0xef};
276
277   Result result = encoder.Encode();
278   ASSERT_EQ(result.status(), OkStatus());
279   EXPECT_EQ(result.value().size(), sizeof(expected_proto));
280   EXPECT_EQ(std::memcmp(
281                 result.value().data(), expected_proto, sizeof(expected_proto)),
282             0);
283 }
284
285 TEST(Codegen, Import) {
286   std::byte encode_buffer[64];
287   NestedEncoder<1, 3> encoder(encode_buffer);
288
289   Period::Encoder period(&encoder);
290   {
291     imported::Timestamp::Encoder start = period.GetStartEncoder();
292     start.WriteSeconds(1589501793);
293     start.WriteNanoseconds(511613110);
294   }
295
296   {
297     imported::Timestamp::Encoder end = period.GetEndEncoder();
298     end.WriteSeconds(1589501841);
299     end.WriteNanoseconds(490367432);
300   }
301
302   EXPECT_EQ(encoder.Encode().status(), OkStatus());
303 }
304
305 TEST(Codegen, NonPigweedPackage) {
306   using namespace non::pigweed::package::name;
307   std::byte encode_buffer[64];
308   std::array<const int64_t, 2> repeated = {0, 1};
309   NestedEncoder<1, 2> encoder(encode_buffer);
310   Packed::Encoder packed(&encoder);
311   packed.WriteRep(std::span<const int64_t>(repeated));
312   packed.WritePacked("packed");
313
314   EXPECT_EQ(encoder.Encode().status(), OkStatus());
315 }
316
317 }  // namespace
318 }  // namespace pw::protobuf