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