blob: f102db95a79badb96c76f3eb0deaef593ae1478c [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
16 void JsonMerge(const ::std::string in1, const ::std::string in2,
17 const ::std::string out) {
18 printf("Merging: %s\n", in1.c_str());
19 printf("Merging: %s\n", in2.c_str());
20 const ::std::vector<uint8_t> fb1 = JsonToFlatbuffer(
21 static_cast<const char *>(in1.c_str()), ConfigurationTypeTable());
22
23 const ::std::string in1_nested = "{ \"nested_config\": " + in1 + " }";
24 const ::std::vector<uint8_t> fb1_nested = JsonToFlatbuffer(
25 static_cast<const char *>(in1_nested.c_str()),
26 ConfigurationTypeTable());
27
28 const ::std::vector<uint8_t> fb2 = JsonToFlatbuffer(
29 static_cast<const char *>(in2.c_str()), ConfigurationTypeTable());
30
31 const ::std::string in2_nested = "{ \"nested_config\": " + in2 + " }";
32 const ::std::vector<uint8_t> fb2_nested =
33 JsonToFlatbuffer(static_cast<const char *>(in2_nested.c_str()),
34 ConfigurationTypeTable());
35
36 const ::std::string out_nested = "{ \"nested_config\": " + out + " }";
37
38 const ::std::vector<uint8_t> empty =
39 JsonToFlatbuffer("{ }", ConfigurationTypeTable());
40
41 ASSERT_NE(fb1.size(), 0u);
42 ASSERT_NE(fb2.size(), 0u);
43 ASSERT_NE(fb1_nested.size(), 0u);
44 ASSERT_NE(fb2_nested.size(), 0u);
45
46 // We now want to run 7 tests.
47 // in1 merged "" -> in1.
48 // in2 merged "" -> in2.
49 // "" merged in1 -> in1.
50 // "" merged in2 -> in2.
51 // nullptr merged in1 -> in1.
52 // in1 merged nullptr -> in1.
53 // in1 merged in2 -> out.
54
55 {
56 // in1 merged with "" => in1.
57 ::std::vector<uint8_t> fb_merged =
58 MergeFlatBuffers<Configuration>(fb1.data(), empty.data());
59 ASSERT_NE(fb_merged.size(), 0u);
60
61 EXPECT_EQ(in1,
62 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
63 }
64
65 {
66 // in2 merged with "" => in2.
67 ::std::vector<uint8_t> fb_merged =
68 MergeFlatBuffers<Configuration>(fb2.data(), empty.data());
69 ASSERT_NE(fb_merged.size(), 0u);
70
71 EXPECT_EQ(in2,
72 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
73 }
74
75 {
76 // "" merged with in1 => in1.
77 ::std::vector<uint8_t> fb_merged =
78 MergeFlatBuffers<Configuration>(empty.data(), fb1.data());
79 ASSERT_NE(fb_merged.size(), 0u);
80
81 EXPECT_EQ(in1,
82 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
83 }
84
85 {
86 // "" merged with in2 => in2.
87 ::std::vector<uint8_t> fb_merged =
88 MergeFlatBuffers<Configuration>(empty.data(), fb2.data());
89 ASSERT_NE(fb_merged.size(), 0u);
90
91 EXPECT_EQ(in2,
92 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
93 }
94
95 {
96 // nullptr merged with in1 => in1.
97 ::std::vector<uint8_t> fb_merged =
98 MergeFlatBuffers<Configuration>(nullptr, fb1.data());
99 ASSERT_NE(fb_merged.size(), 0u);
100
101 EXPECT_EQ(in1, FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
102 }
103
104 {
105 // in1 merged with nullptr => in1.
106 ::std::vector<uint8_t> fb_merged =
107 MergeFlatBuffers<Configuration>(fb1.data(), nullptr);
108 ASSERT_NE(fb_merged.size(), 0u);
109
110 EXPECT_EQ(in1, FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
111 }
112
113 {
114 // in1 merged with in2 => out.
115 ::std::vector<uint8_t> fb_merged =
116 MergeFlatBuffers<Configuration>(fb1.data(), fb2.data());
117 ASSERT_NE(fb_merged.size(), 0u);
118
119 const ::std::string merged_output =
120 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable());
121 EXPECT_EQ(out, merged_output);
122
123 printf("Merged to: %s\n", merged_output.c_str());
124 }
125
126 // Now, to make things extra exciting, nest a config inside a config. And
127 // run all the tests. This will exercise some fun nested merges and copies.
128
129 {
130 // in1_nested merged with "" => in1.
131 ::std::vector<uint8_t> fb_merged =
132 MergeFlatBuffers<Configuration>(fb1_nested.data(), empty.data());
133 ASSERT_NE(fb_merged.size(), 0u);
134
135 EXPECT_EQ(in1_nested,
136 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
137 }
138
139 {
140 // in2_nested merged with "" => in2_nested.
141 ::std::vector<uint8_t> fb_merged =
142 MergeFlatBuffers<Configuration>(fb2_nested.data(), empty.data());
143 ASSERT_NE(fb_merged.size(), 0u);
144
145 EXPECT_EQ(in2_nested,
146 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
147 }
148
149 {
150 // "" merged with in1_nested => in1_nested.
151 ::std::vector<uint8_t> fb_merged =
152 MergeFlatBuffers<Configuration>(empty.data(), fb1_nested.data());
153 ASSERT_NE(fb_merged.size(), 0u);
154
155 EXPECT_EQ(in1_nested,
156 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
157 }
158
159 {
160 // "" merged with in2_nested => in2_nested.
161 ::std::vector<uint8_t> fb_merged =
162 MergeFlatBuffers<Configuration>(empty.data(), fb2_nested.data());
163 ASSERT_NE(fb_merged.size(), 0u);
164
165 EXPECT_EQ(in2_nested,
166 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
167 }
168
169 {
170 // nullptr merged with in1_nested => in1_nested.
171 ::std::vector<uint8_t> fb_merged =
172 MergeFlatBuffers<Configuration>(nullptr, fb1_nested.data());
173 ASSERT_NE(fb_merged.size(), 0u);
174
175 EXPECT_EQ(in1_nested,
176 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
177 }
178
179 {
180 // nullptr merged with in1_nested => in1_nested.
181 ::std::vector<uint8_t> fb_merged =
182 MergeFlatBuffers<Configuration>(fb1_nested.data(), nullptr);
183 ASSERT_NE(fb_merged.size(), 0u);
184
185 EXPECT_EQ(in1_nested,
186 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
187 }
188
189 {
190 // in1_nested merged with in2_nested => out_nested.
191 ::std::vector<uint8_t> fb_merged =
192 MergeFlatBuffers<Configuration>(fb1_nested.data(), fb2_nested.data());
193 ASSERT_NE(fb_merged.size(), 0u);
194
195 EXPECT_EQ(out_nested,
196 FlatbufferToJson(fb_merged.data(), ConfigurationTypeTable()));
197 }
198 }
199};
200
201// Test the easy ones. Test every type, single, no nesting.
202TEST_F(FlatbufferMerge, Basic) {
203 JsonMerge("{ \"foo_bool\": true }", "{ \"foo_bool\": false }",
204 "{ \"foo_bool\": false }");
205
206 JsonMerge("{ \"foo_bool\": false }", "{ \"foo_bool\": true }",
207 "{ \"foo_bool\": true }");
208
209 JsonMerge("{ \"foo_byte\": 5 }", "{ \"foo_byte\": -7 }",
210 "{ \"foo_byte\": -7 }");
211
212 JsonMerge("{ \"foo_ubyte\": 5 }", "{ \"foo_ubyte\": 7 }",
213 "{ \"foo_ubyte\": 7 }");
214
215 JsonMerge("{ \"foo_short\": 5 }", "{ \"foo_short\": 7 }",
216 "{ \"foo_short\": 7 }");
217
218 JsonMerge("{ \"foo_int\": 5 }", "{ \"foo_int\": 7 }", "{ \"foo_int\": 7 }");
219
220 JsonMerge("{ \"foo_uint\": 5 }", "{ \"foo_uint\": 7 }",
221 "{ \"foo_uint\": 7 }");
222
223 JsonMerge("{ \"foo_long\": 5 }", "{ \"foo_long\": 7 }",
224 "{ \"foo_long\": 7 }");
225
226 JsonMerge("{ \"foo_ulong\": 5 }", "{ \"foo_ulong\": 7 }",
227 "{ \"foo_ulong\": 7 }");
228
229 JsonMerge("{ \"foo_float\": 5.0 }", "{ \"foo_float\": 7.1 }",
230 "{ \"foo_float\": 7.1 }");
231
232 JsonMerge("{ \"foo_double\": 5.0 }", "{ \"foo_double\": 7.1 }",
233 "{ \"foo_double\": 7.1 }");
234}
235
236// Test arrays of simple types.
237TEST_F(FlatbufferMerge, Array) {
238 JsonMerge("{ \"foo_string\": \"baz\" }", "{ \"foo_string\": \"bar\" }",
239 "{ \"foo_string\": \"bar\" }");
240
241 JsonMerge("{ \"vector_foo_bool\": [ true, true, false ] }",
242 "{ \"vector_foo_bool\": [ false, true, true, false ] }",
243 "{ \"vector_foo_bool\": [ true, true, false, false, "
244 "true, true, false ] }");
245
246 JsonMerge("{ \"vector_foo_byte\": [ 9, 7, 1 ] }",
247 "{ \"vector_foo_byte\": [ -3, 1, 3, 2 ] }",
248 "{ \"vector_foo_byte\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
249
250 JsonMerge("{ \"vector_foo_ubyte\": [ 9, 7, 1 ] }",
251 "{ \"vector_foo_ubyte\": [ 3, 1, 3, 2 ] }",
252 "{ \"vector_foo_ubyte\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
253
254 JsonMerge("{ \"vector_foo_short\": [ 9, 7, 1 ] }",
255 "{ \"vector_foo_short\": [ -3, 1, 3, 2 ] }",
256 "{ \"vector_foo_short\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
257
258 JsonMerge("{ \"vector_foo_ushort\": [ 9, 7, 1 ] }",
259 "{ \"vector_foo_ushort\": [ 3, 1, 3, 2 ] }",
260 "{ \"vector_foo_ushort\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
261
262 JsonMerge("{ \"vector_foo_int\": [ 9, 7, 1 ] }",
263 "{ \"vector_foo_int\": [ -3, 1, 3, 2 ] }",
264 "{ \"vector_foo_int\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
265
266 JsonMerge("{ \"vector_foo_uint\": [ 9, 7, 1 ] }",
267 "{ \"vector_foo_uint\": [ 3, 1, 3, 2 ] }",
268 "{ \"vector_foo_uint\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
269
270 JsonMerge("{ \"vector_foo_long\": [ 9, 7, 1 ] }",
271 "{ \"vector_foo_long\": [ -3, 1, 3, 2 ] }",
272 "{ \"vector_foo_long\": [ 9, 7, 1, -3, 1, 3, 2 ] }");
273
274 JsonMerge("{ \"vector_foo_ulong\": [ 9, 7, 1 ] }",
275 "{ \"vector_foo_ulong\": [ 3, 1, 3, 2 ] }",
276 "{ \"vector_foo_ulong\": [ 9, 7, 1, 3, 1, 3, 2 ] }");
277
278 JsonMerge("{ \"vector_foo_float\": [ 9.0, 7.0, 1.0 ] }",
279 "{ \"vector_foo_float\": [ -3.0, 1.3, 3.0, 2.0 ] }",
280 "{ \"vector_foo_float\": [ 9.0, 7.0, 1.0, -3.0, 1.3, 3.0, 2.0 ] }");
281
282 JsonMerge("{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \" ] }",
283 "{ \"vector_foo_string\": [ \"31\", \"32\" ] }",
284 "{ \"vector_foo_string\": [ \"9\", \"7\", \"1 \", \"31\", \"32\" ] }");
285}
286
287// Test nested messages, and arrays of nested messages.
288TEST_F(FlatbufferMerge, NestedStruct) {
289 JsonMerge(
290 "{ \"single_application\": { \"name\": \"woot\" } }",
291 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
292 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }");
293
294 JsonMerge(
295 "{ \"single_application\": { \"name\": \"wow\", \"priority\": 7 } }",
296 "{ \"single_application\": { \"name\": \"woot\" } }",
297 "{ \"single_application\": { \"name\": \"woot\", \"priority\": 7 } }");
298
299 JsonMerge("{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" } ] }",
300 "{ \"apps\": [ { \"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }",
301 "{ \"apps\": [ { \"name\": \"woot\" }, { \"name\": \"wow\" }, { "
302 "\"name\": \"woo2\" }, { \"name\": \"wo3\" } ] }");
303}
304
305// TODO(austin): enums
306// TODO(austin): unions
307// TODO(austin): struct
308
309} // namespace testing
310} // namespace aos