• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <stdint.h>
17 
18 #include <cmath>
19 #include <limits>
20 #include <memory>
21 #include <string>
22 
23 #if defined(__ANDROID__)
24 #define INCLUDE_64_BIT_TESTS 0
25 #else
26 #define INCLUDE_64_BIT_TESTS 1
27 #endif
28 
29 #include "alignment_test.h"
30 #include "evolution_test.h"
31 #include "flatbuffers/flatbuffers.h"
32 #include "flatbuffers/idl.h"
33 #include "flatbuffers/minireflect.h"
34 #include "flatbuffers/reflection_generated.h"
35 #include "flatbuffers/registry.h"
36 #include "flatbuffers/util.h"
37 #include "fuzz_test.h"
38 #include "json_test.h"
39 #include "key_field_test.h"
40 #include "monster_test.h"
41 #include "monster_test_generated.h"
42 #include "native_inline_table_test_generated.h"
43 #include "optional_scalars_test.h"
44 #include "parser_test.h"
45 #include "proto_test.h"
46 #include "reflection_test.h"
47 #include "tests/union_vector/union_vector_generated.h"
48 #include "union_underlying_type_test_generated.h"
49 #if !defined(_MSC_VER) || _MSC_VER >= 1700
50 #  include "tests/arrays_test_generated.h"
51 #endif
52 #if INCLUDE_64_BIT_TESTS
53 #include "tests/64bit/offset64_test.h"
54 #endif
55 #include "flexbuffers_test.h"
56 #include "is_quiet_nan.h"
57 #include "monster_test_bfbs_generated.h"  // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed
58 #include "native_type_test_generated.h"
59 #include "test_assert.h"
60 #include "util_test.h"
61 
62 void FlatBufferBuilderTest();
63 
64 namespace flatbuffers {
65 namespace tests {
66 namespace {
67 
68 // clang-format off
69 // Check that char* and uint8_t* are interoperable types.
70 // The reinterpret_cast<> between the pointers are used to simplify data loading.
71 static_assert(flatbuffers::is_same<uint8_t, char>::value ||
72               flatbuffers::is_same<uint8_t, unsigned char>::value,
73               "unexpected uint8_t type");
74 
75 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
76   // Ensure IEEE-754 support if tests of floats with NaN/Inf will run.
77   static_assert(std::numeric_limits<float>::is_iec559 &&
78                 std::numeric_limits<double>::is_iec559,
79                 "IEC-559 (IEEE-754) standard required");
80 #endif
81 // clang-format on
82 
83 using namespace MyGame::Example;
84 
TriviallyCopyableTest()85 void TriviallyCopyableTest() {
86   // clang-format off
87   #if __GNUG__ && __GNUC__ < 5 && \
88       !(defined(__clang__) && __clang_major__ >= 16)
89     TEST_EQ(__is_trivially_copyable(Vec3), true);
90   #else
91     #if __cplusplus >= 201103L
92       TEST_EQ(std::is_trivially_copyable<Vec3>::value, true);
93     #endif
94   #endif
95   // clang-format on
96 }
97 
98 // Guard against -Wunused-function on platforms without file tests.
99 #ifndef FLATBUFFERS_NO_FILE_TESTS
GenerateTableTextTest(const std::string & tests_data_path)100 void GenerateTableTextTest(const std::string &tests_data_path) {
101   std::string schemafile;
102   std::string jsonfile;
103   bool ok =
104       flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
105                             false, &schemafile) &&
106       flatbuffers::LoadFile((tests_data_path + "monsterdata_test.json").c_str(),
107                             false, &jsonfile);
108   TEST_EQ(ok, true);
109   auto include_test_path =
110       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
111   const char *include_directories[] = { tests_data_path.c_str(),
112                                         include_test_path.c_str(), nullptr };
113   flatbuffers::IDLOptions opt;
114   opt.indent_step = -1;
115   flatbuffers::Parser parser(opt);
116   ok = parser.Parse(schemafile.c_str(), include_directories) &&
117        parser.Parse(jsonfile.c_str(), include_directories);
118   TEST_EQ(ok, true);
119   // Test root table
120   const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
121   const auto abilities = monster->testarrayofsortedstruct();
122   TEST_EQ(abilities->size(), 3);
123   TEST_EQ(abilities->Get(0)->id(), 0);
124   TEST_EQ(abilities->Get(0)->distance(), 45);
125   TEST_EQ(abilities->Get(1)->id(), 1);
126   TEST_EQ(abilities->Get(1)->distance(), 21);
127   TEST_EQ(abilities->Get(2)->id(), 5);
128   TEST_EQ(abilities->Get(2)->distance(), 12);
129 
130   std::string jsongen;
131   auto result = GenTextFromTable(parser, monster, "MyGame.Example.Monster",
132                                       &jsongen);
133   TEST_NULL(result);
134   // Test sub table
135   const Vec3 *pos = monster->pos();
136   jsongen.clear();
137   result = GenTextFromTable(parser, pos, "MyGame.Example.Vec3", &jsongen);
138   TEST_NULL(result);
139   TEST_EQ_STR(
140       jsongen.c_str(),
141       "{x: 1.0,y: 2.0,z: 3.0,test1: 3.0,test2: \"Green\",test3: {a: 5,b: 6}}");
142   const Test &test3 = pos->test3();
143   jsongen.clear();
144   result =
145       GenTextFromTable(parser, &test3, "MyGame.Example.Test", &jsongen);
146   TEST_NULL(result);
147   TEST_EQ_STR(jsongen.c_str(), "{a: 5,b: 6}");
148   const Test *test4 = monster->test4()->Get(0);
149   jsongen.clear();
150   result =
151       GenTextFromTable(parser, test4, "MyGame.Example.Test", &jsongen);
152   TEST_NULL(result);
153   TEST_EQ_STR(jsongen.c_str(), "{a: 10,b: 20}");
154 }
155 
MultiFileNameClashTest(const std::string & tests_data_path)156 void MultiFileNameClashTest(const std::string &tests_data_path) {
157   const auto name_clash_path =
158       flatbuffers::ConCatPathFileName(tests_data_path, "name_clash_test");
159   const char *include_directories[] = { name_clash_path.c_str() };
160 
161   // Load valid 2 file Flatbuffer schema
162   const auto valid_path =
163       flatbuffers::ConCatPathFileName(name_clash_path, "valid_test1.fbs");
164   std::string valid_schema;
165   TEST_ASSERT(flatbuffers::LoadFile(valid_path.c_str(), false, &valid_schema));
166   // Clashing table and union names in different namespaces must be parsable
167   TEST_ASSERT(
168       flatbuffers::Parser().Parse(valid_schema.c_str(), include_directories));
169 
170   flatbuffers::Parser p;
171   TEST_ASSERT(p.Parse(valid_schema.c_str(), include_directories));
172 
173   // Load invalid 2 file Flatbuffer schema
174   const auto invalid_path =
175       flatbuffers::ConCatPathFileName(name_clash_path, "invalid_test1.fbs");
176   std::string invalid_schema;
177   TEST_ASSERT(
178       flatbuffers::LoadFile(invalid_path.c_str(), false, &invalid_schema));
179   // Clashing table and union names in same namespace must fail to parse
180   TEST_EQ(
181       flatbuffers::Parser().Parse(invalid_schema.c_str(), include_directories),
182       false);
183 }
184 
InvalidNestedFlatbufferTest(const std::string & tests_data_path)185 void InvalidNestedFlatbufferTest(const std::string &tests_data_path) {
186   // First, load and parse FlatBuffer schema (.fbs)
187   std::string schemafile;
188   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
189                                 false, &schemafile),
190           true);
191   auto include_test_path =
192       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
193   const char *include_directories[] = { tests_data_path.c_str(),
194                                         include_test_path.c_str(), nullptr };
195   flatbuffers::Parser parser1;
196   TEST_EQ(parser1.Parse(schemafile.c_str(), include_directories), true);
197 
198   // "color" inside nested flatbuffer contains invalid enum value
199   TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: "
200                         "\"Leela\", color: \"nonexistent\"}}"),
201           false);
202 }
203 
UnionVectorTest(const std::string & tests_data_path)204 void UnionVectorTest(const std::string &tests_data_path) {
205   // load FlatBuffer fbs schema and json.
206   std::string schemafile, jsonfile;
207   TEST_EQ(flatbuffers::LoadFile(
208               (tests_data_path + "union_vector/union_vector.fbs").c_str(),
209               false, &schemafile),
210           true);
211   TEST_EQ(flatbuffers::LoadFile(
212               (tests_data_path + "union_vector/union_vector.json").c_str(),
213               false, &jsonfile),
214           true);
215 
216   // parse schema.
217   flatbuffers::IDLOptions idl_opts;
218   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
219   flatbuffers::Parser parser(idl_opts);
220   TEST_EQ(parser.Parse(schemafile.c_str()), true);
221 
222   flatbuffers::FlatBufferBuilder fbb;
223 
224   // union types.
225   std::vector<uint8_t> types;
226   types.push_back(static_cast<uint8_t>(Character_Belle));
227   types.push_back(static_cast<uint8_t>(Character_MuLan));
228   types.push_back(static_cast<uint8_t>(Character_BookFan));
229   types.push_back(static_cast<uint8_t>(Character_Other));
230   types.push_back(static_cast<uint8_t>(Character_Unused));
231 
232   // union values.
233   std::vector<flatbuffers::Offset<void>> characters;
234   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
235   characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
236   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
237   characters.push_back(fbb.CreateString("Other").Union());
238   characters.push_back(fbb.CreateString("Unused").Union());
239 
240   // create Movie.
241   const auto movie_offset =
242       CreateMovie(fbb, Character_Rapunzel,
243                   fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
244                   fbb.CreateVector(types), fbb.CreateVector(characters));
245   FinishMovieBuffer(fbb, movie_offset);
246 
247   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
248   TEST_EQ(VerifyMovieBuffer(verifier), true);
249 
250   auto flat_movie = GetMovie(fbb.GetBufferPointer());
251 
252   auto TestMovie = [](const Movie *movie) {
253     TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
254 
255     auto cts = movie->characters_type();
256     TEST_EQ(movie->characters_type()->size(), 5);
257     TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
258     TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
259     TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
260     TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
261     TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
262 
263     auto rapunzel = movie->main_character_as_Rapunzel();
264     TEST_NOTNULL(rapunzel);
265     TEST_EQ(rapunzel->hair_length(), 6);
266 
267     auto cs = movie->characters();
268     TEST_EQ(cs->size(), 5);
269     auto belle = cs->GetAs<BookReader>(0);
270     TEST_EQ(belle->books_read(), 7);
271     auto mu_lan = cs->GetAs<Attacker>(1);
272     TEST_EQ(mu_lan->sword_attack_damage(), 5);
273     auto book_fan = cs->GetAs<BookReader>(2);
274     TEST_EQ(book_fan->books_read(), 2);
275     auto other = cs->GetAsString(3);
276     TEST_EQ_STR(other->c_str(), "Other");
277     auto unused = cs->GetAsString(4);
278     TEST_EQ_STR(unused->c_str(), "Unused");
279   };
280 
281   TestMovie(flat_movie);
282 
283   // Also test the JSON we loaded above.
284   TEST_EQ(parser.Parse(jsonfile.c_str()), true);
285   auto jbuf = parser.builder_.GetBufferPointer();
286   flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
287   TEST_EQ(VerifyMovieBuffer(jverifier), true);
288   TestMovie(GetMovie(jbuf));
289 
290   auto movie_object = flat_movie->UnPack();
291   TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
292   TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
293   TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
294   TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
295   TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
296   TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
297 
298   fbb.Clear();
299   fbb.Finish(Movie::Pack(fbb, movie_object));
300 
301   delete movie_object;
302 
303   auto repacked_movie = GetMovie(fbb.GetBufferPointer());
304 
305   TestMovie(repacked_movie);
306 
307   // Generate text using mini-reflection.
308   auto s =
309       flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
310   TEST_EQ_STR(
311       s.c_str(),
312       "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
313       "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
314       "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
315       "{ books_read: 2 }, \"Other\", \"Unused\" ] }");
316 
317   flatbuffers::ToStringVisitor visitor("\n", true, "  ");
318   IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor);
319   TEST_EQ_STR(visitor.s.c_str(),
320               "{\n"
321               "  \"main_character_type\": \"Rapunzel\",\n"
322               "  \"main_character\": {\n"
323               "    \"hair_length\": 6\n"
324               "  },\n"
325               "  \"characters_type\": [\n"
326               "    \"Belle\",\n"
327               "    \"MuLan\",\n"
328               "    \"BookFan\",\n"
329               "    \"Other\",\n"
330               "    \"Unused\"\n"
331               "  ],\n"
332               "  \"characters\": [\n"
333               "    {\n"
334               "      \"books_read\": 7\n"
335               "    },\n"
336               "    {\n"
337               "      \"sword_attack_damage\": 5\n"
338               "    },\n"
339               "    {\n"
340               "      \"books_read\": 2\n"
341               "    },\n"
342               "    \"Other\",\n"
343               "    \"Unused\"\n"
344               "  ]\n"
345               "}");
346 
347   // Generate text using parsed schema.
348   std::string jsongen;
349   auto result = GenText(parser, fbb.GetBufferPointer(), &jsongen);
350   TEST_NULL(result);
351   TEST_EQ_STR(jsongen.c_str(),
352               "{\n"
353               "  main_character_type: \"Rapunzel\",\n"
354               "  main_character: {\n"
355               "    hair_length: 6\n"
356               "  },\n"
357               "  characters_type: [\n"
358               "    \"Belle\",\n"
359               "    \"MuLan\",\n"
360               "    \"BookFan\",\n"
361               "    \"Other\",\n"
362               "    \"Unused\"\n"
363               "  ],\n"
364               "  characters: [\n"
365               "    {\n"
366               "      books_read: 7\n"
367               "    },\n"
368               "    {\n"
369               "      sword_attack_damage: 5\n"
370               "    },\n"
371               "    {\n"
372               "      books_read: 2\n"
373               "    },\n"
374               "    \"Other\",\n"
375               "    \"Unused\"\n"
376               "  ]\n"
377               "}\n");
378 
379   // Simple test with reflection.
380   parser.Serialize();
381   auto schema = reflection::GetSchema(parser.builder_.GetBufferPointer());
382   auto ok = flatbuffers::Verify(*schema, *schema->root_table(),
383                                 fbb.GetBufferPointer(), fbb.GetSize());
384   TEST_EQ(ok, true);
385 
386   flatbuffers::Parser parser2(idl_opts);
387   TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
388                         "union Any { Bool }"
389                         "table Root { a:Any; }"
390                         "root_type Root;"),
391           true);
392   TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
393 }
394 #endif
395 
EndianSwapTest()396 void EndianSwapTest() {
397   TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
398   TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
399           0x78563412);
400   TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
401           0xEFCDAB9078563412);
402   TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
403 }
404 
UninitializedVectorTest()405 void UninitializedVectorTest() {
406   flatbuffers::FlatBufferBuilder builder;
407 
408   Test *buf = nullptr;
409   auto vector_offset =
410       builder.CreateUninitializedVectorOfStructs<Test>(2, &buf);
411   TEST_NOTNULL(buf);
412   buf[0] = Test(10, 20);
413   buf[1] = Test(30, 40);
414 
415   auto required_name = builder.CreateString("myMonster");
416   auto monster_builder = MonsterBuilder(builder);
417   monster_builder.add_name(
418       required_name);  // required field mandated for monster.
419   monster_builder.add_test4(vector_offset);
420   builder.Finish(monster_builder.Finish());
421 
422   auto p = builder.GetBufferPointer();
423   auto uvt = flatbuffers::GetRoot<Monster>(p);
424   TEST_NOTNULL(uvt);
425   auto vec = uvt->test4();
426   TEST_NOTNULL(vec);
427   auto test_0 = vec->Get(0);
428   auto test_1 = vec->Get(1);
429   TEST_EQ(test_0->a(), 10);
430   TEST_EQ(test_0->b(), 20);
431   TEST_EQ(test_1->a(), 30);
432   TEST_EQ(test_1->b(), 40);
433 }
434 
EqualOperatorTest()435 void EqualOperatorTest() {
436   MonsterT a;
437   MonsterT b;
438   // We have to reset the fields that are NaN to zero to allow the equality
439   // to evaluate to true.
440   TEST_EQ(std::isnan(a.nan_default), true);
441   TEST_EQ(std::isnan(b.nan_default), true);
442   a.nan_default = 0;
443   b.nan_default = 0;
444   TEST_EQ(b == a, true);
445   TEST_EQ(b != a, false);
446 
447   b.mana = 33;
448   TEST_EQ(b == a, false);
449   TEST_EQ(b != a, true);
450   b.mana = 150;
451   TEST_EQ(b == a, true);
452   TEST_EQ(b != a, false);
453 
454   b.inventory.push_back(3);
455   TEST_EQ(b == a, false);
456   TEST_EQ(b != a, true);
457   b.inventory.clear();
458   TEST_EQ(b == a, true);
459   TEST_EQ(b != a, false);
460 
461   a.enemy.reset(new MonsterT());
462   a.enemy->nan_default = 0;
463   TEST_EQ(b != a, true);
464   a.enemy->mana = 33;
465   TEST_EQ(b == a, false);
466   TEST_EQ(b != a, true);
467 
468   b.enemy.reset(new MonsterT());
469   b.enemy->nan_default = 0;
470   TEST_EQ(b == a, false);
471   TEST_EQ(b != a, true);
472   b.enemy->mana = 33;
473   TEST_EQ(b == a, true);
474   TEST_EQ(b != a, false);
475 
476   a.enemy.reset(nullptr);
477   TEST_EQ(b == a, false);
478   TEST_EQ(b != a, true);
479   b.enemy->mana = 150;
480   TEST_EQ(b == a, false);
481   TEST_EQ(b != a, true);
482   a.enemy.reset(new MonsterT());
483   a.enemy->nan_default = 0;
484   TEST_EQ(b == a, true);
485   TEST_EQ(b != a, false);
486 
487   b.enemy.reset(nullptr);
488 
489   b.test.type = Any_Monster;
490   TEST_EQ(b == a, false);
491   TEST_EQ(b != a, true);
492 
493   // Test that vector of tables are compared by value and not by reference.
494   {
495     // Two tables are equal by default.
496     MonsterT a, b;
497     a.nan_default = 0;
498     b.nan_default = 0;
499     TEST_EQ(a == b, true);
500 
501     // Adding only a table to one of the monster vectors should make it not
502     // equal (due to size mistmatch).
503     a.testarrayoftables.push_back(
504         flatbuffers::unique_ptr<MonsterT>(new MonsterT));
505     a.testarrayoftables.back()->nan_default = 0;
506     TEST_EQ(a == b, false);
507 
508     // Adding an equalivant table to the other monster vector should make it
509     // equal again.
510     b.testarrayoftables.push_back(
511         flatbuffers::unique_ptr<MonsterT>(new MonsterT));
512     b.testarrayoftables.back()->nan_default = 0;
513     TEST_EQ(a == b, true);
514 
515     // Create two new monsters that are different.
516     auto c = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
517     auto d = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
518     c->nan_default = 0;
519     d->nan_default = 0;
520     c->hp = 1;
521     d->hp = 2;
522     TEST_EQ(c == d, false);
523 
524     // Adding them to the original monsters should also make them different.
525     a.testarrayoftables.push_back(std::move(c));
526     b.testarrayoftables.push_back(std::move(d));
527     TEST_EQ(a == b, false);
528 
529     // Remove the mismatching monsters to get back to equality
530     a.testarrayoftables.pop_back();
531     b.testarrayoftables.pop_back();
532     TEST_EQ(a == b, true);
533 
534     // Check that nullptr are OK.
535     a.testarrayoftables.push_back(nullptr);
536     b.testarrayoftables.push_back(
537         flatbuffers::unique_ptr<MonsterT>(new MonsterT));
538     TEST_EQ(a == b, false);
539   }
540 }
541 
CreateSharedStringTest()542 void CreateSharedStringTest() {
543   flatbuffers::FlatBufferBuilder builder;
544   const auto one1 = builder.CreateSharedString("one");
545   const auto two = builder.CreateSharedString("two");
546   const auto one2 = builder.CreateSharedString("one");
547   TEST_EQ(one1.o, one2.o);
548   const auto onetwo = builder.CreateSharedString("onetwo");
549   TEST_EQ(onetwo.o != one1.o, true);
550   TEST_EQ(onetwo.o != two.o, true);
551 
552   // Support for embedded nulls
553   const char chars_b[] = { 'a', '\0', 'b' };
554   const char chars_c[] = { 'a', '\0', 'c' };
555   const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b));
556   const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c));
557   const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b));
558   TEST_EQ(null_b1.o != null_c.o, true);  // Issue#5058 repro
559   TEST_EQ(null_b1.o, null_b2.o);
560 
561   // Put the strings into an array for round trip verification.
562   std::array<flatbuffers::Offset<flatbuffers::String>, 7> array = {
563     one1, two, one2, onetwo, null_b1, null_c, null_b2
564   };
565   const auto vector_offset =
566       builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(array);
567   MonsterBuilder monster_builder(builder);
568   monster_builder.add_name(two);
569   monster_builder.add_testarrayofstring(vector_offset);
570   builder.Finish(monster_builder.Finish());
571 
572   // Read the Monster back.
573   const auto *monster =
574       flatbuffers::GetRoot<Monster>(builder.GetBufferPointer());
575   TEST_EQ_STR(monster->name()->c_str(), "two");
576   const auto *testarrayofstring = monster->testarrayofstring();
577   TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7));
578   const auto &a = *testarrayofstring;
579   TEST_EQ_STR(a[0]->c_str(), "one");
580   TEST_EQ_STR(a[1]->c_str(), "two");
581   TEST_EQ_STR(a[2]->c_str(), "one");
582   TEST_EQ_STR(a[3]->c_str(), "onetwo");
583   TEST_EQ(a[4]->str(), (std::string(chars_b, sizeof(chars_b))));
584   TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c))));
585   TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b))));
586 
587   // Make sure String::operator< works, too, since it is related to
588   // StringOffsetCompare.
589   TEST_EQ((*a[0]) < (*a[1]), true);
590   TEST_EQ((*a[1]) < (*a[0]), false);
591   TEST_EQ((*a[1]) < (*a[2]), false);
592   TEST_EQ((*a[2]) < (*a[1]), true);
593   TEST_EQ((*a[4]) < (*a[3]), true);
594   TEST_EQ((*a[5]) < (*a[4]), false);
595   TEST_EQ((*a[5]) < (*a[4]), false);
596   TEST_EQ((*a[6]) < (*a[5]), true);
597 }
598 
599 #if !defined(FLATBUFFERS_USE_STD_SPAN) && !defined(FLATBUFFERS_SPAN_MINIMAL)
FlatbuffersSpanTest()600 void FlatbuffersSpanTest() {
601   // Compile-time checking of non-const [] to const [] conversions.
602   using flatbuffers::internal::is_span_convertible;
603   (void)is_span_convertible<int, 1, int, 1>::type(123);
604   (void)is_span_convertible<const int, 1, int, 1>::type(123);
605   (void)is_span_convertible<const int64_t, 1, int64_t, 1>::type(123);
606   (void)is_span_convertible<const uint64_t, 1, uint64_t, 1>::type(123);
607   (void)is_span_convertible<const int, 1, const int, 1>::type(123);
608   (void)is_span_convertible<const int64_t, 1, const int64_t, 1>::type(123);
609   (void)is_span_convertible<const uint64_t, 1, const uint64_t, 1>::type(123);
610 
611   using flatbuffers::span;
612   span<char, 0> c1;
613   TEST_EQ(c1.size(), 0);
614   span<char, flatbuffers::dynamic_extent> c2;
615   TEST_EQ(c2.size(), 0);
616   span<char> c3;
617   TEST_EQ(c3.size(), 0);
618   TEST_ASSERT(c1.empty() && c2.empty() && c3.empty());
619 
620   int i_data7[7] = { 0, 1, 2, 3, 4, 5, 6 };
621   span<int, 7> i1(&i_data7[0], 7);
622   span<int> i2(i1);  // make dynamic from static
623   TEST_EQ(i1.size(), 7);
624   TEST_EQ(i1.empty(), false);
625   TEST_EQ(i1.size(), i2.size());
626   TEST_EQ(i1.data(), i_data7);
627   TEST_EQ(i1[2], 2);
628   // Make const span from a non-const one.
629   span<const int, 7> i3(i1);
630   // Construct from a C-array.
631   span<int, 7> i4(i_data7);
632   span<const int, 7> i5(i_data7);
633   span<int> i6(i_data7);
634   span<const int> i7(i_data7);
635   TEST_EQ(i7.size(), 7);
636   // Check construction from a const array.
637   const int i_cdata5[5] = { 4, 3, 2, 1, 0 };
638   span<const int, 5> i8(i_cdata5);
639   span<const int> i9(i_cdata5);
640   TEST_EQ(i9.size(), 5);
641   // Construction from a (ptr, size) pair.
642   span<int, 7> i10(i_data7, 7);
643   span<int> i11(i_data7, 7);
644   TEST_EQ(i11.size(), 7);
645   span<const int, 5> i12(i_cdata5, 5);
646   span<const int> i13(i_cdata5, 5);
647   TEST_EQ(i13.size(), 5);
648   // Construction from std::array.
649   std::array<int, 6> i_arr6 = { { 0, 1, 2, 3, 4, 5 } };
650   span<int, 6> i14(i_arr6);
651   span<const int, 6> i15(i_arr6);
652   span<int> i16(i_arr6);
653   span<const int> i17(i_arr6);
654   TEST_EQ(i17.size(), 6);
655   const std::array<int, 8> i_carr8 = { { 0, 1, 2, 3, 4, 5, 6, 7 } };
656   span<const int, 8> i18(i_carr8);
657   span<const int> i19(i_carr8);
658   TEST_EQ(i18.size(), 8);
659   TEST_EQ(i19.size(), 8);
660   TEST_EQ(i19[7], 7);
661   // Check compatibility with flatbuffers::Array.
662   int fbs_int3_underlaying[3] = { 0 };
663   int fbs_int3_data[3] = { 1, 2, 3 };
664   auto &fbs_int3 = flatbuffers::CastToArray(fbs_int3_underlaying);
665   fbs_int3.CopyFromSpan(fbs_int3_data);
666   TEST_EQ(fbs_int3.Get(1), 2);
667   const int fbs_cint3_data[3] = { 2, 3, 4 };
668   fbs_int3.CopyFromSpan(fbs_cint3_data);
669   TEST_EQ(fbs_int3.Get(1), 3);
670   // Check with Array<Enum, N>
671   enum class Dummy : uint16_t { Zero = 0, One, Two };
672   Dummy fbs_dummy3_underlaying[3] = {};
673   Dummy fbs_dummy3_data[3] = { Dummy::One, Dummy::Two, Dummy::Two };
674   auto &fbs_dummy3 = flatbuffers::CastToArray(fbs_dummy3_underlaying);
675   fbs_dummy3.CopyFromSpan(fbs_dummy3_data);
676   TEST_EQ(fbs_dummy3.Get(1), Dummy::Two);
677 }
678 #else
FlatbuffersSpanTest()679 void FlatbuffersSpanTest() {}
680 #endif
681 
682 // VS10 does not support typed enums, exclude from tests
683 #if !defined(_MSC_VER) || _MSC_VER >= 1700
FixedLengthArrayTest()684 void FixedLengthArrayTest() {
685   // Generate an ArrayTable containing one ArrayStruct.
686   flatbuffers::FlatBufferBuilder fbb;
687   MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
688   TEST_NOTNULL(nStruct0.mutable_a());
689   nStruct0.mutable_a()->Mutate(0, 1);
690   nStruct0.mutable_a()->Mutate(1, 2);
691   TEST_NOTNULL(nStruct0.mutable_c());
692   nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
693   nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
694   TEST_NOTNULL(nStruct0.mutable_d());
695   nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
696   nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
697   MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
698   TEST_NOTNULL(nStruct1.mutable_a());
699   nStruct1.mutable_a()->Mutate(0, 3);
700   nStruct1.mutable_a()->Mutate(1, 4);
701   TEST_NOTNULL(nStruct1.mutable_c());
702   nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
703   nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
704   TEST_NOTNULL(nStruct1.mutable_d());
705   nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
706   nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
707   MyGame::Example::ArrayStruct aStruct(2, 12, 1);
708   TEST_NOTNULL(aStruct.b());
709   TEST_NOTNULL(aStruct.mutable_b());
710   TEST_NOTNULL(aStruct.mutable_d());
711   TEST_NOTNULL(aStruct.mutable_f());
712   for (int i = 0; i < aStruct.b()->size(); i++)
713     aStruct.mutable_b()->Mutate(i, i + 1);
714   aStruct.mutable_d()->Mutate(0, nStruct0);
715   aStruct.mutable_d()->Mutate(1, nStruct1);
716   auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
717   MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
718   // Verify correctness of the ArrayTable.
719   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
720   TEST_ASSERT(MyGame::Example::VerifyArrayTableBuffer(verifier));
721   // Do test.
722   auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
723   auto mArStruct = p->mutable_a();
724   TEST_NOTNULL(mArStruct);
725   TEST_NOTNULL(mArStruct->b());
726   TEST_NOTNULL(mArStruct->d());
727   TEST_NOTNULL(mArStruct->f());
728   TEST_NOTNULL(mArStruct->mutable_b());
729   TEST_NOTNULL(mArStruct->mutable_d());
730   TEST_NOTNULL(mArStruct->mutable_f());
731   TEST_EQ(mArStruct->a(), 2);
732   TEST_EQ(mArStruct->b()->size(), 15);
733   mArStruct->mutable_b()->Mutate(14, -14);
734   TEST_EQ(mArStruct->b()->Get(14), -14);
735   TEST_EQ(mArStruct->c(), 12);
736   TEST_NOTNULL(mArStruct->d()->Get(0));
737   TEST_NOTNULL(mArStruct->d()->Get(0)->a());
738   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(0), 1);
739   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(1), 2);
740   TEST_NOTNULL(mArStruct->d()->Get(1));
741   TEST_NOTNULL(mArStruct->d()->Get(1)->a());
742   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(0), 3);
743   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 4);
744   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
745   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
746   mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
747   TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1));
748   TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b());
749   TEST_NOTNULL(mArStruct->d()->Get(0)->c());
750   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0));
751   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1));
752   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
753           mArStruct->d()->Get(0)->d()->Get(0));
754   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
755           mArStruct->d()->Get(0)->d()->Get(1));
756   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b());
757   TEST_NOTNULL(mArStruct->d()->Get(1)->c());
758   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0));
759   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1));
760   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
761           mArStruct->d()->Get(1)->d()->Get(0));
762   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
763           mArStruct->d()->Get(1)->d()->Get(1));
764   for (int i = 0; i < mArStruct->b()->size() - 1; i++)
765     TEST_EQ(mArStruct->b()->Get(i), i + 1);
766   // Check alignment
767   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->d()) % 8);
768   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->f()) % 8);
769 
770   // Check if default constructor set all memory zero
771   const size_t arr_size = sizeof(MyGame::Example::ArrayStruct);
772   char non_zero_memory[arr_size];
773   // set memory chunk of size ArrayStruct to 1's
774   std::memset(static_cast<void *>(non_zero_memory), 1, arr_size);
775   // after placement-new it should be all 0's
776 #  if defined(_MSC_VER) && defined(_DEBUG)
777 #    undef new
778 #  endif
779   MyGame::Example::ArrayStruct *ap =
780       new (non_zero_memory) MyGame::Example::ArrayStruct;
781 #  if defined(_MSC_VER) && defined(_DEBUG)
782 #    define new DEBUG_NEW
783 #  endif
784   (void)ap;
785   for (size_t i = 0; i < arr_size; ++i) { TEST_EQ(non_zero_memory[i], 0); }
786 }
787 #else
FixedLengthArrayTest()788 void FixedLengthArrayTest() {}
789 #endif  // !defined(_MSC_VER) || _MSC_VER >= 1700
790 
791 #if !defined(FLATBUFFERS_SPAN_MINIMAL) && \
792     (!defined(_MSC_VER) || _MSC_VER >= 1700)
FixedLengthArrayConstructorTest()793 void FixedLengthArrayConstructorTest() {
794   const int32_t nested_a[2] = { 1, 2 };
795   MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A,
796                                             MyGame::Example::TestEnum::B };
797   const int64_t int64_2[2] = { -2, -1 };
798 
799   std::array<MyGame::Example::NestedStruct, 2> init_d = {
800     { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
801                                     nested_c, int64_2),
802       MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::A,
803                                     nested_c,
804                                     std::array<int64_t, 2>{ { 12, 13 } }) }
805   };
806 
807   MyGame::Example::ArrayStruct arr_struct(
808       8.125,
809       std::array<int32_t, 0xF>{
810           { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
811       -17, init_d, 10, int64_2);
812   TEST_EQ(arr_struct.a(), 8.125);
813   TEST_EQ(arr_struct.b()->Get(2), 3);
814   TEST_EQ(arr_struct.c(), -17);
815 
816   TEST_NOTNULL(arr_struct.d());
817   const auto &arr_d_0 = *arr_struct.d()->Get(0);
818   TEST_EQ(arr_d_0.a()->Get(0), 1);
819   TEST_EQ(arr_d_0.a()->Get(1), 2);
820   TEST_EQ(arr_d_0.b(), MyGame::Example::TestEnum::B);
821   TEST_EQ(arr_d_0.c()->Get(0), MyGame::Example::TestEnum::A);
822   TEST_EQ(arr_d_0.c()->Get(1), MyGame::Example::TestEnum::B);
823   TEST_EQ(arr_d_0.d()->Get(0), -2);
824   TEST_EQ(arr_d_0.d()->Get(1), -1);
825   const auto &arr_d_1 = *arr_struct.d()->Get(1);
826   TEST_EQ(arr_d_1.a()->Get(0), 1);
827   TEST_EQ(arr_d_1.a()->Get(1), 2);
828   TEST_EQ(arr_d_1.b(), MyGame::Example::TestEnum::A);
829   TEST_EQ(arr_d_1.c()->Get(0), MyGame::Example::TestEnum::A);
830   TEST_EQ(arr_d_1.c()->Get(1), MyGame::Example::TestEnum::B);
831   TEST_EQ(arr_d_1.d()->Get(0), 12);
832   TEST_EQ(arr_d_1.d()->Get(1), 13);
833 
834   TEST_EQ(arr_struct.e(), 10);
835   TEST_EQ(arr_struct.f()->Get(0), -2);
836   TEST_EQ(arr_struct.f()->Get(1), -1);
837 }
838 #else
FixedLengthArrayConstructorTest()839 void FixedLengthArrayConstructorTest() {}
840 #endif
841 
FixedLengthArrayOperatorEqualTest()842 void FixedLengthArrayOperatorEqualTest() {
843   const int32_t nested_a[2] = { 1, 2 };
844   MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A,
845                                             MyGame::Example::TestEnum::B };
846 
847   MyGame::Example::TestEnum nested_cc[2] = { MyGame::Example::TestEnum::A,
848                                              MyGame::Example::TestEnum::C };
849   const int64_t int64_2[2] = { -2, -1 };
850 
851   std::array<MyGame::Example::NestedStruct, 2> init_d = {
852     { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
853                                     nested_c, int64_2),
854       MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
855                                     nested_c,
856                                     std::array<int64_t, 2>{ { -2, -1 } }) }
857   };
858 
859   auto different = MyGame::Example::NestedStruct(
860       nested_a, MyGame::Example::TestEnum::B, nested_cc,
861       std::array<int64_t, 2>{ { -2, -1 } });
862 
863   TEST_ASSERT(init_d[0] == init_d[1]);
864   TEST_ASSERT(init_d[0] != different);
865 
866   std::array<MyGame::Example::ArrayStruct, 3> arr_struct = {
867     MyGame::Example::ArrayStruct(
868         8.125,
869         std::array<int32_t, 0xF>{
870             { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
871         -17, init_d, 10, int64_2),
872 
873     MyGame::Example::ArrayStruct(
874         8.125,
875         std::array<int32_t, 0xF>{
876             { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
877         -17, init_d, 10, int64_2),
878 
879     MyGame::Example::ArrayStruct(
880         8.125,
881         std::array<int32_t, 0xF>{
882             { 1000, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
883         -17, init_d, 10, int64_2)
884   };
885 
886   TEST_ASSERT(arr_struct[0] == arr_struct[1]);
887   TEST_ASSERT(arr_struct[1] != arr_struct[2]);
888 }
889 
NativeTypeTest()890 void NativeTypeTest() {
891   const int N = 3;
892 
893   Geometry::ApplicationDataT src_data;
894   src_data.vectors.reserve(N);
895   src_data.vectors_alt.reserve(N);
896 
897   for (int i = 0; i < N; ++i) {
898     src_data.vectors.push_back(
899         Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f));
900     src_data.vectors_alt.push_back(
901         Native::Vector3D(20 * i + 0.1f, 20 * i + 0.2f, 20 * i + 0.3f));
902   }
903 
904   flatbuffers::FlatBufferBuilder fbb;
905   fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data));
906 
907   auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer());
908 
909   for (int i = 0; i < N; ++i) {
910     const Native::Vector3D &v = dstDataT->vectors[i];
911     TEST_EQ(v.x, 10 * i + 0.1f);
912     TEST_EQ(v.y, 10 * i + 0.2f);
913     TEST_EQ(v.z, 10 * i + 0.3f);
914 
915     const Native::Vector3D &v2 = dstDataT->vectors_alt[i];
916     TEST_EQ(v2.x, 20 * i + 0.1f);
917     TEST_EQ(v2.y, 20 * i + 0.2f);
918     TEST_EQ(v2.z, 20 * i + 0.3f);
919   }
920 }
921 
922 // Guard against -Wunused-function on platforms without file tests.
923 #ifndef FLATBUFFERS_NO_FILE_TESTS
924 // VS10 does not support typed enums, exclude from tests
925 #  if !defined(_MSC_VER) || _MSC_VER >= 1700
FixedLengthArrayJsonTest(const std::string & tests_data_path,bool binary)926 void FixedLengthArrayJsonTest(const std::string &tests_data_path, bool binary) {
927   // load FlatBuffer schema (.fbs) and JSON from disk
928   std::string schemafile;
929   std::string jsonfile;
930   TEST_EQ(flatbuffers::LoadFile(
931               (tests_data_path + "arrays_test." + (binary ? "bfbs" : "fbs"))
932                   .c_str(),
933               binary, &schemafile),
934           true);
935   TEST_EQ(
936       flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
937                             false, &jsonfile),
938       true);
939 
940   // parse schema first, so we can use it to parse the data after
941   flatbuffers::Parser parserOrg, parserGen;
942   if (binary) {
943     flatbuffers::Verifier verifier(
944         reinterpret_cast<const uint8_t *>(schemafile.c_str()),
945         schemafile.size());
946     TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
947     TEST_EQ(parserOrg.Deserialize(
948                 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
949                 schemafile.size()),
950             true);
951     TEST_EQ(parserGen.Deserialize(
952                 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
953                 schemafile.size()),
954             true);
955   } else {
956     TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
957     TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
958   }
959   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
960 
961   // First, verify it, just in case:
962   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
963                                     parserOrg.builder_.GetSize());
964   TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
965 
966   // Export to JSON
967   std::string jsonGen;
968   TEST_NULL(
969       GenText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen));
970 
971   // Import from JSON
972   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
973 
974   // Verify buffer from generated JSON
975   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
976                                     parserGen.builder_.GetSize());
977   TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
978 
979   // Compare generated buffer to original
980   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
981   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
982                       parserGen.builder_.GetBufferPointer(),
983                       parserOrg.builder_.GetSize()),
984           0);
985 }
986 
FixedLengthArraySpanTest(const std::string & tests_data_path)987 void FixedLengthArraySpanTest(const std::string &tests_data_path) {
988   // load FlatBuffer schema (.fbs) and JSON from disk
989   std::string schemafile;
990   std::string jsonfile;
991   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "arrays_test.fbs").c_str(),
992                                 false, &schemafile),
993           true);
994   TEST_EQ(
995       flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
996                             false, &jsonfile),
997       true);
998 
999   // parse schema first, so we can use it to parse the data after
1000   flatbuffers::Parser parser;
1001   TEST_EQ(parser.Parse(schemafile.c_str()), true);
1002   TEST_EQ(parser.Parse(jsonfile.c_str()), true);
1003   auto &fbb = parser.builder_;
1004   auto verifier = flatbuffers::Verifier(fbb.GetBufferPointer(), fbb.GetSize());
1005   TEST_EQ(true, VerifyArrayTableBuffer(verifier));
1006 
1007   auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
1008   TEST_NOTNULL(p);
1009   auto table_struct = p->mutable_a();
1010   TEST_NOTNULL(table_struct);
1011   TEST_EQ(2, table_struct->d()->size());
1012   TEST_NOTNULL(table_struct->d());
1013   TEST_NOTNULL(table_struct->mutable_d());
1014   // test array of structs
1015   auto const_d = flatbuffers::make_span(*table_struct->d());
1016   auto mutable_d = flatbuffers::make_span(*table_struct->mutable_d());
1017   TEST_EQ(2, const_d.size());
1018   TEST_EQ(2, mutable_d.size());
1019   TEST_ASSERT(const_d[0] == mutable_d[0]);
1020   TEST_ASSERT(const_d[1] == mutable_d[1]);
1021   mutable_d[0] = const_d[0];  // mutate
1022   // test scalars
1023   auto &const_nested = const_d[0];
1024   auto &mutable_nested = mutable_d[0];
1025   static_assert(sizeof(MyGame::Example::TestEnum) == sizeof(uint8_t),
1026                 "TestEnum's underlaying type must by byte");
1027   TEST_NOTNULL(const_nested.d());
1028   TEST_NOTNULL(mutable_nested.d());
1029   {
1030     flatbuffers::span<const MyGame::Example::TestEnum, 2> const_d_c =
1031         flatbuffers::make_span(*const_nested.c());
1032     auto mutable_d_c = flatbuffers::make_span(*mutable_nested.mutable_c());
1033     TEST_EQ(2, const_d_c.size());
1034     TEST_EQ(2, mutable_d_c.size());
1035     TEST_EQ(MyGame::Example::TestEnum::C, const_d_c[0]);
1036     TEST_EQ(MyGame::Example::TestEnum::B, const_d_c[1]);
1037     TEST_ASSERT(mutable_d_c.end() == std::copy(const_d_c.begin(),
1038                                                const_d_c.end(),
1039                                                mutable_d_c.begin()));
1040     TEST_ASSERT(
1041         std::equal(const_d_c.begin(), const_d_c.end(), mutable_d_c.begin()));
1042   }
1043   // test little endian array of int32
1044 #    if FLATBUFFERS_LITTLEENDIAN
1045   {
1046     flatbuffers::span<const int32_t, 2> const_d_a =
1047         flatbuffers::make_span(*const_nested.a());
1048     auto mutable_d_a = flatbuffers::make_span(*mutable_nested.mutable_a());
1049     TEST_EQ(2, const_d_a.size());
1050     TEST_EQ(2, mutable_d_a.size());
1051     TEST_EQ(-1, const_d_a[0]);
1052     TEST_EQ(2, const_d_a[1]);
1053     TEST_ASSERT(mutable_d_a.end() == std::copy(const_d_a.begin(),
1054                                                const_d_a.end(),
1055                                                mutable_d_a.begin()));
1056     TEST_ASSERT(
1057         std::equal(const_d_a.begin(), const_d_a.end(), mutable_d_a.begin()));
1058   }
1059 #    endif
1060 }
1061 #  else
FixedLengthArrayJsonTest(bool)1062 void FixedLengthArrayJsonTest(bool /*binary*/) {}
FixedLengthArraySpanTest()1063 void FixedLengthArraySpanTest() {}
1064 #  endif
1065 
TestEmbeddedBinarySchema(const std::string & tests_data_path)1066 void TestEmbeddedBinarySchema(const std::string &tests_data_path) {
1067   // load JSON from disk
1068   std::string jsonfile;
1069   TEST_EQ(flatbuffers::LoadFile(
1070               (tests_data_path + "monsterdata_test.golden").c_str(), false,
1071               &jsonfile),
1072           true);
1073 
1074   // parse schema first, so we can use it to parse the data after
1075   flatbuffers::Parser parserOrg, parserGen;
1076   flatbuffers::Verifier verifier(MyGame::Example::MonsterBinarySchema::data(),
1077                                  MyGame::Example::MonsterBinarySchema::size());
1078   TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
1079   TEST_EQ(parserOrg.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1080                                 MyGame::Example::MonsterBinarySchema::size()),
1081           true);
1082   TEST_EQ(parserGen.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1083                                 MyGame::Example::MonsterBinarySchema::size()),
1084           true);
1085   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
1086 
1087   // First, verify it, just in case:
1088   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
1089                                     parserOrg.builder_.GetSize());
1090   TEST_EQ(VerifyMonsterBuffer(verifierOrg), true);
1091 
1092   // Export to JSON
1093   std::string jsonGen;
1094   TEST_NULL(
1095       GenText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen));
1096 
1097   // Import from JSON
1098   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
1099 
1100   // Verify buffer from generated JSON
1101   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
1102                                     parserGen.builder_.GetSize());
1103   TEST_EQ(VerifyMonsterBuffer(verifierGen), true);
1104 
1105   // Compare generated buffer to original
1106   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
1107   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
1108                       parserGen.builder_.GetBufferPointer(),
1109                       parserOrg.builder_.GetSize()),
1110           0);
1111 }
1112 #endif
1113 
EmbeddedSchemaAccessByType()1114 template<typename T> void EmbeddedSchemaAccessByType() {
1115   // Get the binary schema from the Type itself.
1116   // Verify the schema is OK.
1117   flatbuffers::Verifier verifierEmbeddedSchema(
1118       T::TableType::BinarySchema::data(), T::TableType::BinarySchema::size());
1119   TEST_EQ(reflection::VerifySchemaBuffer(verifierEmbeddedSchema), true);
1120 
1121   // Reflect it.
1122   auto schema = reflection::GetSchema(T::TableType::BinarySchema::data());
1123 
1124   // This should equal the expected root table.
1125   TEST_EQ_STR(schema->root_table()->name()->c_str(), "MyGame.Example.Monster");
1126 }
1127 
EmbeddedSchemaAccess()1128 void EmbeddedSchemaAccess() {
1129   // Get the binary schema for the monster.
1130   // Verify the schema is OK.
1131   flatbuffers::Verifier verifierEmbeddedSchema(Monster::BinarySchema::data(),
1132                                                Monster::BinarySchema::size());
1133   TEST_EQ(reflection::VerifySchemaBuffer(verifierEmbeddedSchema), true);
1134 
1135   // Reflect it.
1136   auto schema = reflection::GetSchema(Monster::BinarySchema::data());
1137 
1138   // This should equal the expected root table.
1139   TEST_EQ_STR(schema->root_table()->name()->c_str(), "MyGame.Example.Monster");
1140 
1141   // Repeat above, but do so through a template parameter:
1142   EmbeddedSchemaAccessByType<StatT>();
1143 }
1144 
NestedVerifierTest()1145 void NestedVerifierTest() {
1146   // Create a nested monster.
1147   flatbuffers::FlatBufferBuilder nested_builder;
1148   FinishMonsterBuffer(
1149       nested_builder,
1150       CreateMonster(nested_builder, nullptr, 0, 0,
1151                     nested_builder.CreateString("NestedMonster")));
1152 
1153   // Verify the nested monster
1154   flatbuffers::Verifier verifier(nested_builder.GetBufferPointer(),
1155                                  nested_builder.GetSize());
1156   TEST_EQ(true, VerifyMonsterBuffer(verifier));
1157 
1158   {
1159     // Create the outer monster.
1160     flatbuffers::FlatBufferBuilder builder;
1161 
1162     // Add the nested monster as a vector of bytes.
1163     auto nested_monster_bytes = builder.CreateVector(
1164         nested_builder.GetBufferPointer(), nested_builder.GetSize());
1165 
1166     auto name = builder.CreateString("OuterMonster");
1167 
1168     MonsterBuilder mon_builder(builder);
1169     mon_builder.add_name(name);
1170     mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1171     FinishMonsterBuffer(builder, mon_builder.Finish());
1172 
1173     // Verify the root monster, which includes verifing the nested monster
1174     flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1175                                    builder.GetSize());
1176     TEST_EQ(true, VerifyMonsterBuffer(verifier));
1177   }
1178 
1179   {
1180     // Create the outer monster.
1181     flatbuffers::FlatBufferBuilder builder;
1182 
1183     // Purposely invalidate the nested flatbuffer setting its length to 1, an
1184     // invalid length.
1185     uint8_t invalid_nested_buffer[1];
1186     auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 1);
1187 
1188     auto name = builder.CreateString("OuterMonster");
1189 
1190     MonsterBuilder mon_builder(builder);
1191     mon_builder.add_name(name);
1192     mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1193     FinishMonsterBuffer(builder, mon_builder.Finish());
1194 
1195     // Verify the root monster fails, since the included nested monster fails.
1196     flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1197                                    builder.GetSize());
1198     TEST_EQ(false, VerifyMonsterBuffer(verifier));
1199 
1200     // Verify the root monster succeeds, since we've disabled checking nested
1201     // flatbuffers
1202     flatbuffers::Verifier::Options options;
1203     options.check_nested_flatbuffers = false;
1204     flatbuffers::Verifier no_check_nested(builder.GetBufferPointer(),
1205                                           builder.GetSize(), options);
1206     TEST_EQ(true, VerifyMonsterBuffer(no_check_nested));
1207   }
1208 
1209   {
1210     // Create the outer monster.
1211     flatbuffers::FlatBufferBuilder builder;
1212 
1213     // Purposely invalidate the nested flatbuffer setting its length to 0, an
1214     // invalid length.
1215     uint8_t *invalid_nested_buffer = nullptr;
1216     auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 0);
1217 
1218     auto name = builder.CreateString("OuterMonster");
1219 
1220     MonsterBuilder mon_builder(builder);
1221     mon_builder.add_name(name);
1222     mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1223     FinishMonsterBuffer(builder, mon_builder.Finish());
1224 
1225     // Verify the root monster fails, since the included nested monster fails.
1226     flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1227                                    builder.GetSize());
1228     TEST_EQ(false, VerifyMonsterBuffer(verifier));
1229   }
1230 }
1231 
1232 template<class T, class Container>
TestIterators(const std::vector<T> & expected,const Container & tested)1233 void TestIterators(const std::vector<T> &expected, const Container &tested) {
1234   TEST_ASSERT(tested.rbegin().base() == tested.end());
1235   TEST_ASSERT(tested.crbegin().base() == tested.cend());
1236   TEST_ASSERT(tested.rend().base() == tested.begin());
1237   TEST_ASSERT(tested.crend().base() == tested.cbegin());
1238 
1239   size_t k = 0;
1240   for (auto it = tested.begin(); it != tested.end(); ++it, ++k) {
1241     const auto &e = expected.at(k);
1242     TEST_EQ(*it, e);
1243   }
1244   TEST_EQ(k, expected.size());
1245 
1246   k = expected.size();
1247   for (auto it = tested.rbegin(); it != tested.rend(); ++it, --k) {
1248     const auto &e = expected.at(k - 1);
1249     TEST_EQ(*it, e);
1250   }
1251   TEST_EQ(k, 0);
1252 }
1253 
FlatbuffersIteratorsTest()1254 void FlatbuffersIteratorsTest() {
1255   {
1256     flatbuffers::FlatBufferBuilder fbb;
1257     const std::vector<unsigned char> inv_data = { 1, 2, 3 };
1258     {
1259       auto mon_name = fbb.CreateString("MyMonster");  // key, mandatory
1260       auto inv_vec = fbb.CreateVector(inv_data);
1261       auto empty_i64_vec =
1262           fbb.CreateVector(static_cast<const int64_t *>(nullptr), 0);
1263       MonsterBuilder mb(fbb);
1264       mb.add_name(mon_name);
1265       mb.add_inventory(inv_vec);
1266       mb.add_vector_of_longs(empty_i64_vec);
1267       FinishMonsterBuffer(fbb, mb.Finish());
1268     }
1269     const auto &mon = *flatbuffers::GetRoot<Monster>(fbb.GetBufferPointer());
1270 
1271     TEST_EQ_STR("MyMonster", mon.name()->c_str());
1272     TEST_ASSERT(mon.inventory());
1273     TEST_ASSERT(mon.vector_of_longs());
1274     TestIterators(inv_data, *mon.inventory());
1275     TestIterators(std::vector<int64_t>(), *mon.vector_of_longs());
1276   }
1277 
1278   {
1279     flatbuffers::FlatBufferBuilder fbb;
1280     MyGame::Example::ArrayStruct aStruct;
1281     MyGame::Example::FinishArrayTableBuffer(
1282         fbb, MyGame::Example::CreateArrayTable(fbb, &aStruct));
1283     const auto &array_table =
1284         *flatbuffers::GetRoot<ArrayTable>(fbb.GetBufferPointer());
1285     TEST_ASSERT(array_table.a());
1286     auto &int_15 = *array_table.a()->b();
1287     TestIterators(std::vector<int>(15, 0), int_15);
1288   }
1289 }
1290 
PrivateAnnotationsLeaks()1291 void PrivateAnnotationsLeaks() {
1292   // Simple schemas and a "has optional scalar" sentinal.
1293   std::vector<std::string> schemas;
1294   std::vector<std::string> failure_schemas;
1295 
1296   // (private) (table/struct)
1297   schemas.push_back(
1298       "table Monster (private) { mana: int; }"
1299       "struct ABC (private) { mana: int; }");
1300 
1301   // (public) (table/struct)
1302   schemas.push_back(
1303       "table Monster { mana: int; }"
1304       "struct ABC { mana: int; }");
1305 
1306   // (private) (union) containing (private) (table/struct)
1307   schemas.push_back(
1308       "table Monster (private) { mana: int; } "
1309       "struct ABC (private) { mana: int; } "
1310       "union Any (private) { Monster, ABC } ");
1311 
1312   // (public) (union) containing (public) (table/struct)
1313   schemas.push_back(
1314       "table Monster { mana: int; }"
1315       "struct ABC { mana: int; }"
1316       "union Any { Monster, ABC }");
1317 
1318   // (private) (table/struct/enum)
1319   schemas.push_back(
1320       "table Monster (private) { mana: int; }"
1321       "struct ABC (private) { mana: int; }"
1322       "enum Race:byte (private) { None = -1, Human = 0, }");
1323 
1324   // (public) (table/struct/enum)
1325   schemas.push_back(
1326       "table Monster { mana: int; }"
1327       "struct ABC { mana: int; }"
1328       "enum Race:byte { None = -1, Human = 0, }");
1329 
1330   // (private) (union) containing (private) (table/struct)
1331   schemas.push_back(
1332       "table Monster (private) { mana: int; }"
1333       "struct ABC (private) { mana: int; }"
1334       "enum Race:byte (private) { None = -1, Human = 0, }"
1335       "union Any (private) { Monster, ABC }");
1336 
1337   // (public) (union) containing (public) (table/struct)
1338   schemas.push_back(
1339       "table Monster { mana: int; }"
1340       "struct ABC { mana: int; }"
1341       "enum Race:byte { None = -1, Human = 0, }"
1342       "union Any { Monster, ABC }");
1343 
1344   // (private) (table), (public struct)
1345   schemas.push_back(
1346       "table Monster (private) { mana: int; }"
1347       "struct ABC { mana: int; }");
1348 
1349   // (private) (table), (public) (struct/enum)
1350   schemas.push_back(
1351       "table Monster (private) { mana: int; }"
1352       "struct ABC { mana: int; }"
1353       "enum Race:byte { None = -1, Human = 0, }");
1354 
1355   // (public) (struct) containing (public) (enum)
1356   schemas.push_back(
1357       "enum Race:byte { None = -1, Human = 0, }"
1358       "table Monster { mana: int; }"
1359       "struct ABC { mana: int; type: Race; }");
1360 
1361   // (public) (union) containing (private) (table) & (public) (struct)
1362   failure_schemas.push_back(
1363       "table Monster (private) { mana: int; }"
1364       "struct ABC { mana: int; }"
1365       "union Any { Monster, ABC }");
1366 
1367   // (public) (union) containing (private) (table/struct)
1368   failure_schemas.push_back(
1369       "table Monster (private) { mana: int; }"
1370       "struct ABC (private) { mana: int; }"
1371       "enum Race:byte { None = -1, Human = 0, }"
1372       "union Any { Monster, ABC }");
1373 
1374   // (public) (table) containing (private) (struct)
1375   failure_schemas.push_back(
1376       "table Monster { mana: int; ab: ABC; }"
1377       "struct ABC (private) { mana: int; }");
1378 
1379   // (public) (struct) containing (private) (enum)
1380   failure_schemas.push_back(
1381       "enum Race:byte (private) { None = -1, Human = 0, }"
1382       "table Monster { mana: int; }"
1383       "struct ABC { mana: int; type: Race; }");
1384 
1385   flatbuffers::IDLOptions opts;
1386   opts.lang_to_generate = flatbuffers::IDLOptions::Language::kSwift;
1387   opts.no_leak_private_annotations = true;
1388 
1389   for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1390     flatbuffers::Parser parser(opts);
1391     TEST_ASSERT(parser.Parse(schema->c_str()));
1392   }
1393 
1394   for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1395        schema++) {
1396     flatbuffers::Parser parser(opts);
1397     TEST_EQ(false, parser.Parse(schema->c_str()));
1398   }
1399 
1400   opts.no_leak_private_annotations = false;
1401 
1402   for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1403     flatbuffers::Parser parser(opts);
1404     TEST_ASSERT(parser.Parse(schema->c_str()));
1405   }
1406 
1407   for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1408        schema++) {
1409     flatbuffers::Parser parser(opts);
1410     TEST_ASSERT(parser.Parse(schema->c_str()));
1411   }
1412 }
1413 
VectorSpanTest()1414 void VectorSpanTest() {
1415   flatbuffers::FlatBufferBuilder builder;
1416 
1417   auto mloc = CreateMonster(
1418       builder, nullptr, 0, 0, builder.CreateString("Monster"),
1419       builder.CreateVector<uint8_t>({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
1420 
1421   FinishMonsterBuffer(builder, mloc);
1422 
1423   auto monster = GetMonster(builder.GetBufferPointer());
1424   auto mutable_monster = GetMutableMonster(builder.GetBufferPointer());
1425 
1426   {  // using references
1427     TEST_NOTNULL(monster->inventory());
1428 
1429     flatbuffers::span<const uint8_t> const_inventory =
1430         flatbuffers::make_span(*monster->inventory());
1431     TEST_EQ(const_inventory.size(), 10);
1432     TEST_EQ(const_inventory[0], 0);
1433     TEST_EQ(const_inventory[9], 9);
1434 
1435     flatbuffers::span<uint8_t> mutable_inventory =
1436         flatbuffers::make_span(*mutable_monster->mutable_inventory());
1437     TEST_EQ(mutable_inventory.size(), 10);
1438     TEST_EQ(mutable_inventory[0], 0);
1439     TEST_EQ(mutable_inventory[9], 9);
1440 
1441     mutable_inventory[0] = 42;
1442     TEST_EQ(mutable_inventory[0], 42);
1443 
1444     mutable_inventory[0] = 0;
1445     TEST_EQ(mutable_inventory[0], 0);
1446   }
1447 
1448   {  // using pointers
1449     TEST_EQ(flatbuffers::VectorLength(monster->inventory()), 10);
1450 
1451     flatbuffers::span<const uint8_t> const_inventory =
1452         flatbuffers::make_span(monster->inventory());
1453     TEST_EQ(const_inventory.size(), 10);
1454     TEST_EQ(const_inventory[0], 0);
1455     TEST_EQ(const_inventory[9], 9);
1456 
1457     flatbuffers::span<uint8_t> mutable_inventory =
1458         flatbuffers::make_span(mutable_monster->mutable_inventory());
1459     TEST_EQ(mutable_inventory.size(), 10);
1460     TEST_EQ(mutable_inventory[0], 0);
1461     TEST_EQ(mutable_inventory[9], 9);
1462 
1463     mutable_inventory[0] = 42;
1464     TEST_EQ(mutable_inventory[0], 42);
1465 
1466     mutable_inventory[0] = 0;
1467     TEST_EQ(mutable_inventory[0], 0);
1468   }
1469 
1470   {
1471     TEST_ASSERT(nullptr == monster->testnestedflatbuffer());
1472 
1473     TEST_EQ(flatbuffers::VectorLength(monster->testnestedflatbuffer()), 0);
1474 
1475     flatbuffers::span<const uint8_t> const_nested =
1476         flatbuffers::make_span(monster->testnestedflatbuffer());
1477     TEST_ASSERT(const_nested.empty());
1478 
1479     flatbuffers::span<uint8_t> mutable_nested =
1480         flatbuffers::make_span(mutable_monster->mutable_testnestedflatbuffer());
1481     TEST_ASSERT(mutable_nested.empty());
1482   }
1483 }
1484 
NativeInlineTableVectorTest()1485 void NativeInlineTableVectorTest() {
1486   TestNativeInlineTableT test;
1487   for (int i = 0; i < 10; ++i) {
1488     NativeInlineTableT t;
1489     t.a = i;
1490     test.t.push_back(t);
1491   }
1492 
1493   flatbuffers::FlatBufferBuilder fbb;
1494   auto offset = TestNativeInlineTable::Pack(fbb, &test);
1495   fbb.Finish(offset);
1496 
1497   auto *root =
1498       flatbuffers::GetRoot<TestNativeInlineTable>(fbb.GetBufferPointer());
1499   TestNativeInlineTableT unpacked;
1500   root->UnPackTo(&unpacked);
1501 
1502   for (int i = 0; i < 10; ++i) { TEST_ASSERT(unpacked.t[i] == test.t[i]); }
1503 
1504   TEST_ASSERT(unpacked.t == test.t);
1505 }
1506 
1507 // Guard against -Wunused-function on platforms without file tests.
1508 #ifndef FLATBUFFERS_NO_FILE_TESTS
DoNotRequireEofTest(const std::string & tests_data_path)1509 void DoNotRequireEofTest(const std::string &tests_data_path) {
1510   std::string schemafile;
1511   bool ok = flatbuffers::LoadFile(
1512       (tests_data_path + "monster_test.fbs").c_str(), false, &schemafile);
1513   TEST_EQ(ok, true);
1514   auto include_test_path =
1515       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
1516   const char *include_directories[] = { tests_data_path.c_str(),
1517                                         include_test_path.c_str(), nullptr };
1518   flatbuffers::IDLOptions opt;
1519   opt.require_json_eof = false;
1520   flatbuffers::Parser parser(opt);
1521   ok = parser.Parse(schemafile.c_str(), include_directories);
1522   TEST_EQ(ok, true);
1523 
1524   const char *str = R"(Some text at the beginning. {
1525       "name": "Blob",
1526       "hp": 5
1527     }{
1528       "name": "Imp",
1529       "hp": 10
1530     }
1531     Some extra text at the end too.
1532   )";
1533   const char *tableStart = std::strchr(str, '{');
1534   ok = parser.ParseJson(tableStart);
1535   TEST_EQ(ok, true);
1536 
1537   const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
1538   TEST_EQ_STR(monster->name()->c_str(), "Blob");
1539   TEST_EQ(monster->hp(), 5);
1540 
1541   tableStart += parser.BytesConsumed();
1542 
1543   ok = parser.ParseJson(tableStart);
1544   TEST_EQ(ok, true);
1545 
1546   monster = GetMonster(parser.builder_.GetBufferPointer());
1547   TEST_EQ_STR(monster->name()->c_str(), "Imp");
1548   TEST_EQ(monster->hp(), 10);
1549 }
1550 #endif
1551 
UnionUnderlyingTypeTest()1552 void UnionUnderlyingTypeTest() {
1553     using namespace UnionUnderlyingType;
1554     TEST_ASSERT(sizeof(ABC) == sizeof(uint32_t));
1555     TEST_ASSERT(static_cast<int32_t>(ABC::A) == 555);
1556     TEST_ASSERT(static_cast<int32_t>(ABC::B) == 666);
1557     TEST_ASSERT(static_cast<int32_t>(ABC::C) == 777);
1558 
1559     DT buffer;
1560     AT a;
1561     a.a = 42;
1562     BT b;
1563     b.b = "foo";
1564     CT c;
1565     c.c = true;
1566     buffer.test_union = ABCUnion();
1567     buffer.test_union.Set(a);
1568     buffer.test_vector_of_union.resize(3);
1569     buffer.test_vector_of_union[0].Set(a);
1570     buffer.test_vector_of_union[1].Set(b);
1571     buffer.test_vector_of_union[2].Set(c);
1572 
1573     flatbuffers::FlatBufferBuilder fbb;
1574     auto offset = D::Pack(fbb, &buffer);
1575     fbb.Finish(offset);
1576 
1577     auto *root =
1578     flatbuffers::GetRoot<D>(fbb.GetBufferPointer());
1579     DT unpacked;
1580     root->UnPackTo(&unpacked);
1581 
1582     TEST_ASSERT(unpacked.test_union == buffer.test_union);
1583     TEST_ASSERT(unpacked.test_vector_of_union == buffer.test_vector_of_union);
1584 
1585 }
1586 
Offset64Tests()1587 static void Offset64Tests() {
1588 #if INCLUDE_64_BIT_TESTS
1589   Offset64Test();
1590   Offset64SerializedFirst();
1591   Offset64NestedFlatBuffer();
1592   Offset64CreateDirect();
1593   Offset64Evolution();
1594   Offset64VectorOfStructs();
1595   Offset64SizePrefix();
1596   Offset64ManyVectors();
1597   Offset64ForceAlign();
1598 #endif
1599 }
1600 
FlatBufferTests(const std::string & tests_data_path)1601 int FlatBufferTests(const std::string &tests_data_path) {
1602   // Run our various test suites:
1603 
1604   std::string rawbuf;
1605   auto flatbuf1 = CreateFlatBufferTest(rawbuf);
1606   auto flatbuf = std::move(flatbuf1);  // Test move assignment.
1607 
1608   AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()),
1609                        rawbuf.length());
1610   AccessFlatBufferTest(flatbuf.data(), flatbuf.size());
1611 
1612   MutateFlatBuffersTest(flatbuf.data(), flatbuf.size());
1613 
1614   ObjectFlatBuffersTest(flatbuf.data());
1615   UnPackTo(flatbuf.data());
1616 
1617   MiniReflectFlatBuffersTest(flatbuf.data());
1618   MiniReflectFixedLengthArrayTest();
1619 
1620   SizePrefixedTest();
1621 
1622   AlignmentTest();
1623 
1624 #ifndef FLATBUFFERS_NO_FILE_TESTS
1625   ParseAndGenerateTextTest(tests_data_path, false);
1626   ParseAndGenerateTextTest(tests_data_path, true);
1627   FixedLengthArrayJsonTest(tests_data_path, false);
1628   FixedLengthArrayJsonTest(tests_data_path, true);
1629   ReflectionTest(tests_data_path, flatbuf.data(), flatbuf.size());
1630   ParseProtoTest(tests_data_path);
1631   EvolutionTest(tests_data_path);
1632   UnionDeprecationTest(tests_data_path);
1633   UnionVectorTest(tests_data_path);
1634   GenerateTableTextTest(tests_data_path);
1635   TestEmbeddedBinarySchema(tests_data_path);
1636   JsonOptionalTest(tests_data_path, false);
1637   JsonOptionalTest(tests_data_path, true);
1638   MultiFileNameClashTest(tests_data_path);
1639   InvalidNestedFlatbufferTest(tests_data_path);
1640   JsonDefaultTest(tests_data_path);
1641   JsonEnumsTest(tests_data_path);
1642   TestMonsterExtraFloats(tests_data_path);
1643   ParseIncorrectMonsterJsonTest(tests_data_path);
1644   FixedLengthArraySpanTest(tests_data_path);
1645   DoNotRequireEofTest(tests_data_path);
1646   JsonUnionStructTest();
1647 #else
1648   // Guard against -Wunused-parameter.
1649   (void)tests_data_path;
1650 #endif
1651 
1652   UtilConvertCase();
1653 
1654   FuzzTest1();
1655   FuzzTest2();
1656 
1657   TriviallyCopyableTest();
1658   ErrorTest();
1659   ValueTest();
1660   EnumValueTest();
1661   NestedListTest();
1662   EnumStringsTest();
1663   EnumNamesTest();
1664   EnumOutOfRangeTest();
1665   IntegerOutOfRangeTest();
1666   IntegerBoundaryTest();
1667   UnicodeTest();
1668   UnicodeTestAllowNonUTF8();
1669   UnicodeTestGenerateTextFailsOnNonUTF8();
1670   UnicodeSurrogatesTest();
1671   UnicodeInvalidSurrogatesTest();
1672   InvalidUTF8Test();
1673   UnknownFieldsTest();
1674   ParseUnionTest();
1675   ValidSameNameDifferentNamespaceTest();
1676   ConformTest();
1677   ParseProtoBufAsciiTest();
1678   TypeAliasesTest();
1679   EndianSwapTest();
1680   CreateSharedStringTest();
1681   FlexBuffersTest();
1682   FlexBuffersReuseBugTest();
1683   FlexBuffersDeprecatedTest();
1684   UninitializedVectorTest();
1685   EqualOperatorTest();
1686   NumericUtilsTest();
1687   IsAsciiUtilsTest();
1688   ValidFloatTest();
1689   InvalidFloatTest();
1690   FixedLengthArrayTest();
1691   NativeTypeTest();
1692   OptionalScalarsTest();
1693   ParseFlexbuffersFromJsonWithNullTest();
1694   FlatbuffersSpanTest();
1695   FixedLengthArrayConstructorTest();
1696   FixedLengthArrayOperatorEqualTest();
1697   FieldIdentifierTest();
1698   StringVectorDefaultsTest();
1699   FlexBuffersFloatingPointTest();
1700   FlatbuffersIteratorsTest();
1701   WarningsAsErrorsTest();
1702   NestedVerifierTest();
1703   PrivateAnnotationsLeaks();
1704   JsonUnsortedArrayTest();
1705   VectorSpanTest();
1706   NativeInlineTableVectorTest();
1707   FixedSizedScalarKeyInStructTest();
1708   StructKeyInStructTest();
1709   NestedStructKeyInStructTest();
1710   FixedSizedStructArrayKeyInStructTest();
1711   EmbeddedSchemaAccess();
1712   Offset64Tests();
1713   UnionUnderlyingTypeTest();
1714   return 0;
1715 }
1716 }  // namespace
1717 }  // namespace tests
1718 }  // namespace flatbuffers
1719 
main(int argc,const char * argv[])1720 int main(int argc, const char *argv[]) {
1721   std::string tests_data_path = "tests/";
1722 
1723   for (int argi = 1; argi < argc; argi++) {
1724     std::string arg = argv[argi];
1725     if (arg == "--test_path") {
1726       if (++argi >= argc) {
1727         fprintf(stderr, "error: missing path following: %s\n", arg.c_str());
1728         exit(1);
1729       }
1730       // Override default path if provided one.
1731       tests_data_path = argv[argi];
1732 
1733     } else {
1734       fprintf(stderr, "error: Unknown argument: %s\n", arg.c_str());
1735       exit(1);
1736     }
1737   }
1738 
1739   InitTestEngine();
1740 
1741   std::string req_locale;
1742   if (flatbuffers::ReadEnvironmentVariable("FLATBUFFERS_TEST_LOCALE",
1743                                            &req_locale)) {
1744     TEST_OUTPUT_LINE("The environment variable FLATBUFFERS_TEST_LOCALE=%s",
1745                      req_locale.c_str());
1746     req_locale = flatbuffers::RemoveStringQuotes(req_locale);
1747     std::string the_locale;
1748     TEST_ASSERT_FUNC(
1749         flatbuffers::SetGlobalTestLocale(req_locale.c_str(), &the_locale));
1750     TEST_OUTPUT_LINE("The global C-locale changed: %s", the_locale.c_str());
1751   }
1752 
1753 #ifdef FLATBUFFERS_TEST_PATH_PREFIX
1754   tests_data_path =
1755       FLATBUFFERS_STRING(FLATBUFFERS_TEST_PATH_PREFIX) + tests_data_path;
1756 #endif
1757 
1758   flatbuffers::tests::FlatBufferTests(tests_data_path);
1759   FlatBufferBuilderTest();
1760 
1761   if (!testing_fails) {
1762     TEST_OUTPUT_LINE("ALL TESTS PASSED");
1763   } else {
1764     TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
1765   }
1766   return CloseTestEngine();
1767 }
1768