blob: 49182816e742b8ad256c57fbe3de3956a912b3cb [file] [log] [blame]
Austin Schuh3e95e5d2019-09-20 00:08:54 -07001#include "aos/json_to_flatbuffer.h"
2
Austin Schuh3e95e5d2019-09-20 00:08:54 -07003#include "aos/json_to_flatbuffer_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -07004#include "aos/testing/path.h"
Austin Schuh3e95e5d2019-09-20 00:08:54 -07005#include "flatbuffers/minireflect.h"
Brian Silverman5c710412021-02-09 19:09:32 -08006#include "gtest/gtest.h"
Austin Schuh3e95e5d2019-09-20 00:08:54 -07007
8namespace aos {
9namespace testing {
10
11class JsonToFlatbufferTest : public ::testing::Test {
12 public:
13 JsonToFlatbufferTest() {}
14
Brian Silvermanc5105ab2021-02-10 17:55:38 -080015 FlatbufferVector<reflection::Schema> Schema() {
Austin Schuh373f1762021-06-02 21:07:09 -070016 return FileToFlatbuffer<reflection::Schema>(
17 ArtifactPath("aos/json_to_flatbuffer.bfbs"));
Brian Silvermanc5105ab2021-02-10 17:55:38 -080018 }
19
Austin Schuh3e95e5d2019-09-20 00:08:54 -070020 bool JsonAndBack(const ::std::string str) { return JsonAndBack(str, str); }
21
22 bool JsonAndBack(const ::std::string in, const ::std::string out) {
23 printf("Testing: %s\n", in.c_str());
Brian Silvermanc5105ab2021-02-10 17:55:38 -080024 FlatbufferDetachedBuffer<Configuration> fb_typetable =
Austin Schuhadd6eb32020-11-09 21:24:26 -080025 JsonToFlatbuffer<Configuration>(in.data());
Brian Silvermanc5105ab2021-02-10 17:55:38 -080026 FlatbufferDetachedBuffer<Configuration> fb_reflection =
27 JsonToFlatbuffer(in.data(), FlatbufferType(&Schema().message()));
Austin Schuh3e95e5d2019-09-20 00:08:54 -070028
Brian Silvermanc5105ab2021-02-10 17:55:38 -080029 if (fb_typetable.span().size() == 0) {
30 return false;
31 }
32 if (fb_reflection.span().size() == 0) {
Austin Schuh3e95e5d2019-09-20 00:08:54 -070033 return false;
34 }
35
Brian Silvermanc5105ab2021-02-10 17:55:38 -080036 const ::std::string back_typetable = FlatbufferToJson(fb_typetable);
37 const ::std::string back_reflection = FlatbufferToJson(fb_reflection);
Austin Schuh3e95e5d2019-09-20 00:08:54 -070038
Brian Silvermanc5105ab2021-02-10 17:55:38 -080039 printf("Back to string via TypeTable: %s\n", back_typetable.c_str());
40 printf("Back to string via reflection: %s\n", back_reflection.c_str());
Austin Schuh3e95e5d2019-09-20 00:08:54 -070041
Brian Silvermanc5105ab2021-02-10 17:55:38 -080042 return back_typetable == out && back_reflection == out;
Austin Schuh3e95e5d2019-09-20 00:08:54 -070043 }
44};
45
46// Tests that the various escapes work as expected.
47TEST_F(JsonToFlatbufferTest, ValidEscapes) {
48 EXPECT_TRUE(
49 JsonAndBack("{ \"foo_string\": \"a\\\"b\\/c\\bd\\fc\\nd\\re\\tf\" }",
50 "{ \"foo_string\": \"a\\\"b/c\\bd\\fc\\nd\\re\\tf\" }"));
51}
52
53// Test the easy ones. Test every type, single, no nesting.
54TEST_F(JsonToFlatbufferTest, Basic) {
55 EXPECT_TRUE(JsonAndBack("{ \"foo_bool\": true }"));
56
57 EXPECT_TRUE(JsonAndBack("{ \"foo_byte\": 5 }"));
58 EXPECT_TRUE(JsonAndBack("{ \"foo_ubyte\": 5 }"));
59
60 EXPECT_TRUE(JsonAndBack("{ \"foo_short\": 5 }"));
61 EXPECT_TRUE(JsonAndBack("{ \"foo_ushort\": 5 }"));
62
63 EXPECT_TRUE(JsonAndBack("{ \"foo_int\": 5 }"));
64 EXPECT_TRUE(JsonAndBack("{ \"foo_uint\": 5 }"));
65
66 EXPECT_TRUE(JsonAndBack("{ \"foo_long\": 5 }"));
67 EXPECT_TRUE(JsonAndBack("{ \"foo_ulong\": 5 }"));
68
69 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": 5.0 }"));
70 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": 5.0 }"));
71
Alex Perrycb7da4b2019-08-28 19:35:56 -070072 EXPECT_TRUE(JsonAndBack("{ \"foo_enum\": \"None\" }"));
73 EXPECT_TRUE(JsonAndBack("{ \"foo_enum\": \"UType\" }"));
74
75 EXPECT_TRUE(JsonAndBack("{ \"foo_enum_default\": \"None\" }"));
76 EXPECT_TRUE(JsonAndBack("{ \"foo_enum_default\": \"UType\" }"));
77
Austin Schuh3e95e5d2019-09-20 00:08:54 -070078 EXPECT_TRUE(JsonAndBack("{ \"foo_string\": \"baz\" }"));
Brian Silverman5c710412021-02-09 19:09:32 -080079
80 EXPECT_TRUE(JsonAndBack("{ \"foo_enum_nonconsecutive\": \"Zero\" }"));
81 EXPECT_TRUE(JsonAndBack("{ \"foo_enum_nonconsecutive\": \"Big\" }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -070082}
83
Austin Schuh9fa0b8e2021-03-21 19:21:50 -070084// Tests that Inf is handled correctly
85TEST_F(JsonToFlatbufferTest, Inf) {
86 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": inf }"));
87 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": -inf }"));
88 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": inf }"));
89 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": -inf }"));
90}
91
Austin Schuhbba0c3c2019-11-29 22:00:34 -080092// Tests that NaN is handled correctly
93TEST_F(JsonToFlatbufferTest, Nan) {
94 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": nan }"));
95 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": -nan }"));
Austin Schuh9fa0b8e2021-03-21 19:21:50 -070096 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": nan }"));
97 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": -nan }"));
Austin Schuhbba0c3c2019-11-29 22:00:34 -080098}
99
Pallavi Madhukare2eb2812022-07-19 09:56:09 -0700100// Tests that unicode is handled correctly
101TEST_F(JsonToFlatbufferTest, Unicode) {
102 EXPECT_TRUE(JsonAndBack("{ \"foo_string\": \"\\uF672\" }"));
103 EXPECT_TRUE(JsonAndBack("{ \"foo_string\": \"\\uEFEF\" }"));
104 EXPECT_TRUE(JsonAndBack("{ \"foo_string\": \"helloworld\\uD83E\\uDE94\" }"));
105 EXPECT_TRUE(JsonAndBack("{ \"foo_string\": \"\\uD83C\\uDF32\" }"));
106 EXPECT_FALSE(JsonAndBack("{ \"foo_string\": \"\\uP890\" }"));
107 EXPECT_FALSE(JsonAndBack("{ \"foo_string\": \"\\u!FA8\" }"));
108 EXPECT_FALSE(JsonAndBack("{ \"foo_string\": \"\\uF89\" }"));
109 EXPECT_FALSE(JsonAndBack("{ \"foo_string\": \"\\uD83C\" }"));
110}
111
Austin Schuh84314af2019-10-03 09:11:34 -0700112// Tests that we can handle decimal points.
113TEST_F(JsonToFlatbufferTest, DecimalPoint) {
114 EXPECT_TRUE(JsonAndBack("{ \"foo_float\": 5.1 }"));
115 EXPECT_TRUE(JsonAndBack("{ \"foo_double\": 5.1 }"));
116}
117
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700118// Test what happens if you pass a field name that we don't know.
119TEST_F(JsonToFlatbufferTest, InvalidFieldName) {
120 EXPECT_FALSE(JsonAndBack("{ \"foo\": 5 }"));
121}
122
Alex Perrycb7da4b2019-08-28 19:35:56 -0700123// Tests that an invalid enum type is handled correctly.
124TEST_F(JsonToFlatbufferTest, InvalidEnumName) {
125 EXPECT_FALSE(JsonAndBack("{ \"foo_enum\": \"5ype\" }"));
126
127 EXPECT_FALSE(JsonAndBack("{ \"foo_enum_default\": \"7ype\" }"));
Brian Silverman5c710412021-02-09 19:09:32 -0800128
129 EXPECT_FALSE(JsonAndBack("{ \"foo_enum_nonconsecutive\": \"Nope\" }"));
130
131 EXPECT_FALSE(
132 JsonAndBack("{ \"foo_enum_nonconsecutive_default\": \"Nope\" }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700133}
134
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700135// Test that adding a duplicate field results in an error.
136TEST_F(JsonToFlatbufferTest, DuplicateField) {
137 EXPECT_FALSE(
138 JsonAndBack("{ \"foo_int\": 5, \"foo_int\": 7 }", "{ \"foo_int\": 7 }"));
139}
140
141// Test that various syntax errors are caught correctly
142TEST_F(JsonToFlatbufferTest, InvalidSyntax) {
143 EXPECT_FALSE(JsonAndBack("{ \"foo_int\": 5"));
144 EXPECT_FALSE(JsonAndBack("{ \"foo_int\": 5 "));
145 EXPECT_FALSE(JsonAndBack("{ \"foo_string\": \""));
146 EXPECT_FALSE(JsonAndBack("{ \"foo_int\": 5 } }"));
147
148 EXPECT_FALSE(JsonAndBack("{ foo_int: 5 }"));
149
150 EXPECT_FALSE(JsonAndBack("{ \"foo_int\": 5, }", "{ \"foo_int\": 5 }"));
151
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700152 EXPECT_FALSE(
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700153 JsonAndBack("{ \"apps\":\n[\n{\n\"name\": \"woot\"\n},\n{\n\"name\": "
154 "\"wow\"\n} ,\n]\n}"));
155
156 EXPECT_FALSE(JsonAndBack(
157 "{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" } ] , }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700158
159 EXPECT_FALSE(
160 JsonAndBack("{ \"vector_foo_string\": [ \"bar\", \"baz\" ] , }"));
161
162 EXPECT_FALSE(
163 JsonAndBack("{ \"single_application\": { \"name\": \"woot\" } , }"));
164}
165
166// Test arrays of simple types.
167TEST_F(JsonToFlatbufferTest, Array) {
168 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_byte\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700169 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_byte\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700170 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ubyte\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700171 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ubyte\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700172
173 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_short\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700174 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_short\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700175 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ushort\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700176 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ushort\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700177
178 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_int\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700179 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_int\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700180 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_uint\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700181 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_uint\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700182
183 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_long\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700184 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_long\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700185 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ulong\": [ 9, 7, 1 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700186 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_ulong\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700187
188 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700189 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_float\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700190 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_double\": [ 9.0, 7.0, 1.0 ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700191 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_double\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700192
193 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_float\": [ 9, 7, 1 ] }",
194 "{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ] }"));
195 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_double\": [ 9, 7, 1 ] }",
196 "{ \"vector_foo_double\": [ 9.0, 7.0, 1.0 ] }"));
197
198 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_string\": [ \"bar\", \"baz\" ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700199 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_string\": [ ] }"));
Ravago Jonescf453ab2020-05-06 21:14:53 -0700200 EXPECT_TRUE(JsonAndBack(
201 "{ \"vector_foo_enum\": [ \"None\", \"UType\", \"Bool\" ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700202 EXPECT_TRUE(JsonAndBack("{ \"vector_foo_enum\": [ ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700203}
204
205// Test nested messages, and arrays of nested messages.
206TEST_F(JsonToFlatbufferTest, NestedStruct) {
207 EXPECT_TRUE(
208 JsonAndBack("{ \"single_application\": { \"name\": \"woot\" } }"));
209
Alex Perrycb7da4b2019-08-28 19:35:56 -0700210 EXPECT_TRUE(JsonAndBack("{ \"single_application\": { } }"));
211
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700212 EXPECT_TRUE(JsonAndBack(
213 "{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" } ] }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700214
Ravago Jonescf453ab2020-05-06 21:14:53 -0700215 EXPECT_TRUE(JsonAndBack("{ \"apps\": [ { }, { } ] }"));
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700216}
217
Austin Schuh84314af2019-10-03 09:11:34 -0700218// Test that we can parse an empty message.
219TEST_F(JsonToFlatbufferTest, EmptyMessage) {
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700220 // Empty message works.
Austin Schuh84314af2019-10-03 09:11:34 -0700221 EXPECT_TRUE(JsonAndBack("{ }"));
222}
223
Austin Schuh81da4b22019-10-06 14:03:24 -0700224// Tests that comments get stripped.
225TEST_F(JsonToFlatbufferTest, Comments) {
226 EXPECT_TRUE(JsonAndBack("{ /* foo */ \"vector_foo_double\": [ 9, 7, 1 ] }",
227 "{ \"vector_foo_double\": [ 9.0, 7.0, 1.0 ] }"));
228}
229
Austin Schuh9e2532d2019-10-06 14:01:15 -0700230// Tests that multiple arrays get properly handled.
231TEST_F(JsonToFlatbufferTest, MultipleArrays) {
232 EXPECT_TRUE(
233 JsonAndBack("{ \"vector_foo_float\": [ 9, 7, 1 ], \"vector_foo_double\": "
234 "[ 9, 7, 1 ] }",
235 "{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ], "
236 "\"vector_foo_double\": [ 9.0, 7.0, 1.0 ] }"));
237}
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700238
Alex Perrycb7da4b2019-08-28 19:35:56 -0700239// Tests that multiple arrays get properly handled.
240TEST_F(JsonToFlatbufferTest, NestedArrays) {
241 EXPECT_TRUE(
Ravago Jonescf453ab2020-05-06 21:14:53 -0700242 JsonAndBack("{ \"vov\": { \"v\": [ { \"str\": [ \"a\", \"b\" ] }, { "
243 "\"str\": [ \"c\", \"d\" ] } ] } }"));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700244}
245
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700246// TODO(austin): Missmatched values.
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700247//
248// TODO(austin): unions?
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700249
Austin Schuhd3936202020-04-07 20:11:07 -0700250TEST_F(JsonToFlatbufferTest, TrimmedVector) {
251 std::string json_short = "{ \"vector_foo_int\": [ 0";
252 for (int i = 1; i < 100; ++i) {
253 json_short += ", ";
254 json_short += std::to_string(i);
255 }
256 std::string json_long = json_short;
257 json_short += " ] }";
258 json_long += ", 101 ] }";
259
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800260 const FlatbufferDetachedBuffer<Configuration> fb_short_typetable(
Austin Schuhadd6eb32020-11-09 21:24:26 -0800261 JsonToFlatbuffer<Configuration>(json_short));
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800262 ASSERT_GT(fb_short_typetable.span().size(), 0);
263 const FlatbufferDetachedBuffer<Configuration> fb_long_typetable(
Austin Schuhadd6eb32020-11-09 21:24:26 -0800264 JsonToFlatbuffer<Configuration>(json_long));
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800265 ASSERT_GT(fb_long_typetable.span().size(), 0);
266 const FlatbufferDetachedBuffer<Configuration> fb_short_reflection(
267 JsonToFlatbuffer(json_short, FlatbufferType(&Schema().message())));
268 ASSERT_GT(fb_short_reflection.span().size(), 0);
269 const FlatbufferDetachedBuffer<Configuration> fb_long_reflection(
270 JsonToFlatbuffer(json_long, FlatbufferType(&Schema().message())));
271 ASSERT_GT(fb_long_reflection.span().size(), 0);
Austin Schuhd3936202020-04-07 20:11:07 -0700272
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800273 const std::string back_json_short_typetable = FlatbufferToJson<Configuration>(
274 fb_short_typetable, {.multi_line = false, .max_vector_size = 100});
275 const std::string back_json_long_typetable = FlatbufferToJson<Configuration>(
276 fb_long_typetable, {.multi_line = false, .max_vector_size = 100});
277 const std::string back_json_short_reflection =
278 FlatbufferToJson<Configuration>(
279 fb_short_reflection, {.multi_line = false, .max_vector_size = 100});
280 const std::string back_json_long_reflection = FlatbufferToJson<Configuration>(
281 fb_long_reflection, {.multi_line = false, .max_vector_size = 100});
Austin Schuhd3936202020-04-07 20:11:07 -0700282
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800283 EXPECT_EQ(json_short, back_json_short_typetable);
284 EXPECT_EQ(json_short, back_json_short_reflection);
Austin Schuh041fe9f2021-10-16 23:01:15 -0700285 EXPECT_EQ("{ \"vector_foo_int\": [ \"... 101 elements ...\" ] }",
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800286 back_json_long_typetable);
Austin Schuh041fe9f2021-10-16 23:01:15 -0700287 EXPECT_EQ("{ \"vector_foo_int\": [ \"... 101 elements ...\" ] }",
Brian Silvermanc5105ab2021-02-10 17:55:38 -0800288 back_json_long_reflection);
Austin Schuhd3936202020-04-07 20:11:07 -0700289}
290
Austin Schuh7f99e472020-06-17 20:38:17 -0700291// Tests that a nullptr buffer prints nullptr.
292TEST_F(JsonToFlatbufferTest, NullptrData) {
293 EXPECT_EQ("null", TableFlatbufferToJson((const flatbuffers::Table *)(nullptr),
Ravago Jonescf453ab2020-05-06 21:14:53 -0700294 ConfigurationTypeTable()));
Austin Schuh7f99e472020-06-17 20:38:17 -0700295}
296
Austin Schuh3e95e5d2019-09-20 00:08:54 -0700297} // namespace testing
298} // namespace aos