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