blob: 890a83152214a050fdf61e318161ac1acbdc1117 [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);
Austin Schuh30d7db92020-01-26 16:45:47 -080023
24 aos::FlatbufferDetachedBuffer<Configuration> expected_message(
25 JsonToFlatbuffer(std::string(expected_output).c_str(),
26 ConfigurationTypeTable()));
27 EXPECT_TRUE(
28 CompareFlatBuffer(flatbuffers::GetRoot<Configuration>(fb_merged.data()),
29 &expected_message.message()));
James Kuszmaulf3a3be22020-01-04 12:12:00 -080030 }
31
Austin Schuh09d7ffa2019-10-03 23:43:34 -070032 void JsonMerge(const ::std::string in1, const ::std::string in2,
33 const ::std::string out) {
34 printf("Merging: %s\n", in1.c_str());
35 printf("Merging: %s\n", in2.c_str());
Austin Schuhe93d8642019-10-13 15:27:07 -070036 const flatbuffers::DetachedBuffer fb1 = JsonToFlatbuffer(
Austin Schuh09d7ffa2019-10-03 23:43:34 -070037 static_cast<const char *>(in1.c_str()), ConfigurationTypeTable());
38
39 const ::std::string in1_nested = "{ \"nested_config\": " + in1 + " }";
Austin Schuhe93d8642019-10-13 15:27:07 -070040 const flatbuffers::DetachedBuffer fb1_nested =
41 JsonToFlatbuffer(static_cast<const char *>(in1_nested.c_str()),
42 ConfigurationTypeTable());
Austin Schuh09d7ffa2019-10-03 23:43:34 -070043
Austin Schuhe93d8642019-10-13 15:27:07 -070044 const flatbuffers::DetachedBuffer fb2 = JsonToFlatbuffer(
Austin Schuh09d7ffa2019-10-03 23:43:34 -070045 static_cast<const char *>(in2.c_str()), ConfigurationTypeTable());
46
47 const ::std::string in2_nested = "{ \"nested_config\": " + in2 + " }";
Austin Schuhe93d8642019-10-13 15:27:07 -070048 const flatbuffers::DetachedBuffer fb2_nested =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070049 JsonToFlatbuffer(static_cast<const char *>(in2_nested.c_str()),
50 ConfigurationTypeTable());
51
52 const ::std::string out_nested = "{ \"nested_config\": " + out + " }";
53
Austin Schuhe93d8642019-10-13 15:27:07 -070054 const flatbuffers::DetachedBuffer empty =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070055 JsonToFlatbuffer("{ }", ConfigurationTypeTable());
56
57 ASSERT_NE(fb1.size(), 0u);
58 ASSERT_NE(fb2.size(), 0u);
59 ASSERT_NE(fb1_nested.size(), 0u);
60 ASSERT_NE(fb2_nested.size(), 0u);
61
62 // We now want to run 7 tests.
63 // in1 merged "" -> in1.
64 // in2 merged "" -> in2.
65 // "" merged in1 -> in1.
66 // "" merged in2 -> in2.
67 // nullptr merged in1 -> in1.
68 // in1 merged nullptr -> in1.
69 // in1 merged in2 -> out.
70
71 {
72 // in1 merged with "" => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -070073 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070074 MergeFlatBuffers<Configuration>(fb1.data(), empty.data());
75 ASSERT_NE(fb_merged.size(), 0u);
76
Austin Schuhe93d8642019-10-13 15:27:07 -070077 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070078 }
79
80 {
81 // in2 merged with "" => in2.
Austin Schuhe93d8642019-10-13 15:27:07 -070082 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070083 MergeFlatBuffers<Configuration>(fb2.data(), empty.data());
84 ASSERT_NE(fb_merged.size(), 0u);
85
Austin Schuhe93d8642019-10-13 15:27:07 -070086 EXPECT_EQ(in2, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070087 }
88
89 {
90 // "" merged with in1 => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -070091 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -070092 MergeFlatBuffers<Configuration>(empty.data(), fb1.data());
93 ASSERT_NE(fb_merged.size(), 0u);
94
Austin Schuhe93d8642019-10-13 15:27:07 -070095 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -070096 }
97
98 {
99 // "" merged with in2 => in2.
Austin Schuhe93d8642019-10-13 15:27:07 -0700100 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700101 MergeFlatBuffers<Configuration>(empty.data(), fb2.data());
102 ASSERT_NE(fb_merged.size(), 0u);
103
Austin Schuhe93d8642019-10-13 15:27:07 -0700104 EXPECT_EQ(in2, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700105 }
106
107 {
108 // nullptr merged with in1 => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700109 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700110 MergeFlatBuffers<Configuration>(nullptr, fb1.data());
111 ASSERT_NE(fb_merged.size(), 0u);
112
Austin Schuhe93d8642019-10-13 15:27:07 -0700113 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700114 }
115
116 {
117 // in1 merged with nullptr => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700118 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700119 MergeFlatBuffers<Configuration>(fb1.data(), nullptr);
120 ASSERT_NE(fb_merged.size(), 0u);
121
Austin Schuhe93d8642019-10-13 15:27:07 -0700122 EXPECT_EQ(in1, FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700123 }
124
125 {
126 // in1 merged with in2 => out.
Austin Schuhe93d8642019-10-13 15:27:07 -0700127 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700128 MergeFlatBuffers<Configuration>(fb1.data(), fb2.data());
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700129
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800130 ExpectMergedOutput(fb_merged, out);
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700131 }
132
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800133 // Test all the different merge methods:
134 ExpectMergedOutput(
135 MergeFlatBuffers(ConfigurationTypeTable(), fb1.data(), fb2.data()),
136 out);
137 {
138 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800139 fbb.ForceDefaults(true);
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800140 fbb.Finish(MergeFlatBuffers(
141 ConfigurationTypeTable(),
142 flatbuffers::GetRoot<flatbuffers::Table>(fb1.data()),
143 flatbuffers::GetRoot<flatbuffers::Table>(fb2.data()), &fbb));
144 ExpectMergedOutput(fbb.Release(), out);
145 }
146 {
147 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800148 fbb.ForceDefaults(true);
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800149 fbb.Finish(MergeFlatBuffers<Configuration>(
150 flatbuffers::GetRoot<flatbuffers::Table>(fb1.data()),
151 flatbuffers::GetRoot<flatbuffers::Table>(fb2.data()), &fbb));
152 ExpectMergedOutput(fbb.Release(), out);
153 }
154 ExpectMergedOutput(MergeFlatBuffers<Configuration>(fb1.data(), fb2.data()),
155 out);
156 ExpectMergedOutput(MergeFlatBuffers<Configuration>(fb1, fb2), out);
157 ExpectMergedOutput(MergeFlatBuffers<Configuration>(
158 flatbuffers::GetRoot<Configuration>(fb1.data()),
159 flatbuffers::GetRoot<Configuration>(fb2.data()))
160 .buffer(),
161 out);
162
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700163 // Now, to make things extra exciting, nest a config inside a config. And
164 // run all the tests. This will exercise some fun nested merges and copies.
165
166 {
167 // in1_nested merged with "" => in1.
Austin Schuhe93d8642019-10-13 15:27:07 -0700168 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700169 MergeFlatBuffers<Configuration>(fb1_nested.data(), empty.data());
170 ASSERT_NE(fb_merged.size(), 0u);
171
172 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700173 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700174 }
175
176 {
177 // in2_nested merged with "" => in2_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700178 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700179 MergeFlatBuffers<Configuration>(fb2_nested.data(), empty.data());
180 ASSERT_NE(fb_merged.size(), 0u);
181
182 EXPECT_EQ(in2_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700183 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700184 }
185
186 {
187 // "" merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700188 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700189 MergeFlatBuffers<Configuration>(empty.data(), fb1_nested.data());
190 ASSERT_NE(fb_merged.size(), 0u);
191
192 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700193 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700194 }
195
196 {
197 // "" merged with in2_nested => in2_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700198 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700199 MergeFlatBuffers<Configuration>(empty.data(), fb2_nested.data());
200 ASSERT_NE(fb_merged.size(), 0u);
201
202 EXPECT_EQ(in2_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700203 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700204 }
205
206 {
207 // nullptr merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700208 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700209 MergeFlatBuffers<Configuration>(nullptr, fb1_nested.data());
210 ASSERT_NE(fb_merged.size(), 0u);
211
212 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700213 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700214 }
215
216 {
217 // nullptr merged with in1_nested => in1_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700218 flatbuffers::DetachedBuffer fb_merged =
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700219 MergeFlatBuffers<Configuration>(fb1_nested.data(), nullptr);
220 ASSERT_NE(fb_merged.size(), 0u);
221
222 EXPECT_EQ(in1_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700223 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700224 }
225
226 {
227 // in1_nested merged with in2_nested => out_nested.
Austin Schuhe93d8642019-10-13 15:27:07 -0700228 flatbuffers::DetachedBuffer fb_merged =
229 MergeFlatBuffers<Configuration>(fb1_nested, fb2_nested);
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700230 ASSERT_NE(fb_merged.size(), 0u);
231
232 EXPECT_EQ(out_nested,
Austin Schuhe93d8642019-10-13 15:27:07 -0700233 FlatbufferToJson(fb_merged, ConfigurationTypeTable()));
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700234 }
235 }
236};
237
238// Test the easy ones. Test every type, single, no nesting.
239TEST_F(FlatbufferMerge, Basic) {
James Kuszmaulf3a3be22020-01-04 12:12:00 -0800240 JsonMerge("{ }", "{ }", "{ }");
241
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700242 JsonMerge("{ \"foo_bool\": true }", "{ \"foo_bool\": false }",
243 "{ \"foo_bool\": false }");
244
245 JsonMerge("{ \"foo_bool\": false }", "{ \"foo_bool\": true }",
246 "{ \"foo_bool\": true }");
247
248 JsonMerge("{ \"foo_byte\": 5 }", "{ \"foo_byte\": -7 }",
249 "{ \"foo_byte\": -7 }");
250
251 JsonMerge("{ \"foo_ubyte\": 5 }", "{ \"foo_ubyte\": 7 }",
252 "{ \"foo_ubyte\": 7 }");
253
254 JsonMerge("{ \"foo_short\": 5 }", "{ \"foo_short\": 7 }",
255 "{ \"foo_short\": 7 }");
256
257 JsonMerge("{ \"foo_int\": 5 }", "{ \"foo_int\": 7 }", "{ \"foo_int\": 7 }");
258
259 JsonMerge("{ \"foo_uint\": 5 }", "{ \"foo_uint\": 7 }",
260 "{ \"foo_uint\": 7 }");
261
262 JsonMerge("{ \"foo_long\": 5 }", "{ \"foo_long\": 7 }",
263 "{ \"foo_long\": 7 }");
264
265 JsonMerge("{ \"foo_ulong\": 5 }", "{ \"foo_ulong\": 7 }",
266 "{ \"foo_ulong\": 7 }");
267
268 JsonMerge("{ \"foo_float\": 5.0 }", "{ \"foo_float\": 7.1 }",
269 "{ \"foo_float\": 7.1 }");
270
271 JsonMerge("{ \"foo_double\": 5.0 }", "{ \"foo_double\": 7.1 }",
272 "{ \"foo_double\": 7.1 }");
273}
274
275// Test arrays of simple types.
276TEST_F(FlatbufferMerge, Array) {
277 JsonMerge("{ \"foo_string\": \"baz\" }", "{ \"foo_string\": \"bar\" }",
278 "{ \"foo_string\": \"bar\" }");
279
280 JsonMerge("{ \"vector_foo_bool\": [ true, true, false ] }",
281 "{ \"vector_foo_bool\": [ false, true, true, false ] }",
282 "{ \"vector_foo_bool\": [ true, true, false, false, "
283 "true, true, false ] }");
284
285 JsonMerge("{ \"vector_foo_byte\": [ 9, 7, 1 ] }",
286 "{ \"vector_foo_byte\": [ -3, 1, 3, 2 ] }",
287 "{ \"vector_foo_byte\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
288
289 JsonMerge("{ \"vector_foo_ubyte\": [ 9, 7, 1 ] }",
290 "{ \"vector_foo_ubyte\": [ 3, 1, 3, 2 ] }",
291 "{ \"vector_foo_ubyte\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
292
293 JsonMerge("{ \"vector_foo_short\": [ 9, 7, 1 ] }",
294 "{ \"vector_foo_short\": [ -3, 1, 3, 2 ] }",
295 "{ \"vector_foo_short\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
296
297 JsonMerge("{ \"vector_foo_ushort\": [ 9, 7, 1 ] }",
298 "{ \"vector_foo_ushort\": [ 3, 1, 3, 2 ] }",
299 "{ \"vector_foo_ushort\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
300
301 JsonMerge("{ \"vector_foo_int\": [ 9, 7, 1 ] }",
302 "{ \"vector_foo_int\": [ -3, 1, 3, 2 ] }",
303 "{ \"vector_foo_int\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
304
305 JsonMerge("{ \"vector_foo_uint\": [ 9, 7, 1 ] }",
306 "{ \"vector_foo_uint\": [ 3, 1, 3, 2 ] }",
307 "{ \"vector_foo_uint\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
308
309 JsonMerge("{ \"vector_foo_long\": [ 9, 7, 1 ] }",
310 "{ \"vector_foo_long\": [ -3, 1, 3, 2 ] }",
311 "{ \"vector_foo_long\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
312
313 JsonMerge("{ \"vector_foo_ulong\": [ 9, 7, 1 ] }",
314 "{ \"vector_foo_ulong\": [ 3, 1, 3, 2 ] }",
315 "{ \"vector_foo_ulong\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
316
317 JsonMerge("{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ] }",
318 "{ \"vector_foo_float\": [ -3.0, 1.3, 3.0, 2.0 ] }",
319 "{ \"vector_foo_float\": [ 9.0, 7.0, 1.0, -3.0, 1.3, 3.0, 2.0 ] }");
320
Austin Schuhe93d8642019-10-13 15:27:07 -0700321 JsonMerge(
322 "{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \" ] }",
323 "{ \"vector_foo_string\": [ \"31\", \"32\" ] }",
324 "{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \", \"31\", \"32\" ] }");
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700325}
326
327// Test nested messages, and arrays of nested messages.
328TEST_F(FlatbufferMerge, NestedStruct) {
329 JsonMerge(
330 "{ \"single_application\": { \"name\": \"woot\" } }",
331 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
332 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }");
333
334 JsonMerge(
335 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
336 "{ \"single_application\": { \"name\": \"woot\" } }",
337 "{ \"single_application\": { \"name\": \"woot\", \"priority\": 7 } }");
338
339 JsonMerge("{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" } ] }",
340 "{ \"apps\": [ { \"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }",
341 "{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" }, { "
342 "\"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }");
343}
344
Austin Schuh30d7db92020-01-26 16:45:47 -0800345// Tests a compare of 2 basic (different) messages.
346TEST_F(FlatbufferMerge, CompareDifferent) {
347 aos::FlatbufferDetachedBuffer<Configuration> message1(JsonToFlatbuffer(
348 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
349 ConfigurationTypeTable()));
350 aos::FlatbufferDetachedBuffer<Configuration> message2(JsonToFlatbuffer(
351 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 8 } }",
352 ConfigurationTypeTable()));
353
354 EXPECT_FALSE(CompareFlatBuffer(&message1.message(), &message2.message()));
355}
356
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700357// TODO(austin): enums
358// TODO(austin): unions
359// TODO(austin): struct
360
361} // namespace testing
362} // namespace aos