blob: a4b09f78ebbc74e86fccbac0b055cf4a00ca7e14 [file] [log] [blame]
Philipp Schrader790cb542023-07-05 21:06:52 -07001#include "flatbuffers/reflection.h"
2#include "gtest/gtest.h"
3
Tyler Chatow5e369a42019-11-23 11:57:31 -08004#include "aos/json_to_flatbuffer.h"
5#include "aos/json_to_flatbuffer_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -07006#include "aos/testing/path.h"
Tyler Chatow5e369a42019-11-23 11:57:31 -08007#include "aos/util/file.h"
Tyler Chatow5e369a42019-11-23 11:57:31 -08008
9namespace aos {
10namespace testing {
11
Austin Schuh373f1762021-06-02 21:07:09 -070012using aos::testing::ArtifactPath;
13
Tyler Chatow5e369a42019-11-23 11:57:31 -080014class FlatbufferIntrospectionTest : public ::testing::Test {
15 public:
16 FlatbufferIntrospectionTest()
Austin Schuh0de30f32020-12-06 12:44:28 -080017 : schema_data_(FileToFlatbuffer<reflection::Schema>(
Austin Schuh373f1762021-06-02 21:07:09 -070018 ArtifactPath("aos/json_to_flatbuffer.bfbs"))) {
Austin Schuhadd6eb32020-11-09 21:24:26 -080019 schema_ = reflection::GetSchema(schema_data_.span().data());
Tyler Chatow5e369a42019-11-23 11:57:31 -080020 }
21
22 protected:
Austin Schuh0de30f32020-12-06 12:44:28 -080023 FlatbufferVector<reflection::Schema> schema_data_;
Tyler Chatow5e369a42019-11-23 11:57:31 -080024 const reflection::Schema *schema_;
25};
26
27TEST_F(FlatbufferIntrospectionTest, IntegerTest) {
28 flatbuffers::FlatBufferBuilder builder;
29 ConfigurationBuilder config_builder(builder);
30
31 config_builder.add_foo_byte(-5);
32 config_builder.add_foo_ubyte(5);
33 config_builder.add_foo_bool(true);
34
35 config_builder.add_foo_short(-10);
36 config_builder.add_foo_ushort(10);
37
38 config_builder.add_foo_int(-20);
39 config_builder.add_foo_uint(20);
40
41 config_builder.add_foo_long(-100);
42 config_builder.add_foo_ulong(100);
43
44 builder.Finish(config_builder.Finish());
45
46 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
47
48 EXPECT_EQ(out,
49 "{\"foo_bool\": true, \"foo_byte\": -5, \"foo_int\": -20, "
50 "\"foo_long\": -100, \"foo_short\": -10, \"foo_ubyte\": 5, "
51 "\"foo_uint\": 20, \"foo_ulong\": 100, \"foo_ushort\": 10}");
52}
53
54TEST_F(FlatbufferIntrospectionTest, FloatTest) {
55 flatbuffers::FlatBufferBuilder builder;
56 ConfigurationBuilder config_builder(builder);
57
58 config_builder.add_foo_float(1.0 / 3.0);
59 config_builder.add_foo_double(5.0 / 9.0);
60
61 builder.Finish(config_builder.Finish());
62
63 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
64
65 EXPECT_EQ(out,
66 "{\"foo_double\": 0.555555555555556, \"foo_float\": 0.333333}");
67}
68
Brian Silvermana6aa5042020-04-28 16:42:38 -070069TEST_F(FlatbufferIntrospectionTest, NanFloatTest) {
70 flatbuffers::FlatBufferBuilder builder;
71 ConfigurationBuilder config_builder(builder);
72
73 config_builder.add_foo_float(std::numeric_limits<float>::quiet_NaN());
74 config_builder.add_foo_double(std::numeric_limits<double>::quiet_NaN());
75
76 builder.Finish(config_builder.Finish());
77
78 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
79
80 EXPECT_EQ(out, "{\"foo_double\": null, \"foo_float\": null}");
81}
82
Tyler Chatow5e369a42019-11-23 11:57:31 -080083TEST_F(FlatbufferIntrospectionTest, VectorScalarTest) {
84 flatbuffers::FlatBufferBuilder builder;
85
86 // Flatbuffers don't like creating vectors simultaneously with table, so do
87 // first.
88 auto foo_bytes = builder.CreateVector<int8_t>({-3, -2, -1, 0, 1, 2, 3});
89 auto foo_ubytes = builder.CreateVector<uint8_t>({0, 1, 2, 3, 4, 5, 6});
90 auto foo_bools = builder.CreateVector<uint8_t>({true, false, true, false});
91
92 auto foo_shorts =
93 builder.CreateVector<int16_t>({-30, -20, -10, 0, 10, 20, 30});
94 auto foo_ushorts =
95 builder.CreateVector<uint16_t>({0, 10, 20, 30, 40, 50, 60});
96
97 auto foo_ints =
98 builder.CreateVector<int32_t>({-300, -200, -100, 0, 100, 200, 300});
99 auto foo_uints =
100 builder.CreateVector<uint32_t>({0, 100, 200, 300, 400, 500, 600});
101
102 auto foo_longs =
103 builder.CreateVector<int64_t>({-3000, -2000, -1000, 0, 1000, 2000, 3000});
104 auto foo_ulongs =
105 builder.CreateVector<uint64_t>({0, 1000, 2000, 3000, 4000, 5000, 6000});
106
107 auto foo_floats =
108 builder.CreateVector<float>({0.0, 1.0 / 9.0, 2.0 / 9.0, 3.0 / 9.0});
109 auto foo_doubles =
110 builder.CreateVector<double>({0, 1.0 / 9.0, 2.0 / 9.0, 3.0 / 9.0});
111
112 ConfigurationBuilder config_builder(builder);
113 config_builder.add_vector_foo_byte(foo_bytes);
114 config_builder.add_vector_foo_ubyte(foo_ubytes);
115 config_builder.add_vector_foo_bool(foo_bools);
116
117 config_builder.add_vector_foo_short(foo_shorts);
118 config_builder.add_vector_foo_ushort(foo_ushorts);
119
120 config_builder.add_vector_foo_int(foo_ints);
121 config_builder.add_vector_foo_uint(foo_uints);
122
123 config_builder.add_vector_foo_long(foo_longs);
124 config_builder.add_vector_foo_ulong(foo_ulongs);
125
126 config_builder.add_vector_foo_float(foo_floats);
127 config_builder.add_vector_foo_double(foo_doubles);
128
129 builder.Finish(config_builder.Finish());
130
131 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
132
133 EXPECT_EQ(
134 out,
135 "{\"vector_foo_bool\": [true, false, true, false], \"vector_foo_byte\": "
136 "[-3, -2, -1, 0, 1, 2, 3], \"vector_foo_double\": [0, 0.111111111111111, "
137 "0.222222222222222, 0.333333333333333], \"vector_foo_float\": [0, "
138 "0.111111, 0.222222, 0.333333], \"vector_foo_int\": [-300, -200, -100, "
139 "0, 100, 200, 300], \"vector_foo_long\": [-3000, -2000, -1000, 0, 1000, "
140 "2000, 3000], \"vector_foo_short\": [-30, -20, -10, 0, 10, 20, 30], "
141 "\"vector_foo_ubyte\": [0, 1, 2, 3, 4, 5, 6], \"vector_foo_uint\": [0, "
142 "100, 200, 300, 400, 500, 600], \"vector_foo_ulong\": [0, 1000, 2000, "
143 "3000, 4000, 5000, 6000], \"vector_foo_ushort\": [0, 10, 20, 30, 40, 50, "
144 "60]}");
145}
146
147TEST_F(FlatbufferIntrospectionTest, StringTest) {
148 flatbuffers::FlatBufferBuilder builder;
149
150 auto foo_string = builder.CreateString("I <3 FlatBuffers!");
151
152 ConfigurationBuilder config_builder(builder);
153 config_builder.add_foo_string(foo_string);
154
155 builder.Finish(config_builder.Finish());
156
157 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
158
159 EXPECT_EQ(out, "{\"foo_string\": \"I <3 FlatBuffers!\"}");
160}
161
162TEST_F(FlatbufferIntrospectionTest, EnumTest) {
163 flatbuffers::FlatBufferBuilder builder;
164
165 ConfigurationBuilder config_builder(builder);
Austin Schuh872723c2019-12-25 14:38:09 -0800166 config_builder.add_foo_enum(BaseType::UShort);
Tyler Chatow5e369a42019-11-23 11:57:31 -0800167
168 builder.Finish(config_builder.Finish());
169
170 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
171
172 EXPECT_EQ(out, "{\"foo_enum\": \"UShort\"}");
173}
174
Brian Silvermana6aa5042020-04-28 16:42:38 -0700175TEST_F(FlatbufferIntrospectionTest, EnumWithUnknownValueTest) {
176 flatbuffers::FlatBufferBuilder builder;
177
178 ConfigurationBuilder config_builder(builder);
179 // 123 is not part of the enum. We expect it to be represented by null in
180 // the json.
181 config_builder.fbb_.AddElement<uint8_t>(Configuration::VT_FOO_ENUM, 123, 0);
182
183 builder.Finish(config_builder.Finish());
184
185 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
186
187 EXPECT_EQ(out, "{\"foo_enum\": 123}");
188}
189
Tyler Chatow5e369a42019-11-23 11:57:31 -0800190TEST_F(FlatbufferIntrospectionTest, VectorStringTest) {
191 flatbuffers::FlatBufferBuilder builder;
192
193 std::vector<std::vector<std::string>> words{
194 {"abc", "acb"}, {"bac", "bca"}, {"cab", "cba"}};
195 std::vector<flatbuffers::Offset<
196 flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>>
197 strings;
198
199 for (const auto &v : words) {
200 strings.push_back(builder.CreateVectorOfStrings(v));
201 }
202
203 std::vector<flatbuffers::Offset<VectorOfStrings>> sub_vectors;
204
205 for (const auto &v : strings) {
206 VectorOfStringsBuilder v_builder(builder);
207 v_builder.add_str(v);
208 sub_vectors.push_back(v_builder.Finish());
209 }
210
211 auto foo_vov = builder.CreateVector(sub_vectors);
212
213 VectorOfVectorOfStringBuilder vov_builder(builder);
214 vov_builder.add_v(foo_vov);
215 auto vov = vov_builder.Finish();
216
217 ConfigurationBuilder config_builder(builder);
218 config_builder.add_vector_foo_string(strings[0]);
219 config_builder.add_vov(vov);
220
221 builder.Finish(config_builder.Finish());
222
223 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
224
225 EXPECT_EQ(out,
226 "{\"vector_foo_string\": [\"abc\", \"acb\"], \"vov\": {\"v\": "
227 "[{\"str\": [\"abc\", \"acb\"]}, {\"str\": [\"bac\", \"bca\"]}, "
228 "{\"str\": [\"cab\", \"cba\"]}]}}");
229}
230
231TEST_F(FlatbufferIntrospectionTest, TableTest) {
232 flatbuffers::FlatBufferBuilder builder;
233
234 auto foo_string2 = builder.CreateString("Nested Config String");
235 auto foo_bytes2 = builder.CreateVector<int8_t>({6, 7, 8, 9, 10});
236
237 ConfigurationBuilder config_builder2(builder);
238 config_builder2.add_foo_byte(10);
239 config_builder2.add_foo_string(foo_string2);
240 config_builder2.add_vector_foo_byte(foo_bytes2);
241
242 flatbuffers::Offset<Configuration> config_2 = config_builder2.Finish();
243
244 auto foo_string = builder.CreateString("Root Config String");
245 auto foo_bytes = builder.CreateVector<int8_t>({0, 1, 2, 3, 4, 5});
246
247 ConfigurationBuilder config_builder(builder);
248 config_builder.add_nested_config(config_2);
249 config_builder.add_foo_byte(5);
250 config_builder.add_foo_string(foo_string);
251 config_builder.add_vector_foo_byte(foo_bytes);
252
253 builder.Finish(config_builder.Finish());
254
255 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
256
257 EXPECT_EQ(out,
258 "{\"foo_byte\": 5, \"foo_string\": \"Root Config String\", "
259 "\"nested_config\": {\"foo_byte\": 10, \"foo_string\": \"Nested "
260 "Config String\", \"vector_foo_byte\": [6, 7, 8, 9, 10]}, "
261 "\"vector_foo_byte\": [0, 1, 2, 3, 4, 5]}");
262}
263
264TEST_F(FlatbufferIntrospectionTest, StructTest) {
265 flatbuffers::FlatBufferBuilder builder;
266
267 FooStructNested foo_struct2(10);
268
269 FooStruct foo_struct(5, foo_struct2);
270
271 ConfigurationBuilder config_builder(builder);
272 config_builder.add_foo_struct(&foo_struct);
273
274 builder.Finish(config_builder.Finish());
275
276 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
277
278 EXPECT_EQ(out,
279 "{\"foo_struct\": {\"foo_byte\": 5, \"nested_struct\": "
280 "{\"foo_byte\": 10}}}");
281}
282
283TEST_F(FlatbufferIntrospectionTest, VectorStructTest) {
284 flatbuffers::FlatBufferBuilder builder;
285
286 FooStructNested foo_struct2(1);
287
288 auto structs = builder.CreateVectorOfStructs(
289 std::vector<FooStruct>({{5, foo_struct2}, {10, foo_struct2}}));
290
291 ConfigurationBuilder config_builder(builder);
292 config_builder.add_vector_foo_struct(structs);
293
294 builder.Finish(config_builder.Finish());
295
296 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
297
298 EXPECT_EQ(out,
299 "{\"vector_foo_struct\": [{\"foo_byte\": 5, \"nested_struct\": "
300 "{\"foo_byte\": 1}}, {\"foo_byte\": 10, \"nested_struct\": "
301 "{\"foo_byte\": 1}}]}");
302}
303
304TEST_F(FlatbufferIntrospectionTest, VectorEnumTest) {
305 flatbuffers::FlatBufferBuilder builder;
306
Austin Schuh872723c2019-12-25 14:38:09 -0800307 auto enums = builder.CreateVector<BaseType>(
308 {BaseType::UShort, BaseType::Obj, BaseType::UInt});
Tyler Chatow5e369a42019-11-23 11:57:31 -0800309
310 ConfigurationBuilder config_builder(builder);
milind upadhyay328d3392020-11-25 19:34:00 -0800311 config_builder.add_vector_foo_enum(enums);
Tyler Chatow5e369a42019-11-23 11:57:31 -0800312
313 builder.Finish(config_builder.Finish());
314
315 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
316
317 EXPECT_EQ(out, "{\"vector_foo_enum\": [\"UShort\", \"Obj\", \"UInt\"]}");
318}
319
320TEST_F(FlatbufferIntrospectionTest, StructEnumTest) {
321 flatbuffers::FlatBufferBuilder builder;
322
Austin Schuh872723c2019-12-25 14:38:09 -0800323 StructEnum foo_struct(BaseType::UShort);
Tyler Chatow5e369a42019-11-23 11:57:31 -0800324
325 ConfigurationBuilder config_builder(builder);
326 config_builder.add_foo_struct_enum(&foo_struct);
327
328 builder.Finish(config_builder.Finish());
329
330 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
331
332 EXPECT_EQ(out, "{\"foo_struct_enum\": {\"foo_enum\": \"UShort\"}}");
333}
334
335TEST_F(FlatbufferIntrospectionTest, StringEscapeTest) {
336 flatbuffers::FlatBufferBuilder builder;
337
338 auto foo_string = builder.CreateString("\"\\\b\f\n\r\t");
339
340 ConfigurationBuilder config_builder(builder);
341 config_builder.add_foo_string(foo_string);
342
343 builder.Finish(config_builder.Finish());
344
345 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer());
346 EXPECT_EQ(out, "{\"foo_string\": \"\\\"\\\\\\b\\f\\n\\r\\t\"}");
347}
348
Austin Schuhd3936202020-04-07 20:11:07 -0700349TEST_F(FlatbufferIntrospectionTest, TrimmedVector) {
350 flatbuffers::FlatBufferBuilder builder;
351
352 std::vector<int32_t> contents;
353 for (int i = 0; i < 101; ++i) {
354 contents.push_back(i);
355 }
356 const auto contents_offset = builder.CreateVector(contents);
357
358 ConfigurationBuilder config_builder(builder);
359 config_builder.add_vector_foo_int(contents_offset);
360
361 builder.Finish(config_builder.Finish());
362
Ravago Jonese8338b02020-04-16 15:43:00 -0700363 std::string out =
Ravago Jonescf453ab2020-05-06 21:14:53 -0700364 FlatbufferToJson(schema_, builder.GetBufferPointer(),
365 {.multi_line = false, .max_vector_size = 100});
Austin Schuh041fe9f2021-10-16 23:01:15 -0700366 EXPECT_EQ(out, "{\"vector_foo_int\": [ \"... 101 elements ...\" ]}");
Austin Schuhd3936202020-04-07 20:11:07 -0700367}
368
Ravago Jonese8338b02020-04-16 15:43:00 -0700369TEST_F(FlatbufferIntrospectionTest, MultilineTest) {
370 flatbuffers::FlatBufferBuilder builder;
371 ConfigurationBuilder config_builder(builder);
372
373 config_builder.add_foo_bool(true);
374 config_builder.add_foo_int(-20);
375
376 builder.Finish(config_builder.Finish());
377
Ravago Jonescf453ab2020-05-06 21:14:53 -0700378 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer(),
379 {.multi_line = true});
Ravago Jonese8338b02020-04-16 15:43:00 -0700380
381 EXPECT_EQ(out,
382 "{\n"
383 " \"foo_bool\": true,\n"
384 " \"foo_int\": -20\n"
385 "}");
386}
387
388TEST_F(FlatbufferIntrospectionTest, MultilineStructTest) {
389 flatbuffers::FlatBufferBuilder builder;
390 ConfigurationBuilder config_builder(builder);
391
392 FooStructNested foo_struct2(10);
393 FooStruct foo_struct(5, foo_struct2);
394
395 config_builder.add_foo_struct(&foo_struct);
396
397 builder.Finish(config_builder.Finish());
398
Ravago Jonescf453ab2020-05-06 21:14:53 -0700399 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer(),
400 {.multi_line = true});
Ravago Jonese8338b02020-04-16 15:43:00 -0700401
402 EXPECT_EQ(out,
403 "{\n"
404 " \"foo_struct\": {\n"
405 " \"foo_byte\": 5,\n"
406 " \"nested_struct\": {\"foo_byte\": 10}\n"
407 " }\n"
408 "}");
409}
410
411TEST_F(FlatbufferIntrospectionTest, MultilineVectorStructTest) {
412 flatbuffers::FlatBufferBuilder builder;
413
414 FooStructNested foo_struct2(1);
415
416 auto structs = builder.CreateVectorOfStructs(
417 std::vector<FooStruct>({{5, foo_struct2}, {10, foo_struct2}}));
418
419 ConfigurationBuilder config_builder(builder);
420 config_builder.add_vector_foo_struct(structs);
421
422 builder.Finish(config_builder.Finish());
423
Ravago Jonescf453ab2020-05-06 21:14:53 -0700424 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer(),
425 {.multi_line = true});
Ravago Jonese8338b02020-04-16 15:43:00 -0700426
427 EXPECT_EQ(out,
428 "{\n"
429 " \"vector_foo_struct\": [\n"
430 " {\n"
431 " \"foo_byte\": 5,\n"
432 " \"nested_struct\": {\"foo_byte\": 1}\n"
433 " },\n"
434 " {\n"
435 " \"foo_byte\": 10,\n"
436 " \"nested_struct\": {\"foo_byte\": 1}\n"
437 " }\n"
438 " ]\n"
439 "}");
440}
441
442TEST_F(FlatbufferIntrospectionTest, MultilineVectorScalarTest) {
443 flatbuffers::FlatBufferBuilder builder;
444
445 // Flatbuffers don't like creating vectors simultaneously with table, so do
446 // first.
447 auto foo_ints =
448 builder.CreateVector<int32_t>({-300, -200, -100, 0, 100, 200, 300});
449
450 auto foo_floats =
451 builder.CreateVector<float>({0.0, 1.0 / 9.0, 2.0 / 9.0, 3.0 / 9.0});
452 auto foo_doubles =
453 builder.CreateVector<double>({0, 1.0 / 9.0, 2.0 / 9.0, 3.0 / 9.0});
454
455 ConfigurationBuilder config_builder(builder);
456
457 config_builder.add_vector_foo_int(foo_ints);
458 config_builder.add_vector_foo_float(foo_floats);
459 config_builder.add_vector_foo_double(foo_doubles);
460
461 builder.Finish(config_builder.Finish());
462
Ravago Jonescf453ab2020-05-06 21:14:53 -0700463 std::string out = FlatbufferToJson(schema_, builder.GetBufferPointer(),
464 {.multi_line = true});
Ravago Jonese8338b02020-04-16 15:43:00 -0700465
466 EXPECT_EQ(out,
467 "{\n"
468 " \"vector_foo_double\": [0, 0.111111111111111, "
469 "0.222222222222222, 0.333333333333333],\n"
470 " \"vector_foo_float\": [0, 0.111111, 0.222222, 0.333333],\n"
471 " \"vector_foo_int\": [-300, -200, -100, 0, 100, 200, 300]\n"
472 "}");
473}
474
Austin Schuh7f99e472020-06-17 20:38:17 -0700475// Tests that a nullptr buffer prints nullptr.
476TEST_F(FlatbufferIntrospectionTest, NullptrData) {
477 EXPECT_EQ("null", FlatbufferToJson(schema_, nullptr));
478}
479
480// Tests that a null schema gets caught.
481TEST(FlatbufferIntrospectionDeathTest, NullSchema) {
482 EXPECT_DEATH(
483 {
484 FlatbufferToJson(static_cast<const reflection::Schema *>(nullptr),
485 nullptr);
486 },
487 "Need to provide a schema");
488}
489
Tyler Chatow5e369a42019-11-23 11:57:31 -0800490} // namespace testing
491} // namespace aos