blob: 079eb11dd3fdf9ca857c407c9c45adee32e441f1 [file] [log] [blame]
Austin Schuh09d7ffa2019-10-03 23:43:34 -07001#include "aos/flatbuffer_merge.h"
2
3#include "gtest/gtest.h"
4
5#include "aos/json_to_flatbuffer.h"
6#include "aos/json_to_flatbuffer_generated.h"
7#include "flatbuffers/minireflect.h"
8
9namespace aos {
10namespace testing {
11
12class FlatbufferMerge : public ::testing::Test {
13 public:
14 FlatbufferMerge() {}
15
James Kuszmaulf3a3be22020-01-04 12:12:00 -080016 void ExpectMergedOutput(const flatbuffers::DetachedBuffer &fb_merged,
17 std::string_view expected_output) {
18 ASSERT_NE(fb_merged.size(), 0u);
19
20 const ::std::string merged_output =
21 FlatbufferToJson(fb_merged, ConfigurationTypeTable());
22 EXPECT_EQ(expected_output, merged_output);
23 }
24
Austin Schuh09d7ffa2019-10-03 23:43:34 -070025 void JsonMerge(const ::std::string in1, const ::std::string in2,
26 const ::std::string out) {
27 printf("Merging: %s\n", in1.c_str());
28 printf("Merging: %s\n", in2.c_str());
Austin Schuhe93d8642019-10-13 15:27:07 -070029 const flatbuffers::DetachedBuffer fb1 = JsonToFlatbuffer(
Austin Schuh09d7ffa2019-10-03 23:43:34 -070030 static_cast<const char *>(in1.c_str()), ConfigurationTypeTable());
31
32 const ::std::string in1_nested = "{ \"nested_config\": " + in1 + " }";
Austin Schuhe93d8642019-10-13 15:27:07 -070033 const flatbuffers::DetachedBuffer fb1_nested =
34 JsonToFlatbuffer(static_cast<const char *>(in1_nested.c_str()),
35 ConfigurationTypeTable());
Austin Schuh09d7ffa2019-10-03 23:43:34 -070036
Austin Schuhe93d8642019-10-13 15:27:07 -070037 const flatbuffers::DetachedBuffer fb2 = JsonToFlatbuffer(
Austin Schuh09d7ffa2019-10-03 23:43:34 -070038 static_cast<const char *>(in2.c_str()), ConfigurationTypeTable());
39
40 const ::std::string in2_nested = "{ \"nested_config\": " + in2 + " }";
Austin Schuhe93d8642019-10-13 15:27:07 -070041 const flatbuffers::DetachedBuffer fb2_nested =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070042 JsonToFlatbuffer(static_cast<const char *>(in2_nested.c_str()),
43 ConfigurationTypeTable());
44
45 const ::std::string out_nested = "{ \"nested_config\": " + out + " }";
46
Austin Schuhe93d8642019-10-13 15:27:07 -070047 const flatbuffers::DetachedBuffer empty =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070048 JsonToFlatbuffer("{ }", ConfigurationTypeTable());
49
50 ASSERT_NE(fb1.size(), 0u);
51 ASSERT_NE(fb2.size(), 0u);
52 ASSERT_NE(fb1_nested.size(), 0u);
53 ASSERT_NE(fb2_nested.size(), 0u);
54
55 // We now want to run 7 tests.
56 // in1 merged "" -> in1.
57 // in2 merged "" -> in2.
58 // "" merged in1 -> in1.
59 // "" merged in2 -> in2.
60 // nullptr merged in1 -> in1.
61 // in1 merged nullptr -> in1.
62 // in1 merged in2 -> out.
63
64 {
65 // in1 merged with "" => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -070066 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070067 MergeFlatBuffers<Configuration>(fb1.data(), empty.data());
68 ASSERT_NE(fb_merged.size(), 0u);
69
Austin Schuhe93d8642019-10-13 15:27:07 -070070 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070071 }
72
73 {
74 // in2 merged with "" => in2.
Austin Schuhe93d8642019-10-13 15:27:07 -070075 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070076 MergeFlatBuffers<Configuration>(fb2.data(), empty.data());
77 ASSERT_NE(fb_merged.size(), 0u);
78
Austin Schuhe93d8642019-10-13 15:27:07 -070079 EXPECT_EQ(in2, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070080 }
81
82 {
83 // "" merged with in1 => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -070084 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070085 MergeFlatBuffers<Configuration>(empty.data(), fb1.data());
86 ASSERT_NE(fb_merged.size(), 0u);
87
Austin Schuhe93d8642019-10-13 15:27:07 -070088 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070089 }
90
91 {
92 // "" merged with in2 => in2.
Austin Schuhe93d8642019-10-13 15:27:07 -070093 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070094 MergeFlatBuffers<Configuration>(empty.data(), fb2.data());
95 ASSERT_NE(fb_merged.size(), 0u);
96
Austin Schuhe93d8642019-10-13 15:27:07 -070097 EXPECT_EQ(in2, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070098 }
99
100 {
101 // nullptr merged with in1 => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700102 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700103 MergeFlatBuffers<Configuration>(nullptr, fb1.data());
104 ASSERT_NE(fb_merged.size(), 0u);
105
Austin Schuhe93d8642019-10-13 15:27:07 -0700106 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700107 }
108
109 {
110 // in1 merged with nullptr => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700111 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700112 MergeFlatBuffers<Configuration>(fb1.data(), nullptr);
113 ASSERT_NE(fb_merged.size(), 0u);
114
Austin Schuhe93d8642019-10-13 15:27:07 -0700115 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700116 }
117
118 {
119 // in1 merged with in2 => out.
Austin Schuhe93d8642019-10-13 15:27:07 -0700120 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700121 MergeFlatBuffers<Configuration>(fb1.data(), fb2.data());
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700122
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800123 ExpectMergedOutput(fb_merged, out);
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700124 }
125
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800126 // Test all the different merge methods:
127 ExpectMergedOutput(
128 MergeFlatBuffers(ConfigurationTypeTable(), fb1.data(), fb2.data()),
129 out);
130 {
131 flatbuffers::FlatBufferBuilder fbb;
132 fbb.ForceDefaults(1);
133 fbb.Finish(MergeFlatBuffers(
134 ConfigurationTypeTable(),
135 flatbuffers::GetRoot<flatbuffers::Table>(fb1.data()),
136 flatbuffers::GetRoot<flatbuffers::Table>(fb2.data()), &fbb));
137 ExpectMergedOutput(fbb.Release(), out);
138 }
139 {
140 flatbuffers::FlatBufferBuilder fbb;
141 fbb.ForceDefaults(1);
142 fbb.Finish(MergeFlatBuffers<Configuration>(
143 flatbuffers::GetRoot<flatbuffers::Table>(fb1.data()),
144 flatbuffers::GetRoot<flatbuffers::Table>(fb2.data()), &fbb));
145 ExpectMergedOutput(fbb.Release(), out);
146 }
147 ExpectMergedOutput(MergeFlatBuffers<Configuration>(fb1.data(), fb2.data()),
148 out);
149 ExpectMergedOutput(MergeFlatBuffers<Configuration>(fb1, fb2), out);
150 ExpectMergedOutput(MergeFlatBuffers<Configuration>(
151 flatbuffers::GetRoot<Configuration>(fb1.data()),
152 flatbuffers::GetRoot<Configuration>(fb2.data()))
153 .buffer(),
154 out);
155
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700156 // Now, to make things extra exciting, nest a config inside a config. And
157 // run all the tests. This will exercise some fun nested merges and copies.
158
159 {
160 // in1_nested merged with "" => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700161 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700162 MergeFlatBuffers<Configuration>(fb1_nested.data(), empty.data());
163 ASSERT_NE(fb_merged.size(), 0u);
164
165 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700166 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700167 }
168
169 {
170 // in2_nested merged with "" => in2_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700171 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700172 MergeFlatBuffers<Configuration>(fb2_nested.data(), empty.data());
173 ASSERT_NE(fb_merged.size(), 0u);
174
175 EXPECT_EQ(in2_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700176 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700177 }
178
179 {
180 // "" merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700181 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700182 MergeFlatBuffers<Configuration>(empty.data(), fb1_nested.data());
183 ASSERT_NE(fb_merged.size(), 0u);
184
185 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700186 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700187 }
188
189 {
190 // "" merged with in2_nested => in2_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700191 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700192 MergeFlatBuffers<Configuration>(empty.data(), fb2_nested.data());
193 ASSERT_NE(fb_merged.size(), 0u);
194
195 EXPECT_EQ(in2_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700196 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700197 }
198
199 {
200 // nullptr merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700201 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700202 MergeFlatBuffers<Configuration>(nullptr, fb1_nested.data());
203 ASSERT_NE(fb_merged.size(), 0u);
204
205 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700206 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700207 }
208
209 {
210 // nullptr merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700211 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700212 MergeFlatBuffers<Configuration>(fb1_nested.data(), nullptr);
213 ASSERT_NE(fb_merged.size(), 0u);
214
215 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700216 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700217 }
218
219 {
220 // in1_nested merged with in2_nested => out_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700221 flatbuffers::DetachedBuffer fb_merged =
222 MergeFlatBuffers<Configuration>(fb1_nested, fb2_nested);
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700223 ASSERT_NE(fb_merged.size(), 0u);
224
225 EXPECT_EQ(out_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700226 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700227 }
228 }
229};
230
231// Test the easy ones. Test every type, single, no nesting.
232TEST_F(FlatbufferMerge, Basic) {
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800233 JsonMerge("{ }", "{ }", "{ }");
234
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700235 JsonMerge("{ \"foo_bool\": true }", "{ \"foo_bool\": false }",
236 "{ \"foo_bool\": false }");
237
238 JsonMerge("{ \"foo_bool\": false }", "{ \"foo_bool\": true }",
239 "{ \"foo_bool\": true }");
240
241 JsonMerge("{ \"foo_byte\": 5 }", "{ \"foo_byte\": -7 }",
242 "{ \"foo_byte\": -7 }");
243
244 JsonMerge("{ \"foo_ubyte\": 5 }", "{ \"foo_ubyte\": 7 }",
245 "{ \"foo_ubyte\": 7 }");
246
247 JsonMerge("{ \"foo_short\": 5 }", "{ \"foo_short\": 7 }",
248 "{ \"foo_short\": 7 }");
249
250 JsonMerge("{ \"foo_int\": 5 }", "{ \"foo_int\": 7 }", "{ \"foo_int\": 7 }");
251
252 JsonMerge("{ \"foo_uint\": 5 }", "{ \"foo_uint\": 7 }",
253 "{ \"foo_uint\": 7 }");
254
255 JsonMerge("{ \"foo_long\": 5 }", "{ \"foo_long\": 7 }",
256 "{ \"foo_long\": 7 }");
257
258 JsonMerge("{ \"foo_ulong\": 5 }", "{ \"foo_ulong\": 7 }",
259 "{ \"foo_ulong\": 7 }");
260
261 JsonMerge("{ \"foo_float\": 5.0 }", "{ \"foo_float\": 7.1 }",
262 "{ \"foo_float\": 7.1 }");
263
264 JsonMerge("{ \"foo_double\": 5.0 }", "{ \"foo_double\": 7.1 }",
265 "{ \"foo_double\": 7.1 }");
266}
267
268// Test arrays of simple types.
269TEST_F(FlatbufferMerge, Array) {
270 JsonMerge("{ \"foo_string\": \"baz\" }", "{ \"foo_string\": \"bar\" }",
271 "{ \"foo_string\": \"bar\" }");
272
273 JsonMerge("{ \"vector_foo_bool\": [ true, true, false ] }",
274 "{ \"vector_foo_bool\": [ false, true, true, false ] }",
275 "{ \"vector_foo_bool\": [ true, true, false, false, "
276 "true, true, false ] }");
277
278 JsonMerge("{ \"vector_foo_byte\": [ 9, 7, 1 ] }",
279 "{ \"vector_foo_byte\": [ -3, 1, 3, 2 ] }",
280 "{ \"vector_foo_byte\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
281
282 JsonMerge("{ \"vector_foo_ubyte\": [ 9, 7, 1 ] }",
283 "{ \"vector_foo_ubyte\": [ 3, 1, 3, 2 ] }",
284 "{ \"vector_foo_ubyte\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
285
286 JsonMerge("{ \"vector_foo_short\": [ 9, 7, 1 ] }",
287 "{ \"vector_foo_short\": [ -3, 1, 3, 2 ] }",
288 "{ \"vector_foo_short\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
289
290 JsonMerge("{ \"vector_foo_ushort\": [ 9, 7, 1 ] }",
291 "{ \"vector_foo_ushort\": [ 3, 1, 3, 2 ] }",
292 "{ \"vector_foo_ushort\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
293
294 JsonMerge("{ \"vector_foo_int\": [ 9, 7, 1 ] }",
295 "{ \"vector_foo_int\": [ -3, 1, 3, 2 ] }",
296 "{ \"vector_foo_int\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
297
298 JsonMerge("{ \"vector_foo_uint\": [ 9, 7, 1 ] }",
299 "{ \"vector_foo_uint\": [ 3, 1, 3, 2 ] }",
300 "{ \"vector_foo_uint\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
301
302 JsonMerge("{ \"vector_foo_long\": [ 9, 7, 1 ] }",
303 "{ \"vector_foo_long\": [ -3, 1, 3, 2 ] }",
304 "{ \"vector_foo_long\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
305
306 JsonMerge("{ \"vector_foo_ulong\": [ 9, 7, 1 ] }",
307 "{ \"vector_foo_ulong\": [ 3, 1, 3, 2 ] }",
308 "{ \"vector_foo_ulong\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
309
310 JsonMerge("{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ] }",
311 "{ \"vector_foo_float\": [ -3.0, 1.3, 3.0, 2.0 ] }",
312 "{ \"vector_foo_float\": [ 9.0, 7.0, 1.0, -3.0, 1.3, 3.0, 2.0 ] }");
313
Austin Schuhe93d8642019-10-13 15:27:07 -0700314 JsonMerge(
315 "{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \" ] }",
316 "{ \"vector_foo_string\": [ \"31\", \"32\" ] }",
317 "{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \", \"31\", \"32\" ] }");
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700318}
319
320// Test nested messages, and arrays of nested messages.
321TEST_F(FlatbufferMerge, NestedStruct) {
322 JsonMerge(
323 "{ \"single_application\": { \"name\": \"woot\" } }",
324 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
325 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }");
326
327 JsonMerge(
328 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
329 "{ \"single_application\": { \"name\": \"woot\" } }",
330 "{ \"single_application\": { \"name\": \"woot\", \"priority\": 7 } }");
331
332 JsonMerge("{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" } ] }",
333 "{ \"apps\": [ { \"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }",
334 "{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" }, { "
335 "\"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }");
336}
337
338// TODO(austin): enums
339// TODO(austin): unions
340// TODO(austin): struct
341
342} // namespace testing
343} // namespace aos