Kotlin test optional enum (#6201)
[platform/upstream/flatbuffers.git] / tests / test.cpp
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 <cmath>
17
18 #include "flatbuffers/flatbuffers.h"
19 #include "flatbuffers/idl.h"
20 #include "flatbuffers/minireflect.h"
21 #include "flatbuffers/registry.h"
22 #include "flatbuffers/util.h"
23
24 // clang-format off
25 #ifdef FLATBUFFERS_CPP98_STL
26   namespace std {
27     using flatbuffers::unique_ptr;
28   }
29 #endif
30 // clang-format on
31
32 #include "monster_test_generated.h"
33 #include "namespace_test/namespace_test1_generated.h"
34 #include "namespace_test/namespace_test2_generated.h"
35 #include "union_vector/union_vector_generated.h"
36 #include "monster_extra_generated.h"
37 #include "optional_scalars_generated.h"
38 #if !defined(_MSC_VER) || _MSC_VER >= 1700
39 #  include "arrays_test_generated.h"
40 #  include "evolution_test/evolution_v1_generated.h"
41 #  include "evolution_test/evolution_v2_generated.h"
42 #endif
43
44 #include "native_type_test_generated.h"
45 #include "test_assert.h"
46
47 #include "flatbuffers/flexbuffers.h"
48 #include "monster_test_bfbs_generated.h"  // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed
49
50 // clang-format off
51 // Check that char* and uint8_t* are interoperable types.
52 // The reinterpret_cast<> between the pointers are used to simplify data loading.
53 static_assert(flatbuffers::is_same<uint8_t, char>::value ||
54               flatbuffers::is_same<uint8_t, unsigned char>::value,
55               "unexpected uint8_t type");
56
57 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
58   // Ensure IEEE-754 support if tests of floats with NaN/Inf will run.
59   static_assert(std::numeric_limits<float>::is_iec559 &&
60                 std::numeric_limits<double>::is_iec559,
61                 "IEC-559 (IEEE-754) standard required");
62 #endif
63 // clang-format on
64
65 // Shortcuts for the infinity.
66 static const auto infinityf = std::numeric_limits<float>::infinity();
67 static const auto infinityd = std::numeric_limits<double>::infinity();
68
69 using namespace MyGame::Example;
70
71 void FlatBufferBuilderTest();
72
73 // Include simple random number generator to ensure results will be the
74 // same cross platform.
75 // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
76 uint32_t lcg_seed = 48271;
77 uint32_t lcg_rand() {
78   return lcg_seed =
79              (static_cast<uint64_t>(lcg_seed) * 279470273UL) % 4294967291UL;
80 }
81 void lcg_reset() { lcg_seed = 48271; }
82
83 std::string test_data_path =
84 #ifdef BAZEL_TEST_DATA_PATH
85     "../com_github_google_flatbuffers/tests/";
86 #else
87     "tests/";
88 #endif
89
90 // example of how to build up a serialized buffer algorithmically:
91 flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
92   flatbuffers::FlatBufferBuilder builder;
93
94   auto vec = Vec3(1, 2, 3, 0, Color_Red, Test(10, 20));
95
96   auto name = builder.CreateString("MyMonster");
97
98   unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
99   auto inventory = builder.CreateVector(inv_data, 10);
100
101   // Alternatively, create the vector first, and fill in data later:
102   // unsigned char *inv_buf = nullptr;
103   // auto inventory = builder.CreateUninitializedVector<unsigned char>(
104   //                                                              10, &inv_buf);
105   // memcpy(inv_buf, inv_data, 10);
106
107   Test tests[] = { Test(10, 20), Test(30, 40) };
108   auto testv = builder.CreateVectorOfStructs(tests, 2);
109
110   // clang-format off
111   #ifndef FLATBUFFERS_CPP98_STL
112     // Create a vector of structures from a lambda.
113     auto testv2 = builder.CreateVectorOfStructs<Test>(
114           2, [&](size_t i, Test* s) -> void {
115             *s = tests[i];
116           });
117   #else
118     // Create a vector of structures using a plain old C++ function.
119     auto testv2 = builder.CreateVectorOfStructs<Test>(
120           2, [](size_t i, Test* s, void *state) -> void {
121             *s = (reinterpret_cast<Test*>(state))[i];
122           }, tests);
123   #endif  // FLATBUFFERS_CPP98_STL
124   // clang-format on
125
126   // create monster with very few fields set:
127   // (same functionality as CreateMonster below, but sets fields manually)
128   flatbuffers::Offset<Monster> mlocs[3];
129   auto fred = builder.CreateString("Fred");
130   auto barney = builder.CreateString("Barney");
131   auto wilma = builder.CreateString("Wilma");
132   MonsterBuilder mb1(builder);
133   mb1.add_name(fred);
134   mlocs[0] = mb1.Finish();
135   MonsterBuilder mb2(builder);
136   mb2.add_name(barney);
137   mb2.add_hp(1000);
138   mlocs[1] = mb2.Finish();
139   MonsterBuilder mb3(builder);
140   mb3.add_name(wilma);
141   mlocs[2] = mb3.Finish();
142
143   // Create an array of strings. Also test string pooling, and lambdas.
144   auto vecofstrings =
145       builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(
146           4,
147           [](size_t i, flatbuffers::FlatBufferBuilder *b)
148               -> flatbuffers::Offset<flatbuffers::String> {
149             static const char *names[] = { "bob", "fred", "bob", "fred" };
150             return b->CreateSharedString(names[i]);
151           },
152           &builder);
153
154   // Creating vectors of strings in one convenient call.
155   std::vector<std::string> names2;
156   names2.push_back("jane");
157   names2.push_back("mary");
158   auto vecofstrings2 = builder.CreateVectorOfStrings(names2);
159
160   // Create an array of sorted tables, can be used with binary search when read:
161   auto vecoftables = builder.CreateVectorOfSortedTables(mlocs, 3);
162
163   // Create an array of sorted structs,
164   // can be used with binary search when read:
165   std::vector<Ability> abilities;
166   abilities.push_back(Ability(4, 40));
167   abilities.push_back(Ability(3, 30));
168   abilities.push_back(Ability(2, 20));
169   abilities.push_back(Ability(1, 10));
170   auto vecofstructs = builder.CreateVectorOfSortedStructs(&abilities);
171
172   // Create a nested FlatBuffer.
173   // Nested FlatBuffers are stored in a ubyte vector, which can be convenient
174   // since they can be memcpy'd around much easier than other FlatBuffer
175   // values. They have little overhead compared to storing the table directly.
176   // As a test, create a mostly empty Monster buffer:
177   flatbuffers::FlatBufferBuilder nested_builder;
178   auto nmloc = CreateMonster(nested_builder, nullptr, 0, 0,
179                              nested_builder.CreateString("NestedMonster"));
180   FinishMonsterBuffer(nested_builder, nmloc);
181   // Now we can store the buffer in the parent. Note that by default, vectors
182   // are only aligned to their elements or size field, so in this case if the
183   // buffer contains 64-bit elements, they may not be correctly aligned. We fix
184   // that with:
185   builder.ForceVectorAlignment(nested_builder.GetSize(), sizeof(uint8_t),
186                                nested_builder.GetBufferMinAlignment());
187   // If for whatever reason you don't have the nested_builder available, you
188   // can substitute flatbuffers::largest_scalar_t (64-bit) for the alignment, or
189   // the largest force_align value in your schema if you're using it.
190   auto nested_flatbuffer_vector = builder.CreateVector(
191       nested_builder.GetBufferPointer(), nested_builder.GetSize());
192
193   // Test a nested FlexBuffer:
194   flexbuffers::Builder flexbuild;
195   flexbuild.Int(1234);
196   flexbuild.Finish();
197   auto flex = builder.CreateVector(flexbuild.GetBuffer());
198
199   // Test vector of enums.
200   Color colors[] = { Color_Blue, Color_Green };
201   // We use this special creation function because we have an array of
202   // pre-C++11 (enum class) enums whose size likely is int, yet its declared
203   // type in the schema is byte.
204   auto vecofcolors = builder.CreateVectorScalarCast<uint8_t, Color>(colors, 2);
205
206   // shortcut for creating monster with all fields set:
207   auto mloc = CreateMonster(
208       builder, &vec, 150, 80, name, inventory, Color_Blue, Any_Monster,
209       mlocs[1].Union(),  // Store a union.
210       testv, vecofstrings, vecoftables, 0, nested_flatbuffer_vector, 0, false,
211       0, 0, 0, 0, 0, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, vecofstrings2,
212       vecofstructs, flex, testv2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213       AnyUniqueAliases_NONE, 0, AnyAmbiguousAliases_NONE, 0, vecofcolors);
214
215   FinishMonsterBuffer(builder, mloc);
216
217   // clang-format off
218   #ifdef FLATBUFFERS_TEST_VERBOSE
219   // print byte data for debugging:
220   auto p = builder.GetBufferPointer();
221   for (flatbuffers::uoffset_t i = 0; i < builder.GetSize(); i++)
222     printf("%d ", p[i]);
223   #endif
224   // clang-format on
225
226   // return the buffer for the caller to use.
227   auto bufferpointer =
228       reinterpret_cast<const char *>(builder.GetBufferPointer());
229   buffer.assign(bufferpointer, bufferpointer + builder.GetSize());
230
231   return builder.Release();
232 }
233
234 //  example of accessing a buffer loaded in memory:
235 void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length,
236                           bool pooled = true) {
237   // First, verify the buffers integrity (optional)
238   flatbuffers::Verifier verifier(flatbuf, length);
239   TEST_EQ(VerifyMonsterBuffer(verifier), true);
240
241   // clang-format off
242   #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
243     std::vector<uint8_t> test_buff;
244     test_buff.resize(length * 2);
245     std::memcpy(&test_buff[0], flatbuf, length);
246     std::memcpy(&test_buff[length], flatbuf, length);
247
248     flatbuffers::Verifier verifier1(&test_buff[0], length);
249     TEST_EQ(VerifyMonsterBuffer(verifier1), true);
250     TEST_EQ(verifier1.GetComputedSize(), length);
251
252     flatbuffers::Verifier verifier2(&test_buff[length], length);
253     TEST_EQ(VerifyMonsterBuffer(verifier2), true);
254     TEST_EQ(verifier2.GetComputedSize(), length);
255   #endif
256   // clang-format on
257
258   TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0);
259   TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true);
260   TEST_EQ(strcmp(MonsterExtension(), "mon"), 0);
261
262   // Access the buffer from the root.
263   auto monster = GetMonster(flatbuf);
264
265   TEST_EQ(monster->hp(), 80);
266   TEST_EQ(monster->mana(), 150);  // default
267   TEST_EQ_STR(monster->name()->c_str(), "MyMonster");
268   // Can't access the following field, it is deprecated in the schema,
269   // which means accessors are not generated:
270   // monster.friendly()
271
272   auto pos = monster->pos();
273   TEST_NOTNULL(pos);
274   TEST_EQ(pos->z(), 3);
275   TEST_EQ(pos->test3().a(), 10);
276   TEST_EQ(pos->test3().b(), 20);
277
278   auto inventory = monster->inventory();
279   TEST_EQ(VectorLength(inventory), 10UL);  // Works even if inventory is null.
280   TEST_NOTNULL(inventory);
281   unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
282   // Check compatibilty of iterators with STL.
283   std::vector<unsigned char> inv_vec(inventory->begin(), inventory->end());
284   int n = 0;
285   for (auto it = inventory->begin(); it != inventory->end(); ++it, ++n) {
286     auto indx = it - inventory->begin();
287     TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
288     TEST_EQ(*it, inv_data[indx]);
289   }
290   TEST_EQ(n, inv_vec.size());
291
292   n = 0;
293   for (auto it = inventory->cbegin(); it != inventory->cend(); ++it, ++n) {
294     auto indx = it - inventory->cbegin();
295     TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
296     TEST_EQ(*it, inv_data[indx]);
297   }
298   TEST_EQ(n, inv_vec.size());
299
300   n = 0;
301   for (auto it = inventory->rbegin(); it != inventory->rend(); ++it, ++n) {
302     auto indx = inventory->rend() - it - 1;
303     TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
304     TEST_EQ(*it, inv_data[indx]);
305   }
306   TEST_EQ(n, inv_vec.size());
307
308   n = 0;
309   for (auto it = inventory->crbegin(); it != inventory->crend(); ++it, ++n) {
310     auto indx = inventory->crend() - it - 1;
311     TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
312     TEST_EQ(*it, inv_data[indx]);
313   }
314   TEST_EQ(n, inv_vec.size());
315
316   TEST_EQ(monster->color(), Color_Blue);
317
318   // Example of accessing a union:
319   TEST_EQ(monster->test_type(), Any_Monster);  // First make sure which it is.
320   auto monster2 = reinterpret_cast<const Monster *>(monster->test());
321   TEST_NOTNULL(monster2);
322   TEST_EQ_STR(monster2->name()->c_str(), "Fred");
323
324   // Example of accessing a vector of strings:
325   auto vecofstrings = monster->testarrayofstring();
326   TEST_EQ(vecofstrings->size(), 4U);
327   TEST_EQ_STR(vecofstrings->Get(0)->c_str(), "bob");
328   TEST_EQ_STR(vecofstrings->Get(1)->c_str(), "fred");
329   if (pooled) {
330     // These should have pointer equality because of string pooling.
331     TEST_EQ(vecofstrings->Get(0)->c_str(), vecofstrings->Get(2)->c_str());
332     TEST_EQ(vecofstrings->Get(1)->c_str(), vecofstrings->Get(3)->c_str());
333   }
334
335   auto vecofstrings2 = monster->testarrayofstring2();
336   if (vecofstrings2) {
337     TEST_EQ(vecofstrings2->size(), 2U);
338     TEST_EQ_STR(vecofstrings2->Get(0)->c_str(), "jane");
339     TEST_EQ_STR(vecofstrings2->Get(1)->c_str(), "mary");
340   }
341
342   // Example of accessing a vector of tables:
343   auto vecoftables = monster->testarrayoftables();
344   TEST_EQ(vecoftables->size(), 3U);
345   for (auto it = vecoftables->begin(); it != vecoftables->end(); ++it) {
346     TEST_EQ(strlen(it->name()->c_str()) >= 4, true);
347   }
348   TEST_EQ_STR(vecoftables->Get(0)->name()->c_str(), "Barney");
349   TEST_EQ(vecoftables->Get(0)->hp(), 1000);
350   TEST_EQ_STR(vecoftables->Get(1)->name()->c_str(), "Fred");
351   TEST_EQ_STR(vecoftables->Get(2)->name()->c_str(), "Wilma");
352   TEST_NOTNULL(vecoftables->LookupByKey("Barney"));
353   TEST_NOTNULL(vecoftables->LookupByKey("Fred"));
354   TEST_NOTNULL(vecoftables->LookupByKey("Wilma"));
355
356   // Test accessing a vector of sorted structs
357   auto vecofstructs = monster->testarrayofsortedstruct();
358   if (vecofstructs) {  // not filled in monster_test.bfbs
359     for (flatbuffers::uoffset_t i = 0; i < vecofstructs->size() - 1; i++) {
360       auto left = vecofstructs->Get(i);
361       auto right = vecofstructs->Get(i + 1);
362       TEST_EQ(true, (left->KeyCompareLessThan(right)));
363     }
364     TEST_NOTNULL(vecofstructs->LookupByKey(3));
365     TEST_EQ(static_cast<const Ability *>(nullptr),
366             vecofstructs->LookupByKey(5));
367   }
368
369   // Test nested FlatBuffers if available:
370   auto nested_buffer = monster->testnestedflatbuffer();
371   if (nested_buffer) {
372     // nested_buffer is a vector of bytes you can memcpy. However, if you
373     // actually want to access the nested data, this is a convenient
374     // accessor that directly gives you the root table:
375     auto nested_monster = monster->testnestedflatbuffer_nested_root();
376     TEST_EQ_STR(nested_monster->name()->c_str(), "NestedMonster");
377   }
378
379   // Test flexbuffer if available:
380   auto flex = monster->flex();
381   // flex is a vector of bytes you can memcpy etc.
382   TEST_EQ(flex->size(), 4);  // Encoded FlexBuffer bytes.
383   // However, if you actually want to access the nested data, this is a
384   // convenient accessor that directly gives you the root value:
385   TEST_EQ(monster->flex_flexbuffer_root().AsInt16(), 1234);
386
387   // Test vector of enums:
388   auto colors = monster->vector_of_enums();
389   if (colors) {
390     TEST_EQ(colors->size(), 2);
391     TEST_EQ(colors->Get(0), Color_Blue);
392     TEST_EQ(colors->Get(1), Color_Green);
393   }
394
395   // Since Flatbuffers uses explicit mechanisms to override the default
396   // compiler alignment, double check that the compiler indeed obeys them:
397   // (Test consists of a short and byte):
398   TEST_EQ(flatbuffers::AlignOf<Test>(), 2UL);
399   TEST_EQ(sizeof(Test), 4UL);
400
401   const flatbuffers::Vector<const Test *> *tests_array[] = {
402     monster->test4(),
403     monster->test5(),
404   };
405   for (size_t i = 0; i < sizeof(tests_array) / sizeof(tests_array[0]); ++i) {
406     auto tests = tests_array[i];
407     TEST_NOTNULL(tests);
408     auto test_0 = tests->Get(0);
409     auto test_1 = tests->Get(1);
410     TEST_EQ(test_0->a(), 10);
411     TEST_EQ(test_0->b(), 20);
412     TEST_EQ(test_1->a(), 30);
413     TEST_EQ(test_1->b(), 40);
414     for (auto it = tests->begin(); it != tests->end(); ++it) {
415       TEST_EQ(it->a() == 10 || it->a() == 30, true);  // Just testing iterators.
416     }
417   }
418
419   // Checking for presence of fields:
420   TEST_EQ(flatbuffers::IsFieldPresent(monster, Monster::VT_HP), true);
421   TEST_EQ(flatbuffers::IsFieldPresent(monster, Monster::VT_MANA), false);
422
423   // Obtaining a buffer from a root:
424   TEST_EQ(GetBufferStartFromRootPointer(monster), flatbuf);
425 }
426
427 // Change a FlatBuffer in-place, after it has been constructed.
428 void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
429   // Get non-const pointer to root.
430   auto monster = GetMutableMonster(flatbuf);
431
432   // Each of these tests mutates, then tests, then set back to the original,
433   // so we can test that the buffer in the end still passes our original test.
434   auto hp_ok = monster->mutate_hp(10);
435   TEST_EQ(hp_ok, true);  // Field was present.
436   TEST_EQ(monster->hp(), 10);
437   // Mutate to default value
438   auto hp_ok_default = monster->mutate_hp(100);
439   TEST_EQ(hp_ok_default, true);  // Field was present.
440   TEST_EQ(monster->hp(), 100);
441   // Test that mutate to default above keeps field valid for further mutations
442   auto hp_ok_2 = monster->mutate_hp(20);
443   TEST_EQ(hp_ok_2, true);
444   TEST_EQ(monster->hp(), 20);
445   monster->mutate_hp(80);
446
447   // Monster originally at 150 mana (default value)
448   auto mana_default_ok = monster->mutate_mana(150);  // Mutate to default value.
449   TEST_EQ(mana_default_ok,
450           true);  // Mutation should succeed, because default value.
451   TEST_EQ(monster->mana(), 150);
452   auto mana_ok = monster->mutate_mana(10);
453   TEST_EQ(mana_ok, false);  // Field was NOT present, because default value.
454   TEST_EQ(monster->mana(), 150);
455
456   // Mutate structs.
457   auto pos = monster->mutable_pos();
458   auto test3 = pos->mutable_test3();  // Struct inside a struct.
459   test3.mutate_a(50);                 // Struct fields never fail.
460   TEST_EQ(test3.a(), 50);
461   test3.mutate_a(10);
462
463   // Mutate vectors.
464   auto inventory = monster->mutable_inventory();
465   inventory->Mutate(9, 100);
466   TEST_EQ(inventory->Get(9), 100);
467   inventory->Mutate(9, 9);
468
469   auto tables = monster->mutable_testarrayoftables();
470   auto first = tables->GetMutableObject(0);
471   TEST_EQ(first->hp(), 1000);
472   first->mutate_hp(0);
473   TEST_EQ(first->hp(), 0);
474   first->mutate_hp(1000);
475
476   // Run the verifier and the regular test to make sure we didn't trample on
477   // anything.
478   AccessFlatBufferTest(flatbuf, length);
479 }
480
481 // Unpack a FlatBuffer into objects.
482 void ObjectFlatBuffersTest(uint8_t *flatbuf) {
483   // Optional: we can specify resolver and rehasher functions to turn hashed
484   // strings into object pointers and back, to implement remote references
485   // and such.
486   auto resolver = flatbuffers::resolver_function_t(
487       [](void **pointer_adr, flatbuffers::hash_value_t hash) {
488         (void)pointer_adr;
489         (void)hash;
490         // Don't actually do anything, leave variable null.
491       });
492   auto rehasher = flatbuffers::rehasher_function_t(
493       [](void *pointer) -> flatbuffers::hash_value_t {
494         (void)pointer;
495         return 0;
496       });
497
498   // Turn a buffer into C++ objects.
499   auto monster1 = UnPackMonster(flatbuf, &resolver);
500
501   // Re-serialize the data.
502   flatbuffers::FlatBufferBuilder fbb1;
503   fbb1.Finish(CreateMonster(fbb1, monster1.get(), &rehasher),
504               MonsterIdentifier());
505
506   // Unpack again, and re-serialize again.
507   auto monster2 = UnPackMonster(fbb1.GetBufferPointer(), &resolver);
508   flatbuffers::FlatBufferBuilder fbb2;
509   fbb2.Finish(CreateMonster(fbb2, monster2.get(), &rehasher),
510               MonsterIdentifier());
511
512   // Now we've gone full round-trip, the two buffers should match.
513   auto len1 = fbb1.GetSize();
514   auto len2 = fbb2.GetSize();
515   TEST_EQ(len1, len2);
516   TEST_EQ(memcmp(fbb1.GetBufferPointer(), fbb2.GetBufferPointer(), len1), 0);
517
518   // Test it with the original buffer test to make sure all data survived.
519   AccessFlatBufferTest(fbb2.GetBufferPointer(), len2, false);
520
521   // Test accessing fields, similar to AccessFlatBufferTest above.
522   TEST_EQ(monster2->hp, 80);
523   TEST_EQ(monster2->mana, 150);  // default
524   TEST_EQ_STR(monster2->name.c_str(), "MyMonster");
525
526   auto &pos = monster2->pos;
527   TEST_NOTNULL(pos);
528   TEST_EQ(pos->z(), 3);
529   TEST_EQ(pos->test3().a(), 10);
530   TEST_EQ(pos->test3().b(), 20);
531
532   auto &inventory = monster2->inventory;
533   TEST_EQ(inventory.size(), 10UL);
534   unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
535   for (auto it = inventory.begin(); it != inventory.end(); ++it)
536     TEST_EQ(*it, inv_data[it - inventory.begin()]);
537
538   TEST_EQ(monster2->color, Color_Blue);
539
540   auto monster3 = monster2->test.AsMonster();
541   TEST_NOTNULL(monster3);
542   TEST_EQ_STR(monster3->name.c_str(), "Fred");
543
544   auto &vecofstrings = monster2->testarrayofstring;
545   TEST_EQ(vecofstrings.size(), 4U);
546   TEST_EQ_STR(vecofstrings[0].c_str(), "bob");
547   TEST_EQ_STR(vecofstrings[1].c_str(), "fred");
548
549   auto &vecofstrings2 = monster2->testarrayofstring2;
550   TEST_EQ(vecofstrings2.size(), 2U);
551   TEST_EQ_STR(vecofstrings2[0].c_str(), "jane");
552   TEST_EQ_STR(vecofstrings2[1].c_str(), "mary");
553
554   auto &vecoftables = monster2->testarrayoftables;
555   TEST_EQ(vecoftables.size(), 3U);
556   TEST_EQ_STR(vecoftables[0]->name.c_str(), "Barney");
557   TEST_EQ(vecoftables[0]->hp, 1000);
558   TEST_EQ_STR(vecoftables[1]->name.c_str(), "Fred");
559   TEST_EQ_STR(vecoftables[2]->name.c_str(), "Wilma");
560
561   auto &tests = monster2->test4;
562   TEST_EQ(tests[0].a(), 10);
563   TEST_EQ(tests[0].b(), 20);
564   TEST_EQ(tests[1].a(), 30);
565   TEST_EQ(tests[1].b(), 40);
566 }
567
568 // Prefix a FlatBuffer with a size field.
569 void SizePrefixedTest() {
570   // Create size prefixed buffer.
571   flatbuffers::FlatBufferBuilder fbb;
572   FinishSizePrefixedMonsterBuffer(
573       fbb, CreateMonster(fbb, 0, 200, 300, fbb.CreateString("bob")));
574
575   // Verify it.
576   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
577   TEST_EQ(VerifySizePrefixedMonsterBuffer(verifier), true);
578
579   // Access it.
580   auto m = GetSizePrefixedMonster(fbb.GetBufferPointer());
581   TEST_EQ(m->mana(), 200);
582   TEST_EQ(m->hp(), 300);
583   TEST_EQ_STR(m->name()->c_str(), "bob");
584 }
585
586 void TriviallyCopyableTest() {
587   // clang-format off
588   #if __GNUG__ && __GNUC__ < 5
589     TEST_EQ(__has_trivial_copy(Vec3), true);
590   #else
591     #if __cplusplus >= 201103L
592       TEST_EQ(std::is_trivially_copyable<Vec3>::value, true);
593     #endif
594   #endif
595   // clang-format on
596 }
597
598 // Check stringify of an default enum value to json
599 void JsonDefaultTest() {
600   // load FlatBuffer schema (.fbs) from disk
601   std::string schemafile;
602   TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
603                                 false, &schemafile),
604           true);
605   // parse schema first, so we can use it to parse the data after
606   flatbuffers::Parser parser;
607   auto include_test_path =
608       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
609   const char *include_directories[] = { test_data_path.c_str(),
610                                         include_test_path.c_str(), nullptr };
611
612   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
613   // create incomplete monster and store to json
614   parser.opts.output_default_scalars_in_json = true;
615   parser.opts.output_enum_identifiers = true;
616   flatbuffers::FlatBufferBuilder builder;
617   auto name = builder.CreateString("default_enum");
618   MonsterBuilder color_monster(builder);
619   color_monster.add_name(name);
620   FinishMonsterBuffer(builder, color_monster.Finish());
621   std::string jsongen;
622   auto result = GenerateText(parser, builder.GetBufferPointer(), &jsongen);
623   TEST_EQ(result, true);
624   // default value of the "color" field is Blue
625   TEST_EQ(std::string::npos != jsongen.find("color: \"Blue\""), true);
626   // default value of the "testf" field is 3.14159
627   TEST_EQ(std::string::npos != jsongen.find("testf: 3.14159"), true);
628 }
629
630 void JsonEnumsTest() {
631   // load FlatBuffer schema (.fbs) from disk
632   std::string schemafile;
633   TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
634                                 false, &schemafile),
635           true);
636   // parse schema first, so we can use it to parse the data after
637   flatbuffers::Parser parser;
638   auto include_test_path =
639       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
640   const char *include_directories[] = { test_data_path.c_str(),
641                                         include_test_path.c_str(), nullptr };
642   parser.opts.output_enum_identifiers = true;
643   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
644   flatbuffers::FlatBufferBuilder builder;
645   auto name = builder.CreateString("bitflag_enum");
646   MonsterBuilder color_monster(builder);
647   color_monster.add_name(name);
648   color_monster.add_color(Color(Color_Blue | Color_Red));
649   FinishMonsterBuffer(builder, color_monster.Finish());
650   std::string jsongen;
651   auto result = GenerateText(parser, builder.GetBufferPointer(), &jsongen);
652   TEST_EQ(result, true);
653   TEST_EQ(std::string::npos != jsongen.find("color: \"Red Blue\""), true);
654   // Test forward compatibility with 'output_enum_identifiers = true'.
655   // Current Color doesn't have '(1u << 2)' field, let's add it.
656   builder.Clear();
657   std::string future_json;
658   auto future_name = builder.CreateString("future bitflag_enum");
659   MonsterBuilder future_color(builder);
660   future_color.add_name(future_name);
661   future_color.add_color(
662       static_cast<Color>((1u << 2) | Color_Blue | Color_Red));
663   FinishMonsterBuffer(builder, future_color.Finish());
664   result = GenerateText(parser, builder.GetBufferPointer(), &future_json);
665   TEST_EQ(result, true);
666   TEST_EQ(std::string::npos != future_json.find("color: 13"), true);
667 }
668
669 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
670 // The IEEE-754 quiet_NaN is not simple binary constant.
671 // All binary NaN bit strings have all the bits of the biased exponent field E
672 // set to 1. A quiet NaN bit string should be encoded with the first bit d[1]
673 // of the trailing significand field T being 1 (d[0] is implicit bit).
674 // It is assumed that endianness of floating-point is same as integer.
675 template<typename T, typename U, U qnan_base> bool is_quiet_nan_impl(T v) {
676   static_assert(sizeof(T) == sizeof(U), "unexpected");
677   U b = 0;
678   std::memcpy(&b, &v, sizeof(T));
679   return ((b & qnan_base) == qnan_base);
680 }
681 #if defined(__mips__) || defined(__hppa__)
682 static bool is_quiet_nan(float v) {
683   return is_quiet_nan_impl<float, uint32_t, 0x7FC00000u>(v) ||
684          is_quiet_nan_impl<float, uint32_t, 0x7FBFFFFFu>(v);
685 }
686 static bool is_quiet_nan(double v) {
687   return is_quiet_nan_impl<double, uint64_t, 0x7FF8000000000000ul>(v) ||
688          is_quiet_nan_impl<double, uint64_t, 0x7FF7FFFFFFFFFFFFu>(v);
689 }
690 #else
691 static bool is_quiet_nan(float v) {
692   return is_quiet_nan_impl<float, uint32_t, 0x7FC00000u>(v);
693 }
694 static bool is_quiet_nan(double v) {
695   return is_quiet_nan_impl<double, uint64_t, 0x7FF8000000000000ul>(v);
696 }
697 #endif
698
699 void TestMonsterExtraFloats() {
700   TEST_EQ(is_quiet_nan(1.0), false);
701   TEST_EQ(is_quiet_nan(infinityd), false);
702   TEST_EQ(is_quiet_nan(-infinityf), false);
703   TEST_EQ(is_quiet_nan(std::numeric_limits<float>::quiet_NaN()), true);
704   TEST_EQ(is_quiet_nan(std::numeric_limits<double>::quiet_NaN()), true);
705
706   using namespace flatbuffers;
707   using namespace MyGame;
708   // Load FlatBuffer schema (.fbs) from disk.
709   std::string schemafile;
710   TEST_EQ(LoadFile((test_data_path + "monster_extra.fbs").c_str(), false,
711                    &schemafile),
712           true);
713   // Parse schema first, so we can use it to parse the data after.
714   Parser parser;
715   auto include_test_path = ConCatPathFileName(test_data_path, "include_test");
716   const char *include_directories[] = { test_data_path.c_str(),
717                                         include_test_path.c_str(), nullptr };
718   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
719   // Create empty extra and store to json.
720   parser.opts.output_default_scalars_in_json = true;
721   parser.opts.output_enum_identifiers = true;
722   FlatBufferBuilder builder;
723   const auto def_root = MonsterExtraBuilder(builder).Finish();
724   FinishMonsterExtraBuffer(builder, def_root);
725   const auto def_obj = builder.GetBufferPointer();
726   const auto def_extra = GetMonsterExtra(def_obj);
727   TEST_NOTNULL(def_extra);
728   TEST_EQ(is_quiet_nan(def_extra->f0()), true);
729   TEST_EQ(is_quiet_nan(def_extra->f1()), true);
730   TEST_EQ(def_extra->f2(), +infinityf);
731   TEST_EQ(def_extra->f3(), -infinityf);
732   TEST_EQ(is_quiet_nan(def_extra->d0()), true);
733   TEST_EQ(is_quiet_nan(def_extra->d1()), true);
734   TEST_EQ(def_extra->d2(), +infinityd);
735   TEST_EQ(def_extra->d3(), -infinityd);
736   std::string jsongen;
737   auto result = GenerateText(parser, def_obj, &jsongen);
738   TEST_EQ(result, true);
739   // Check expected default values.
740   TEST_EQ(std::string::npos != jsongen.find("f0: nan"), true);
741   TEST_EQ(std::string::npos != jsongen.find("f1: nan"), true);
742   TEST_EQ(std::string::npos != jsongen.find("f2: inf"), true);
743   TEST_EQ(std::string::npos != jsongen.find("f3: -inf"), true);
744   TEST_EQ(std::string::npos != jsongen.find("d0: nan"), true);
745   TEST_EQ(std::string::npos != jsongen.find("d1: nan"), true);
746   TEST_EQ(std::string::npos != jsongen.find("d2: inf"), true);
747   TEST_EQ(std::string::npos != jsongen.find("d3: -inf"), true);
748   // Parse 'mosterdata_extra.json'.
749   const auto extra_base = test_data_path + "monsterdata_extra";
750   jsongen = "";
751   TEST_EQ(LoadFile((extra_base + ".json").c_str(), false, &jsongen), true);
752   TEST_EQ(parser.Parse(jsongen.c_str()), true);
753   const auto test_file = parser.builder_.GetBufferPointer();
754   const auto test_size = parser.builder_.GetSize();
755   Verifier verifier(test_file, test_size);
756   TEST_ASSERT(VerifyMonsterExtraBuffer(verifier));
757   const auto extra = GetMonsterExtra(test_file);
758   TEST_NOTNULL(extra);
759   TEST_EQ(is_quiet_nan(extra->f0()), true);
760   TEST_EQ(is_quiet_nan(extra->f1()), true);
761   TEST_EQ(extra->f2(), +infinityf);
762   TEST_EQ(extra->f3(), -infinityf);
763   TEST_EQ(is_quiet_nan(extra->d0()), true);
764   TEST_EQ(extra->d1(), +infinityd);
765   TEST_EQ(extra->d2(), -infinityd);
766   TEST_EQ(is_quiet_nan(extra->d3()), true);
767   TEST_NOTNULL(extra->fvec());
768   TEST_EQ(extra->fvec()->size(), 4);
769   TEST_EQ(extra->fvec()->Get(0), 1.0f);
770   TEST_EQ(extra->fvec()->Get(1), -infinityf);
771   TEST_EQ(extra->fvec()->Get(2), +infinityf);
772   TEST_EQ(is_quiet_nan(extra->fvec()->Get(3)), true);
773   TEST_NOTNULL(extra->dvec());
774   TEST_EQ(extra->dvec()->size(), 4);
775   TEST_EQ(extra->dvec()->Get(0), 2.0);
776   TEST_EQ(extra->dvec()->Get(1), +infinityd);
777   TEST_EQ(extra->dvec()->Get(2), -infinityd);
778   TEST_EQ(is_quiet_nan(extra->dvec()->Get(3)), true);
779 }
780 #else
781 void TestMonsterExtraFloats() {}
782 #endif
783
784 // example of parsing text straight into a buffer, and generating
785 // text back from it:
786 void ParseAndGenerateTextTest(bool binary) {
787   // load FlatBuffer schema (.fbs) and JSON from disk
788   std::string schemafile;
789   std::string jsonfile;
790   TEST_EQ(flatbuffers::LoadFile(
791               (test_data_path + "monster_test." + (binary ? "bfbs" : "fbs"))
792                   .c_str(),
793               binary, &schemafile),
794           true);
795   TEST_EQ(flatbuffers::LoadFile(
796               (test_data_path + "monsterdata_test.golden").c_str(), false,
797               &jsonfile),
798           true);
799
800   auto include_test_path =
801       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
802   const char *include_directories[] = { test_data_path.c_str(),
803                                         include_test_path.c_str(), nullptr };
804
805   // parse schema first, so we can use it to parse the data after
806   flatbuffers::Parser parser;
807   if (binary) {
808     flatbuffers::Verifier verifier(
809         reinterpret_cast<const uint8_t *>(schemafile.c_str()),
810         schemafile.size());
811     TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
812     // auto schema = reflection::GetSchema(schemafile.c_str());
813     TEST_EQ(parser.Deserialize((const uint8_t *)schemafile.c_str(),
814                                schemafile.size()),
815             true);
816   } else {
817     TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
818   }
819   TEST_EQ(parser.Parse(jsonfile.c_str(), include_directories), true);
820
821   // here, parser.builder_ contains a binary buffer that is the parsed data.
822
823   // First, verify it, just in case:
824   flatbuffers::Verifier verifier(parser.builder_.GetBufferPointer(),
825                                  parser.builder_.GetSize());
826   TEST_EQ(VerifyMonsterBuffer(verifier), true);
827
828   AccessFlatBufferTest(parser.builder_.GetBufferPointer(),
829                        parser.builder_.GetSize(), false);
830
831   // to ensure it is correct, we now generate text back from the binary,
832   // and compare the two:
833   std::string jsongen;
834   auto result =
835       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
836   TEST_EQ(result, true);
837   TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str());
838
839   // We can also do the above using the convenient Registry that knows about
840   // a set of file_identifiers mapped to schemas.
841   flatbuffers::Registry registry;
842   // Make sure schemas can find their includes.
843   registry.AddIncludeDirectory(test_data_path.c_str());
844   registry.AddIncludeDirectory(include_test_path.c_str());
845   // Call this with many schemas if possible.
846   registry.Register(MonsterIdentifier(),
847                     (test_data_path + "monster_test.fbs").c_str());
848   // Now we got this set up, we can parse by just specifying the identifier,
849   // the correct schema will be loaded on the fly:
850   auto buf = registry.TextToFlatBuffer(jsonfile.c_str(), MonsterIdentifier());
851   // If this fails, check registry.lasterror_.
852   TEST_NOTNULL(buf.data());
853   // Test the buffer, to be sure:
854   AccessFlatBufferTest(buf.data(), buf.size(), false);
855   // We can use the registry to turn this back into text, in this case it
856   // will get the file_identifier from the binary:
857   std::string text;
858   auto ok = registry.FlatBufferToText(buf.data(), buf.size(), &text);
859   // If this fails, check registry.lasterror_.
860   TEST_EQ(ok, true);
861   TEST_EQ_STR(text.c_str(), jsonfile.c_str());
862
863   // Generate text for UTF-8 strings without escapes.
864   std::string jsonfile_utf8;
865   TEST_EQ(flatbuffers::LoadFile((test_data_path + "unicode_test.json").c_str(),
866                                 false, &jsonfile_utf8),
867           true);
868   TEST_EQ(parser.Parse(jsonfile_utf8.c_str(), include_directories), true);
869   // To ensure it is correct, generate utf-8 text back from the binary.
870   std::string jsongen_utf8;
871   // request natural printing for utf-8 strings
872   parser.opts.natural_utf8 = true;
873   parser.opts.strict_json = true;
874   TEST_EQ(
875       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen_utf8),
876       true);
877   TEST_EQ_STR(jsongen_utf8.c_str(), jsonfile_utf8.c_str());
878 }
879
880 void ReflectionTest(uint8_t *flatbuf, size_t length) {
881   // Load a binary schema.
882   std::string bfbsfile;
883   TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.bfbs").c_str(),
884                                 true, &bfbsfile),
885           true);
886
887   // Verify it, just in case:
888   flatbuffers::Verifier verifier(
889       reinterpret_cast<const uint8_t *>(bfbsfile.c_str()), bfbsfile.length());
890   TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
891
892   // Make sure the schema is what we expect it to be.
893   auto &schema = *reflection::GetSchema(bfbsfile.c_str());
894   auto root_table = schema.root_table();
895   TEST_EQ_STR(root_table->name()->c_str(), "MyGame.Example.Monster");
896   auto fields = root_table->fields();
897   auto hp_field_ptr = fields->LookupByKey("hp");
898   TEST_NOTNULL(hp_field_ptr);
899   auto &hp_field = *hp_field_ptr;
900   TEST_EQ_STR(hp_field.name()->c_str(), "hp");
901   TEST_EQ(hp_field.id(), 2);
902   TEST_EQ(hp_field.type()->base_type(), reflection::Short);
903
904   auto friendly_field_ptr = fields->LookupByKey("friendly");
905   TEST_NOTNULL(friendly_field_ptr);
906   TEST_NOTNULL(friendly_field_ptr->attributes());
907   TEST_NOTNULL(friendly_field_ptr->attributes()->LookupByKey("priority"));
908
909   // Make sure the table index is what we expect it to be.
910   auto pos_field_ptr = fields->LookupByKey("pos");
911   TEST_NOTNULL(pos_field_ptr);
912   TEST_EQ(pos_field_ptr->type()->base_type(), reflection::Obj);
913   auto pos_table_ptr = schema.objects()->Get(pos_field_ptr->type()->index());
914   TEST_NOTNULL(pos_table_ptr);
915   TEST_EQ_STR(pos_table_ptr->name()->c_str(), "MyGame.Example.Vec3");
916
917   // Test nullability of fields: hp is a 0-default scalar, pos is a struct =>
918   // optional, and name is a required string => not optional.
919   TEST_EQ(hp_field.optional(), false);
920   TEST_EQ(pos_field_ptr->optional(), true);
921   TEST_EQ(fields->LookupByKey("name")->optional(), false);
922
923   // Now use it to dynamically access a buffer.
924   auto &root = *flatbuffers::GetAnyRoot(flatbuf);
925
926   // Verify the buffer first using reflection based verification
927   TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), flatbuf, length),
928           true);
929
930   auto hp = flatbuffers::GetFieldI<uint16_t>(root, hp_field);
931   TEST_EQ(hp, 80);
932
933   // Rather than needing to know the type, we can also get the value of
934   // any field as an int64_t/double/string, regardless of what it actually is.
935   auto hp_int64 = flatbuffers::GetAnyFieldI(root, hp_field);
936   TEST_EQ(hp_int64, 80);
937   auto hp_double = flatbuffers::GetAnyFieldF(root, hp_field);
938   TEST_EQ(hp_double, 80.0);
939   auto hp_string = flatbuffers::GetAnyFieldS(root, hp_field, &schema);
940   TEST_EQ_STR(hp_string.c_str(), "80");
941
942   // Get struct field through reflection
943   auto pos_struct = flatbuffers::GetFieldStruct(root, *pos_field_ptr);
944   TEST_NOTNULL(pos_struct);
945   TEST_EQ(flatbuffers::GetAnyFieldF(*pos_struct,
946                                     *pos_table_ptr->fields()->LookupByKey("z")),
947           3.0f);
948
949   auto test3_field = pos_table_ptr->fields()->LookupByKey("test3");
950   auto test3_struct = flatbuffers::GetFieldStruct(*pos_struct, *test3_field);
951   TEST_NOTNULL(test3_struct);
952   auto test3_object = schema.objects()->Get(test3_field->type()->index());
953
954   TEST_EQ(flatbuffers::GetAnyFieldF(*test3_struct,
955                                     *test3_object->fields()->LookupByKey("a")),
956           10);
957
958   // We can also modify it.
959   flatbuffers::SetField<uint16_t>(&root, hp_field, 200);
960   hp = flatbuffers::GetFieldI<uint16_t>(root, hp_field);
961   TEST_EQ(hp, 200);
962
963   // We can also set fields generically:
964   flatbuffers::SetAnyFieldI(&root, hp_field, 300);
965   hp_int64 = flatbuffers::GetAnyFieldI(root, hp_field);
966   TEST_EQ(hp_int64, 300);
967   flatbuffers::SetAnyFieldF(&root, hp_field, 300.5);
968   hp_int64 = flatbuffers::GetAnyFieldI(root, hp_field);
969   TEST_EQ(hp_int64, 300);
970   flatbuffers::SetAnyFieldS(&root, hp_field, "300");
971   hp_int64 = flatbuffers::GetAnyFieldI(root, hp_field);
972   TEST_EQ(hp_int64, 300);
973
974   // Test buffer is valid after the modifications
975   TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), flatbuf, length),
976           true);
977
978   // Reset it, for further tests.
979   flatbuffers::SetField<uint16_t>(&root, hp_field, 80);
980
981   // More advanced functionality: changing the size of items in-line!
982   // First we put the FlatBuffer inside an std::vector.
983   std::vector<uint8_t> resizingbuf(flatbuf, flatbuf + length);
984   // Find the field we want to modify.
985   auto &name_field = *fields->LookupByKey("name");
986   // Get the root.
987   // This time we wrap the result from GetAnyRoot in a smartpointer that
988   // will keep rroot valid as resizingbuf resizes.
989   auto rroot = flatbuffers::piv(
990       flatbuffers::GetAnyRoot(flatbuffers::vector_data(resizingbuf)),
991       resizingbuf);
992   SetString(schema, "totally new string", GetFieldS(**rroot, name_field),
993             &resizingbuf);
994   // Here resizingbuf has changed, but rroot is still valid.
995   TEST_EQ_STR(GetFieldS(**rroot, name_field)->c_str(), "totally new string");
996   // Now lets extend a vector by 100 elements (10 -> 110).
997   auto &inventory_field = *fields->LookupByKey("inventory");
998   auto rinventory = flatbuffers::piv(
999       flatbuffers::GetFieldV<uint8_t>(**rroot, inventory_field), resizingbuf);
1000   flatbuffers::ResizeVector<uint8_t>(schema, 110, 50, *rinventory,
1001                                      &resizingbuf);
1002   // rinventory still valid, so lets read from it.
1003   TEST_EQ(rinventory->Get(10), 50);
1004
1005   // For reflection uses not covered already, there is a more powerful way:
1006   // we can simply generate whatever object we want to add/modify in a
1007   // FlatBuffer of its own, then add that to an existing FlatBuffer:
1008   // As an example, let's add a string to an array of strings.
1009   // First, find our field:
1010   auto &testarrayofstring_field = *fields->LookupByKey("testarrayofstring");
1011   // Find the vector value:
1012   auto rtestarrayofstring = flatbuffers::piv(
1013       flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
1014           **rroot, testarrayofstring_field),
1015       resizingbuf);
1016   // It's a vector of 2 strings, to which we add one more, initialized to
1017   // offset 0.
1018   flatbuffers::ResizeVector<flatbuffers::Offset<flatbuffers::String>>(
1019       schema, 3, 0, *rtestarrayofstring, &resizingbuf);
1020   // Here we just create a buffer that contans a single string, but this
1021   // could also be any complex set of tables and other values.
1022   flatbuffers::FlatBufferBuilder stringfbb;
1023   stringfbb.Finish(stringfbb.CreateString("hank"));
1024   // Add the contents of it to our existing FlatBuffer.
1025   // We do this last, so the pointer doesn't get invalidated (since it is
1026   // at the end of the buffer):
1027   auto string_ptr = flatbuffers::AddFlatBuffer(
1028       resizingbuf, stringfbb.GetBufferPointer(), stringfbb.GetSize());
1029   // Finally, set the new value in the vector.
1030   rtestarrayofstring->MutateOffset(2, string_ptr);
1031   TEST_EQ_STR(rtestarrayofstring->Get(0)->c_str(), "bob");
1032   TEST_EQ_STR(rtestarrayofstring->Get(2)->c_str(), "hank");
1033   // Test integrity of all resize operations above.
1034   flatbuffers::Verifier resize_verifier(
1035       reinterpret_cast<const uint8_t *>(flatbuffers::vector_data(resizingbuf)),
1036       resizingbuf.size());
1037   TEST_EQ(VerifyMonsterBuffer(resize_verifier), true);
1038
1039   // Test buffer is valid using reflection as well
1040   TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(),
1041                               flatbuffers::vector_data(resizingbuf),
1042                               resizingbuf.size()),
1043           true);
1044
1045   // As an additional test, also set it on the name field.
1046   // Note: unlike the name change above, this just overwrites the offset,
1047   // rather than changing the string in-place.
1048   SetFieldT(*rroot, name_field, string_ptr);
1049   TEST_EQ_STR(GetFieldS(**rroot, name_field)->c_str(), "hank");
1050
1051   // Using reflection, rather than mutating binary FlatBuffers, we can also copy
1052   // tables and other things out of other FlatBuffers into a FlatBufferBuilder,
1053   // either part or whole.
1054   flatbuffers::FlatBufferBuilder fbb;
1055   auto root_offset = flatbuffers::CopyTable(
1056       fbb, schema, *root_table, *flatbuffers::GetAnyRoot(flatbuf), true);
1057   fbb.Finish(root_offset, MonsterIdentifier());
1058   // Test that it was copied correctly:
1059   AccessFlatBufferTest(fbb.GetBufferPointer(), fbb.GetSize());
1060
1061   // Test buffer is valid using reflection as well
1062   TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(),
1063                               fbb.GetBufferPointer(), fbb.GetSize()),
1064           true);
1065 }
1066
1067 void MiniReflectFlatBuffersTest(uint8_t *flatbuf) {
1068   auto s =
1069       flatbuffers::FlatBufferToString(flatbuf, Monster::MiniReflectTypeTable());
1070   TEST_EQ_STR(
1071       s.c_str(),
1072       "{ "
1073       "pos: { x: 1.0, y: 2.0, z: 3.0, test1: 0.0, test2: Red, test3: "
1074       "{ a: 10, b: 20 } }, "
1075       "hp: 80, "
1076       "name: \"MyMonster\", "
1077       "inventory: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], "
1078       "test_type: Monster, "
1079       "test: { name: \"Fred\" }, "
1080       "test4: [ { a: 10, b: 20 }, { a: 30, b: 40 } ], "
1081       "testarrayofstring: [ \"bob\", \"fred\", \"bob\", \"fred\" ], "
1082       "testarrayoftables: [ { hp: 1000, name: \"Barney\" }, { name: \"Fred\" "
1083       "}, "
1084       "{ name: \"Wilma\" } ], "
1085       // TODO(wvo): should really print this nested buffer correctly.
1086       "testnestedflatbuffer: [ 20, 0, 0, 0, 77, 79, 78, 83, 12, 0, 12, 0, 0, "
1087       "0, "
1088       "4, 0, 6, 0, 8, 0, 12, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 13, 0, 0, 0, 78, "
1089       "101, 115, 116, 101, 100, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0 ], "
1090       "testarrayofstring2: [ \"jane\", \"mary\" ], "
1091       "testarrayofsortedstruct: [ { id: 1, distance: 10 }, "
1092       "{ id: 2, distance: 20 }, { id: 3, distance: 30 }, "
1093       "{ id: 4, distance: 40 } ], "
1094       "flex: [ 210, 4, 5, 2 ], "
1095       "test5: [ { a: 10, b: 20 }, { a: 30, b: 40 } ], "
1096       "vector_of_enums: [ Blue, Green ] "
1097       "}");
1098
1099   Test test(16, 32);
1100   Vec3 vec(1, 2, 3, 1.5, Color_Red, test);
1101   flatbuffers::FlatBufferBuilder vec_builder;
1102   vec_builder.Finish(vec_builder.CreateStruct(vec));
1103   auto vec_buffer = vec_builder.Release();
1104   auto vec_str = flatbuffers::FlatBufferToString(vec_buffer.data(),
1105                                                  Vec3::MiniReflectTypeTable());
1106   TEST_EQ_STR(vec_str.c_str(),
1107               "{ x: 1.0, y: 2.0, z: 3.0, test1: 1.5, test2: Red, test3: { a: "
1108               "16, b: 32 } }");
1109 }
1110
1111 void MiniReflectFixedLengthArrayTest() {
1112   // VS10 does not support typed enums, exclude from tests
1113 #if !defined(_MSC_VER) || _MSC_VER >= 1700
1114   flatbuffers::FlatBufferBuilder fbb;
1115   MyGame::Example::ArrayStruct aStruct(2, 12, 1);
1116   auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
1117   fbb.Finish(aTable);
1118
1119   auto flatbuf = fbb.Release();
1120   auto s = flatbuffers::FlatBufferToString(
1121       flatbuf.data(), MyGame::Example::ArrayTableTypeTable());
1122   TEST_EQ_STR(
1123       "{ "
1124       "a: { a: 2.0, "
1125       "b: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], "
1126       "c: 12, "
1127       "d: [ { a: [ 0, 0 ], b: A, c: [ A, A ], d: [ 0, 0 ] }, "
1128       "{ a: [ 0, 0 ], b: A, c: [ A, A ], d: [ 0, 0 ] } ], "
1129       "e: 1, f: [ 0, 0 ] } "
1130       "}",
1131       s.c_str());
1132 #endif
1133 }
1134
1135 // Parse a .proto schema, output as .fbs
1136 void ParseProtoTest() {
1137   // load the .proto and the golden file from disk
1138   std::string protofile;
1139   std::string goldenfile;
1140   std::string goldenunionfile;
1141   TEST_EQ(
1142       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1143                             false, &protofile),
1144       true);
1145   TEST_EQ(
1146       flatbuffers::LoadFile((test_data_path + "prototest/test.golden").c_str(),
1147                             false, &goldenfile),
1148       true);
1149   TEST_EQ(flatbuffers::LoadFile(
1150               (test_data_path + "prototest/test_union.golden").c_str(), false,
1151               &goldenunionfile),
1152           true);
1153
1154   flatbuffers::IDLOptions opts;
1155   opts.include_dependence_headers = false;
1156   opts.proto_mode = true;
1157
1158   // Parse proto.
1159   flatbuffers::Parser parser(opts);
1160   auto protopath = test_data_path + "prototest/";
1161   const char *include_directories[] = { protopath.c_str(), nullptr };
1162   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1163
1164   // Generate fbs.
1165   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1166
1167   // Ensure generated file is parsable.
1168   flatbuffers::Parser parser2;
1169   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1170   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1171
1172   // Parse proto with --oneof-union option.
1173   opts.proto_oneof_union = true;
1174   flatbuffers::Parser parser3(opts);
1175   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1176
1177   // Generate fbs.
1178   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1179
1180   // Ensure generated file is parsable.
1181   flatbuffers::Parser parser4;
1182   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1183   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1184 }
1185
1186 // Parse a .proto schema, output as .fbs
1187 void ParseProtoTestWithSuffix() {
1188   // load the .proto and the golden file from disk
1189   std::string protofile;
1190   std::string goldenfile;
1191   std::string goldenunionfile;
1192   TEST_EQ(
1193       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1194                             false, &protofile),
1195       true);
1196   TEST_EQ(flatbuffers::LoadFile(
1197               (test_data_path + "prototest/test_suffix.golden").c_str(), false,
1198               &goldenfile),
1199           true);
1200   TEST_EQ(flatbuffers::LoadFile(
1201               (test_data_path + "prototest/test_union_suffix.golden").c_str(),
1202               false, &goldenunionfile),
1203           true);
1204
1205   flatbuffers::IDLOptions opts;
1206   opts.include_dependence_headers = false;
1207   opts.proto_mode = true;
1208   opts.proto_namespace_suffix = "test_namespace_suffix";
1209
1210   // Parse proto.
1211   flatbuffers::Parser parser(opts);
1212   auto protopath = test_data_path + "prototest/";
1213   const char *include_directories[] = { protopath.c_str(), nullptr };
1214   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1215
1216   // Generate fbs.
1217   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1218
1219   // Ensure generated file is parsable.
1220   flatbuffers::Parser parser2;
1221   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1222   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1223
1224   // Parse proto with --oneof-union option.
1225   opts.proto_oneof_union = true;
1226   flatbuffers::Parser parser3(opts);
1227   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1228
1229   // Generate fbs.
1230   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1231
1232   // Ensure generated file is parsable.
1233   flatbuffers::Parser parser4;
1234   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1235   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1236 }
1237
1238 // Parse a .proto schema, output as .fbs
1239 void ParseProtoTestWithIncludes() {
1240   // load the .proto and the golden file from disk
1241   std::string protofile;
1242   std::string goldenfile;
1243   std::string goldenunionfile;
1244   std::string importprotofile;
1245   TEST_EQ(
1246       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1247                             false, &protofile),
1248       true);
1249   TEST_EQ(flatbuffers::LoadFile(
1250               (test_data_path + "prototest/imported.proto").c_str(), false,
1251               &importprotofile),
1252           true);
1253   TEST_EQ(flatbuffers::LoadFile(
1254               (test_data_path + "prototest/test_include.golden").c_str(), false,
1255               &goldenfile),
1256           true);
1257   TEST_EQ(flatbuffers::LoadFile(
1258               (test_data_path + "prototest/test_union_include.golden").c_str(),
1259               false, &goldenunionfile),
1260           true);
1261
1262   flatbuffers::IDLOptions opts;
1263   opts.include_dependence_headers = true;
1264   opts.proto_mode = true;
1265
1266   // Parse proto.
1267   flatbuffers::Parser parser(opts);
1268   auto protopath = test_data_path + "prototest/";
1269   const char *include_directories[] = { protopath.c_str(), nullptr };
1270   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1271
1272   // Generate fbs.
1273   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1274
1275   // Generate fbs from import.proto
1276   flatbuffers::Parser import_parser(opts);
1277   TEST_EQ(import_parser.Parse(importprotofile.c_str(), include_directories),
1278           true);
1279   auto import_fbs = flatbuffers::GenerateFBS(import_parser, "test");
1280
1281   // Ensure generated file is parsable.
1282   flatbuffers::Parser parser2;
1283   TEST_EQ(
1284       parser2.Parse(import_fbs.c_str(), include_directories, "imported.fbs"),
1285       true);
1286   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1287   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1288
1289   // Parse proto with --oneof-union option.
1290   opts.proto_oneof_union = true;
1291   flatbuffers::Parser parser3(opts);
1292   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1293
1294   // Generate fbs.
1295   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1296
1297   // Ensure generated file is parsable.
1298   flatbuffers::Parser parser4;
1299   TEST_EQ(parser4.Parse(import_fbs.c_str(), nullptr, "imported.fbs"), true);
1300   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1301   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1302 }
1303
1304 template<typename T>
1305 void CompareTableFieldValue(flatbuffers::Table *table,
1306                             flatbuffers::voffset_t voffset, T val) {
1307   T read = table->GetField(voffset, static_cast<T>(0));
1308   TEST_EQ(read, val);
1309 }
1310
1311 // Low level stress/fuzz test: serialize/deserialize a variety of
1312 // different kinds of data in different combinations
1313 void FuzzTest1() {
1314   // Values we're testing against: chosen to ensure no bits get chopped
1315   // off anywhere, and also be different from eachother.
1316   const uint8_t bool_val = true;
1317   const int8_t char_val = -127;  // 0x81
1318   const uint8_t uchar_val = 0xFF;
1319   const int16_t short_val = -32222;  // 0x8222;
1320   const uint16_t ushort_val = 0xFEEE;
1321   const int32_t int_val = 0x83333333;
1322   const uint32_t uint_val = 0xFDDDDDDD;
1323   const int64_t long_val = 0x8444444444444444LL;
1324   const uint64_t ulong_val = 0xFCCCCCCCCCCCCCCCULL;
1325   const float float_val = 3.14159f;
1326   const double double_val = 3.14159265359;
1327
1328   const int test_values_max = 11;
1329   const flatbuffers::voffset_t fields_per_object = 4;
1330   const int num_fuzz_objects = 10000;  // The higher, the more thorough :)
1331
1332   flatbuffers::FlatBufferBuilder builder;
1333
1334   lcg_reset();  // Keep it deterministic.
1335
1336   flatbuffers::uoffset_t objects[num_fuzz_objects];
1337
1338   // Generate num_fuzz_objects random objects each consisting of
1339   // fields_per_object fields, each of a random type.
1340   for (int i = 0; i < num_fuzz_objects; i++) {
1341     auto start = builder.StartTable();
1342     for (flatbuffers::voffset_t f = 0; f < fields_per_object; f++) {
1343       int choice = lcg_rand() % test_values_max;
1344       auto off = flatbuffers::FieldIndexToOffset(f);
1345       switch (choice) {
1346         case 0: builder.AddElement<uint8_t>(off, bool_val, 0); break;
1347         case 1: builder.AddElement<int8_t>(off, char_val, 0); break;
1348         case 2: builder.AddElement<uint8_t>(off, uchar_val, 0); break;
1349         case 3: builder.AddElement<int16_t>(off, short_val, 0); break;
1350         case 4: builder.AddElement<uint16_t>(off, ushort_val, 0); break;
1351         case 5: builder.AddElement<int32_t>(off, int_val, 0); break;
1352         case 6: builder.AddElement<uint32_t>(off, uint_val, 0); break;
1353         case 7: builder.AddElement<int64_t>(off, long_val, 0); break;
1354         case 8: builder.AddElement<uint64_t>(off, ulong_val, 0); break;
1355         case 9: builder.AddElement<float>(off, float_val, 0); break;
1356         case 10: builder.AddElement<double>(off, double_val, 0); break;
1357       }
1358     }
1359     objects[i] = builder.EndTable(start);
1360   }
1361   builder.PreAlign<flatbuffers::largest_scalar_t>(0);  // Align whole buffer.
1362
1363   lcg_reset();  // Reset.
1364
1365   uint8_t *eob = builder.GetCurrentBufferPointer() + builder.GetSize();
1366
1367   // Test that all objects we generated are readable and return the
1368   // expected values. We generate random objects in the same order
1369   // so this is deterministic.
1370   for (int i = 0; i < num_fuzz_objects; i++) {
1371     auto table = reinterpret_cast<flatbuffers::Table *>(eob - objects[i]);
1372     for (flatbuffers::voffset_t f = 0; f < fields_per_object; f++) {
1373       int choice = lcg_rand() % test_values_max;
1374       flatbuffers::voffset_t off = flatbuffers::FieldIndexToOffset(f);
1375       switch (choice) {
1376         case 0: CompareTableFieldValue(table, off, bool_val); break;
1377         case 1: CompareTableFieldValue(table, off, char_val); break;
1378         case 2: CompareTableFieldValue(table, off, uchar_val); break;
1379         case 3: CompareTableFieldValue(table, off, short_val); break;
1380         case 4: CompareTableFieldValue(table, off, ushort_val); break;
1381         case 5: CompareTableFieldValue(table, off, int_val); break;
1382         case 6: CompareTableFieldValue(table, off, uint_val); break;
1383         case 7: CompareTableFieldValue(table, off, long_val); break;
1384         case 8: CompareTableFieldValue(table, off, ulong_val); break;
1385         case 9: CompareTableFieldValue(table, off, float_val); break;
1386         case 10: CompareTableFieldValue(table, off, double_val); break;
1387       }
1388     }
1389   }
1390 }
1391
1392 // High level stress/fuzz test: generate a big schema and
1393 // matching json data in random combinations, then parse both,
1394 // generate json back from the binary, and compare with the original.
1395 void FuzzTest2() {
1396   lcg_reset();  // Keep it deterministic.
1397
1398   const int num_definitions = 30;
1399   const int num_struct_definitions = 5;  // Subset of num_definitions.
1400   const int fields_per_definition = 15;
1401   const int instances_per_definition = 5;
1402   const int deprecation_rate = 10;  // 1 in deprecation_rate fields will
1403                                     // be deprecated.
1404
1405   std::string schema = "namespace test;\n\n";
1406
1407   struct RndDef {
1408     std::string instances[instances_per_definition];
1409
1410     // Since we're generating schema and corresponding data in tandem,
1411     // this convenience function adds strings to both at once.
1412     static void Add(RndDef (&definitions_l)[num_definitions],
1413                     std::string &schema_l, const int instances_per_definition_l,
1414                     const char *schema_add, const char *instance_add,
1415                     int definition) {
1416       schema_l += schema_add;
1417       for (int i = 0; i < instances_per_definition_l; i++)
1418         definitions_l[definition].instances[i] += instance_add;
1419     }
1420   };
1421
1422   // clang-format off
1423   #define AddToSchemaAndInstances(schema_add, instance_add) \
1424     RndDef::Add(definitions, schema, instances_per_definition, \
1425                 schema_add, instance_add, definition)
1426
1427   #define Dummy() \
1428     RndDef::Add(definitions, schema, instances_per_definition, \
1429                 "byte", "1", definition)
1430   // clang-format on
1431
1432   RndDef definitions[num_definitions];
1433
1434   // We are going to generate num_definitions, the first
1435   // num_struct_definitions will be structs, the rest tables. For each
1436   // generate random fields, some of which may be struct/table types
1437   // referring to previously generated structs/tables.
1438   // Simultanenously, we generate instances_per_definition JSON data
1439   // definitions, which will have identical structure to the schema
1440   // being generated. We generate multiple instances such that when creating
1441   // hierarchy, we get some variety by picking one randomly.
1442   for (int definition = 0; definition < num_definitions; definition++) {
1443     std::string definition_name = "D" + flatbuffers::NumToString(definition);
1444
1445     bool is_struct = definition < num_struct_definitions;
1446
1447     AddToSchemaAndInstances(
1448         ((is_struct ? "struct " : "table ") + definition_name + " {\n").c_str(),
1449         "{\n");
1450
1451     for (int field = 0; field < fields_per_definition; field++) {
1452       const bool is_last_field = field == fields_per_definition - 1;
1453
1454       // Deprecate 1 in deprecation_rate fields. Only table fields can be
1455       // deprecated.
1456       // Don't deprecate the last field to avoid dangling commas in JSON.
1457       const bool deprecated =
1458           !is_struct && !is_last_field && (lcg_rand() % deprecation_rate == 0);
1459
1460       std::string field_name = "f" + flatbuffers::NumToString(field);
1461       AddToSchemaAndInstances(("  " + field_name + ":").c_str(),
1462                               deprecated ? "" : (field_name + ": ").c_str());
1463       // Pick random type:
1464       auto base_type = static_cast<flatbuffers::BaseType>(
1465           lcg_rand() % (flatbuffers::BASE_TYPE_UNION + 1));
1466       switch (base_type) {
1467         case flatbuffers::BASE_TYPE_STRING:
1468           if (is_struct) {
1469             Dummy();  // No strings in structs.
1470           } else {
1471             AddToSchemaAndInstances("string", deprecated ? "" : "\"hi\"");
1472           }
1473           break;
1474         case flatbuffers::BASE_TYPE_VECTOR:
1475           if (is_struct) {
1476             Dummy();  // No vectors in structs.
1477           } else {
1478             AddToSchemaAndInstances("[ubyte]",
1479                                     deprecated ? "" : "[\n0,\n1,\n255\n]");
1480           }
1481           break;
1482         case flatbuffers::BASE_TYPE_NONE:
1483         case flatbuffers::BASE_TYPE_UTYPE:
1484         case flatbuffers::BASE_TYPE_STRUCT:
1485         case flatbuffers::BASE_TYPE_UNION:
1486           if (definition) {
1487             // Pick a random previous definition and random data instance of
1488             // that definition.
1489             int defref = lcg_rand() % definition;
1490             int instance = lcg_rand() % instances_per_definition;
1491             AddToSchemaAndInstances(
1492                 ("D" + flatbuffers::NumToString(defref)).c_str(),
1493                 deprecated ? ""
1494                            : definitions[defref].instances[instance].c_str());
1495           } else {
1496             // If this is the first definition, we have no definition we can
1497             // refer to.
1498             Dummy();
1499           }
1500           break;
1501         case flatbuffers::BASE_TYPE_BOOL:
1502           AddToSchemaAndInstances(
1503               "bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
1504           break;
1505         case flatbuffers::BASE_TYPE_ARRAY:
1506           if (!is_struct) {
1507             AddToSchemaAndInstances(
1508                 "ubyte",
1509                 deprecated ? "" : "255");  // No fixed-length arrays in tables.
1510           } else {
1511             AddToSchemaAndInstances("[int:3]", deprecated ? "" : "[\n,\n,\n]");
1512           }
1513           break;
1514         default:
1515           // All the scalar types.
1516           schema += flatbuffers::kTypeNames[base_type];
1517
1518           if (!deprecated) {
1519             // We want each instance to use its own random value.
1520             for (int inst = 0; inst < instances_per_definition; inst++)
1521               definitions[definition].instances[inst] +=
1522                   flatbuffers::IsFloat(base_type)
1523                       ? flatbuffers::NumToString<double>(lcg_rand() % 128)
1524                             .c_str()
1525                       : flatbuffers::NumToString<int>(lcg_rand() % 128).c_str();
1526           }
1527       }
1528       AddToSchemaAndInstances(deprecated ? "(deprecated);\n" : ";\n",
1529                               deprecated ? "" : is_last_field ? "\n" : ",\n");
1530     }
1531     AddToSchemaAndInstances("}\n\n", "}");
1532   }
1533
1534   schema += "root_type D" + flatbuffers::NumToString(num_definitions - 1);
1535   schema += ";\n";
1536
1537   flatbuffers::Parser parser;
1538
1539   // Will not compare against the original if we don't write defaults
1540   parser.builder_.ForceDefaults(true);
1541
1542   // Parse the schema, parse the generated data, then generate text back
1543   // from the binary and compare against the original.
1544   TEST_EQ(parser.Parse(schema.c_str()), true);
1545
1546   const std::string &json =
1547       definitions[num_definitions - 1].instances[0] + "\n";
1548
1549   TEST_EQ(parser.Parse(json.c_str()), true);
1550
1551   std::string jsongen;
1552   parser.opts.indent_step = 0;
1553   auto result =
1554       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
1555   TEST_EQ(result, true);
1556
1557   if (jsongen != json) {
1558     // These strings are larger than a megabyte, so we show the bytes around
1559     // the first bytes that are different rather than the whole string.
1560     size_t len = std::min(json.length(), jsongen.length());
1561     for (size_t i = 0; i < len; i++) {
1562       if (json[i] != jsongen[i]) {
1563         i -= std::min(static_cast<size_t>(10), i);  // show some context;
1564         size_t end = std::min(len, i + 20);
1565         for (; i < end; i++)
1566           TEST_OUTPUT_LINE("at %d: found \"%c\", expected \"%c\"\n",
1567                            static_cast<int>(i), jsongen[i], json[i]);
1568         break;
1569       }
1570     }
1571     TEST_NOTNULL(nullptr);  //-V501 (this comment supresses CWE-570 warning)
1572   }
1573
1574   // clang-format off
1575   #ifdef FLATBUFFERS_TEST_VERBOSE
1576     TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n",
1577                      static_cast<int>(schema.length() / 1024),
1578                      static_cast<int>(json.length() / 1024));
1579   #endif
1580   // clang-format on
1581 }
1582
1583 // Test that parser errors are actually generated.
1584 void TestError_(const char *src, const char *error_substr, bool strict_json,
1585                 const char *file, int line, const char *func) {
1586   flatbuffers::IDLOptions opts;
1587   opts.strict_json = strict_json;
1588   flatbuffers::Parser parser(opts);
1589   if (parser.Parse(src)) {
1590     TestFail("true", "false",
1591              ("parser.Parse(\"" + std::string(src) + "\")").c_str(), file, line,
1592              func);
1593   } else if (!strstr(parser.error_.c_str(), error_substr)) {
1594     TestFail(error_substr, parser.error_.c_str(),
1595              ("parser.Parse(\"" + std::string(src) + "\")").c_str(), file, line,
1596              func);
1597   }
1598 }
1599
1600 void TestError_(const char *src, const char *error_substr, const char *file,
1601                 int line, const char *func) {
1602   TestError_(src, error_substr, false, file, line, func);
1603 }
1604
1605 #ifdef _WIN32
1606 #  define TestError(src, ...) \
1607     TestError_(src, __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__)
1608 #else
1609 #  define TestError(src, ...) \
1610     TestError_(src, __VA_ARGS__, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1611 #endif
1612
1613 // Test that parsing errors occur as we'd expect.
1614 // Also useful for coverage, making sure these paths are run.
1615 void ErrorTest() {
1616   // In order they appear in idl_parser.cpp
1617   TestError("table X { Y:byte; } root_type X; { Y: 999 }", "does not fit");
1618   TestError("\"\0", "illegal");
1619   TestError("\"\\q", "escape code");
1620   TestError("table ///", "documentation");
1621   TestError("@", "illegal");
1622   TestError("table 1", "expecting");
1623   TestError("table X { Y:[[int]]; }", "nested vector");
1624   TestError("table X { Y:1; }", "illegal type");
1625   TestError("table X { Y:int; Y:int; }", "field already");
1626   TestError("table Y {} table X { Y:int; }", "same as table");
1627   TestError("struct X { Y:string; }", "only scalar");
1628   TestError("table X { Y:string = \"\"; }", "default values");
1629   TestError("struct X { a:uint = 42; }", "default values");
1630   TestError("enum Y:byte { Z = 1 } table X { y:Y; }", "not part of enum");
1631   TestError("struct X { Y:int (deprecated); }", "deprecate");
1632   TestError("union Z { X } table X { Y:Z; } root_type X; { Y: {}, A:1 }",
1633             "missing type field");
1634   TestError("union Z { X } table X { Y:Z; } root_type X; { Y_type: 99, Y: {",
1635             "type id");
1636   TestError("table X { Y:int; } root_type X; { Z:", "unknown field");
1637   TestError("table X { Y:int; } root_type X; { Y:", "string constant", true);
1638   TestError("table X { Y:int; } root_type X; { \"Y\":1, }", "string constant",
1639             true);
1640   TestError(
1641       "struct X { Y:int; Z:int; } table W { V:X; } root_type W; "
1642       "{ V:{ Y:1 } }",
1643       "wrong number");
1644   TestError("enum E:byte { A } table X { Y:E; } root_type X; { Y:U }",
1645             "unknown enum value");
1646   TestError("table X { Y:byte; } root_type X; { Y:; }", "starting");
1647   TestError("enum X:byte { Y } enum X {", "enum already");
1648   TestError("enum X:float {}", "underlying");
1649   TestError("enum X:byte { Y, Y }", "value already");
1650   TestError("enum X:byte { Y=2, Z=2 }", "unique");
1651   TestError("table X { Y:int; } table X {", "datatype already");
1652   TestError("struct X (force_align: 7) { Y:int; }", "force_align");
1653   TestError("struct X {}", "size 0");
1654   TestError("{}", "no root");
1655   TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file");
1656   TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",
1657             "end of file");
1658   TestError("root_type X;", "unknown root");
1659   TestError("struct X { Y:int; } root_type X;", "a table");
1660   TestError("union X { Y }", "referenced");
1661   TestError("union Z { X } struct X { Y:int; }", "only tables");
1662   TestError("table X { Y:[int]; YLength:int; }", "clash");
1663   TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once");
1664   // float to integer conversion is forbidden
1665   TestError("table X { Y:int; } root_type X; { Y:1.0 }", "float");
1666   TestError("table X { Y:bool; } root_type X; { Y:1.0 }", "float");
1667   TestError("enum X:bool { Y = true }", "must be integral");
1668   // Array of non-scalar
1669   TestError("table X { x:int; } struct Y { y:[X:2]; }",
1670             "may contain only scalar or struct fields");
1671   // Non-snake case field names
1672   TestError("table X { Y: int; } root_type Y: {Y:1.0}", "snake_case");
1673 }
1674
1675 template<typename T>
1676 T TestValue(const char *json, const char *type_name,
1677             const char *decls = nullptr) {
1678   flatbuffers::Parser parser;
1679   parser.builder_.ForceDefaults(true);  // return defaults
1680   auto check_default = json ? false : true;
1681   if (check_default) { parser.opts.output_default_scalars_in_json = true; }
1682   // Simple schema.
1683   std::string schema = std::string(decls ? decls : "") + "\n" +
1684                        "table X { y:" + std::string(type_name) +
1685                        "; } root_type X;";
1686   auto schema_done = parser.Parse(schema.c_str());
1687   TEST_EQ_STR(parser.error_.c_str(), "");
1688   TEST_EQ(schema_done, true);
1689
1690   auto done = parser.Parse(check_default ? "{}" : json);
1691   TEST_EQ_STR(parser.error_.c_str(), "");
1692   TEST_EQ(done, true);
1693
1694   // Check with print.
1695   std::string print_back;
1696   parser.opts.indent_step = -1;
1697   TEST_EQ(GenerateText(parser, parser.builder_.GetBufferPointer(), &print_back),
1698           true);
1699   // restore value from its default
1700   if (check_default) { TEST_EQ(parser.Parse(print_back.c_str()), true); }
1701
1702   auto root = flatbuffers::GetRoot<flatbuffers::Table>(
1703       parser.builder_.GetBufferPointer());
1704   return root->GetField<T>(flatbuffers::FieldIndexToOffset(0), 0);
1705 }
1706
1707 bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; }
1708
1709 // Additional parser testing not covered elsewhere.
1710 void ValueTest() {
1711   // Test scientific notation numbers.
1712   TEST_EQ(
1713       FloatCompare(TestValue<float>("{ y:0.0314159e+2 }", "float"), 3.14159f),
1714       true);
1715   // number in string
1716   TEST_EQ(FloatCompare(TestValue<float>("{ y:\"0.0314159e+2\" }", "float"),
1717                        3.14159f),
1718           true);
1719
1720   // Test conversion functions.
1721   TEST_EQ(FloatCompare(TestValue<float>("{ y:cos(rad(180)) }", "float"), -1),
1722           true);
1723
1724   // int embedded to string
1725   TEST_EQ(TestValue<int>("{ y:\"-876\" }", "int=-123"), -876);
1726   TEST_EQ(TestValue<int>("{ y:\"876\" }", "int=-123"), 876);
1727
1728   // Test negative hex constant.
1729   TEST_EQ(TestValue<int>("{ y:-0x8ea0 }", "int=-0x8ea0"), -36512);
1730   TEST_EQ(TestValue<int>(nullptr, "int=-0x8ea0"), -36512);
1731
1732   // positive hex constant
1733   TEST_EQ(TestValue<int>("{ y:0x1abcdef }", "int=0x1"), 0x1abcdef);
1734   // with optional '+' sign
1735   TEST_EQ(TestValue<int>("{ y:+0x1abcdef }", "int=+0x1"), 0x1abcdef);
1736   // hex in string
1737   TEST_EQ(TestValue<int>("{ y:\"0x1abcdef\" }", "int=+0x1"), 0x1abcdef);
1738
1739   // Make sure we do unsigned 64bit correctly.
1740   TEST_EQ(TestValue<uint64_t>("{ y:12335089644688340133 }", "ulong"),
1741           12335089644688340133ULL);
1742
1743   // bool in string
1744   TEST_EQ(TestValue<bool>("{ y:\"false\" }", "bool=true"), false);
1745   TEST_EQ(TestValue<bool>("{ y:\"true\" }", "bool=\"true\""), true);
1746   TEST_EQ(TestValue<bool>("{ y:'false' }", "bool=true"), false);
1747   TEST_EQ(TestValue<bool>("{ y:'true' }", "bool=\"true\""), true);
1748
1749   // check comments before and after json object
1750   TEST_EQ(TestValue<int>("/*before*/ { y:1 } /*after*/", "int"), 1);
1751   TEST_EQ(TestValue<int>("//before \n { y:1 } //after", "int"), 1);
1752 }
1753
1754 void NestedListTest() {
1755   flatbuffers::Parser parser1;
1756   TEST_EQ(parser1.Parse("struct Test { a:short; b:byte; } table T { F:[Test]; }"
1757                         "root_type T;"
1758                         "{ F:[ [10,20], [30,40]] }"),
1759           true);
1760 }
1761
1762 void EnumStringsTest() {
1763   flatbuffers::Parser parser1;
1764   TEST_EQ(parser1.Parse("enum E:byte { A, B, C } table T { F:[E]; }"
1765                         "root_type T;"
1766                         "{ F:[ A, B, \"C\", \"A B C\" ] }"),
1767           true);
1768   flatbuffers::Parser parser2;
1769   TEST_EQ(parser2.Parse("enum E:byte { A, B, C } table T { F:[int]; }"
1770                         "root_type T;"
1771                         "{ F:[ \"E.C\", \"E.A E.B E.C\" ] }"),
1772           true);
1773   // unsigned bit_flags
1774   flatbuffers::Parser parser3;
1775   TEST_EQ(
1776       parser3.Parse("enum E:uint16 (bit_flags) { F0, F07=7, F08, F14=14, F15 }"
1777                     " table T { F: E = \"F15 F08\"; }"
1778                     "root_type T;"),
1779       true);
1780 }
1781
1782 void EnumNamesTest() {
1783   TEST_EQ_STR("Red", EnumNameColor(Color_Red));
1784   TEST_EQ_STR("Green", EnumNameColor(Color_Green));
1785   TEST_EQ_STR("Blue", EnumNameColor(Color_Blue));
1786   // Check that Color to string don't crash while decode a mixture of Colors.
1787   // 1) Example::Color enum is enum with unfixed underlying type.
1788   // 2) Valid enum range: [0; 2^(ceil(log2(Color_ANY))) - 1].
1789   // Consequence: A value is out of this range will lead to UB (since C++17).
1790   // For details see C++17 standard or explanation on the SO:
1791   // stackoverflow.com/questions/18195312/what-happens-if-you-static-cast-invalid-value-to-enum-class
1792   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(0)));
1793   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY - 1)));
1794   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY + 1)));
1795 }
1796
1797 void EnumOutOfRangeTest() {
1798   TestError("enum X:byte { Y = 128 }", "enum value does not fit");
1799   TestError("enum X:byte { Y = -129 }", "enum value does not fit");
1800   TestError("enum X:byte { Y = 126, Z0, Z1 }", "enum value does not fit");
1801   TestError("enum X:ubyte { Y = -1 }", "enum value does not fit");
1802   TestError("enum X:ubyte { Y = 256 }", "enum value does not fit");
1803   TestError("enum X:ubyte { Y = 255, Z }", "enum value does not fit");
1804   TestError("table Y{} union X { Y = -1 }", "enum value does not fit");
1805   TestError("table Y{} union X { Y = 256 }", "enum value does not fit");
1806   TestError("table Y{} union X { Y = 255, Z:Y }", "enum value does not fit");
1807   TestError("enum X:int { Y = -2147483649 }", "enum value does not fit");
1808   TestError("enum X:int { Y = 2147483648 }", "enum value does not fit");
1809   TestError("enum X:uint { Y = -1 }", "enum value does not fit");
1810   TestError("enum X:uint { Y = 4294967297 }", "enum value does not fit");
1811   TestError("enum X:long { Y = 9223372036854775808 }", "does not fit");
1812   TestError("enum X:long { Y = 9223372036854775807, Z }",
1813             "enum value does not fit");
1814   TestError("enum X:ulong { Y = -1 }", "does not fit");
1815   TestError("enum X:ubyte (bit_flags) { Y=8 }", "bit flag out");
1816   TestError("enum X:byte (bit_flags) { Y=7 }", "must be unsigned");  // -128
1817   // bit_flgs out of range
1818   TestError("enum X:ubyte (bit_flags) { Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8 }",
1819             "out of range");
1820 }
1821
1822 void EnumValueTest() {
1823   // json: "{ Y:0 }", schema: table X { y: "E"}
1824   // 0 in enum (V=0) E then Y=0 is valid.
1825   TEST_EQ(TestValue<int>("{ y:0 }", "E", "enum E:int { V }"), 0);
1826   TEST_EQ(TestValue<int>("{ y:V }", "E", "enum E:int { V }"), 0);
1827   // A default value of Y is 0.
1828   TEST_EQ(TestValue<int>("{ }", "E", "enum E:int { V }"), 0);
1829   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { V=5 }"), 5);
1830   // Generate json with defaults and check.
1831   TEST_EQ(TestValue<int>(nullptr, "E=V", "enum E:int { V=5 }"), 5);
1832   // 5 in enum
1833   TEST_EQ(TestValue<int>("{ y:5 }", "E", "enum E:int { Z, V=5 }"), 5);
1834   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { Z, V=5 }"), 5);
1835   // Generate json with defaults and check.
1836   TEST_EQ(TestValue<int>(nullptr, "E", "enum E:int { Z, V=5 }"), 0);
1837   TEST_EQ(TestValue<int>(nullptr, "E=V", "enum E:int { Z, V=5 }"), 5);
1838   // u84 test
1839   TEST_EQ(TestValue<uint64_t>(nullptr, "E=V",
1840                               "enum E:ulong { V = 13835058055282163712 }"),
1841           13835058055282163712ULL);
1842   TEST_EQ(TestValue<uint64_t>(nullptr, "E=V",
1843                               "enum E:ulong { V = 18446744073709551615 }"),
1844           18446744073709551615ULL);
1845   // Assign non-enum value to enum field. Is it right?
1846   TEST_EQ(TestValue<int>("{ y:7 }", "E", "enum E:int { V = 0 }"), 7);
1847   // Check that non-ascending values are valid.
1848   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { Z=10, V=5 }"), 5);
1849 }
1850
1851 void IntegerOutOfRangeTest() {
1852   TestError("table T { F:byte; } root_type T; { F:128 }",
1853             "constant does not fit");
1854   TestError("table T { F:byte; } root_type T; { F:-129 }",
1855             "constant does not fit");
1856   TestError("table T { F:ubyte; } root_type T; { F:256 }",
1857             "constant does not fit");
1858   TestError("table T { F:ubyte; } root_type T; { F:-1 }",
1859             "constant does not fit");
1860   TestError("table T { F:short; } root_type T; { F:32768 }",
1861             "constant does not fit");
1862   TestError("table T { F:short; } root_type T; { F:-32769 }",
1863             "constant does not fit");
1864   TestError("table T { F:ushort; } root_type T; { F:65536 }",
1865             "constant does not fit");
1866   TestError("table T { F:ushort; } root_type T; { F:-1 }",
1867             "constant does not fit");
1868   TestError("table T { F:int; } root_type T; { F:2147483648 }",
1869             "constant does not fit");
1870   TestError("table T { F:int; } root_type T; { F:-2147483649 }",
1871             "constant does not fit");
1872   TestError("table T { F:uint; } root_type T; { F:4294967296 }",
1873             "constant does not fit");
1874   TestError("table T { F:uint; } root_type T; { F:-1 }",
1875             "constant does not fit");
1876   // Check fixed width aliases
1877   TestError("table X { Y:uint8; } root_type X; { Y: -1 }", "does not fit");
1878   TestError("table X { Y:uint8; } root_type X; { Y: 256 }", "does not fit");
1879   TestError("table X { Y:uint16; } root_type X; { Y: -1 }", "does not fit");
1880   TestError("table X { Y:uint16; } root_type X; { Y: 65536 }", "does not fit");
1881   TestError("table X { Y:uint32; } root_type X; { Y: -1 }", "");
1882   TestError("table X { Y:uint32; } root_type X; { Y: 4294967296 }",
1883             "does not fit");
1884   TestError("table X { Y:uint64; } root_type X; { Y: -1 }", "");
1885   TestError("table X { Y:uint64; } root_type X; { Y: -9223372036854775809 }",
1886             "does not fit");
1887   TestError("table X { Y:uint64; } root_type X; { Y: 18446744073709551616 }",
1888             "does not fit");
1889
1890   TestError("table X { Y:int8; } root_type X; { Y: -129 }", "does not fit");
1891   TestError("table X { Y:int8; } root_type X; { Y: 128 }", "does not fit");
1892   TestError("table X { Y:int16; } root_type X; { Y: -32769 }", "does not fit");
1893   TestError("table X { Y:int16; } root_type X; { Y: 32768 }", "does not fit");
1894   TestError("table X { Y:int32; } root_type X; { Y: -2147483649 }", "");
1895   TestError("table X { Y:int32; } root_type X; { Y: 2147483648 }",
1896             "does not fit");
1897   TestError("table X { Y:int64; } root_type X; { Y: -9223372036854775809 }",
1898             "does not fit");
1899   TestError("table X { Y:int64; } root_type X; { Y: 9223372036854775808 }",
1900             "does not fit");
1901   // check out-of-int64 as int8
1902   TestError("table X { Y:int8; } root_type X; { Y: -9223372036854775809 }",
1903             "does not fit");
1904   TestError("table X { Y:int8; } root_type X; { Y: 9223372036854775808 }",
1905             "does not fit");
1906
1907   // Check default values
1908   TestError("table X { Y:int64=-9223372036854775809; } root_type X; {}",
1909             "does not fit");
1910   TestError("table X { Y:int64= 9223372036854775808; } root_type X; {}",
1911             "does not fit");
1912   TestError("table X { Y:uint64; } root_type X; { Y: -1 }", "");
1913   TestError("table X { Y:uint64=-9223372036854775809; } root_type X; {}",
1914             "does not fit");
1915   TestError("table X { Y:uint64= 18446744073709551616; } root_type X; {}",
1916             "does not fit");
1917 }
1918
1919 void IntegerBoundaryTest() {
1920   // Check numerical compatibility with non-C++ languages.
1921   // By the C++ standard, std::numerical_limits<int64_t>::min() ==
1922   // -9223372036854775807 (-2^63+1) or less* The Flatbuffers grammar and most of
1923   // the languages (C#, Java, Rust) expect that minimum values are: -128,
1924   // -32768,.., -9223372036854775808. Since C++20,
1925   // static_cast<int64>(0x8000000000000000ULL) is well-defined two's complement
1926   // cast. Therefore -9223372036854775808 should be valid negative value.
1927   TEST_EQ(flatbuffers::numeric_limits<int8_t>::min(), -128);
1928   TEST_EQ(flatbuffers::numeric_limits<int8_t>::max(), 127);
1929   TEST_EQ(flatbuffers::numeric_limits<int16_t>::min(), -32768);
1930   TEST_EQ(flatbuffers::numeric_limits<int16_t>::max(), 32767);
1931   TEST_EQ(flatbuffers::numeric_limits<int32_t>::min() + 1, -2147483647);
1932   TEST_EQ(flatbuffers::numeric_limits<int32_t>::max(), 2147483647ULL);
1933   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min() + 1LL,
1934           -9223372036854775807LL);
1935   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(), 9223372036854775807ULL);
1936   TEST_EQ(flatbuffers::numeric_limits<uint8_t>::max(), 255);
1937   TEST_EQ(flatbuffers::numeric_limits<uint16_t>::max(), 65535);
1938   TEST_EQ(flatbuffers::numeric_limits<uint32_t>::max(), 4294967295ULL);
1939   TEST_EQ(flatbuffers::numeric_limits<uint64_t>::max(),
1940           18446744073709551615ULL);
1941
1942   TEST_EQ(TestValue<int8_t>("{ y:127 }", "byte"), 127);
1943   TEST_EQ(TestValue<int8_t>("{ y:-128 }", "byte"), -128);
1944   TEST_EQ(TestValue<uint8_t>("{ y:255 }", "ubyte"), 255);
1945   TEST_EQ(TestValue<uint8_t>("{ y:0 }", "ubyte"), 0);
1946   TEST_EQ(TestValue<int16_t>("{ y:32767 }", "short"), 32767);
1947   TEST_EQ(TestValue<int16_t>("{ y:-32768 }", "short"), -32768);
1948   TEST_EQ(TestValue<uint16_t>("{ y:65535 }", "ushort"), 65535);
1949   TEST_EQ(TestValue<uint16_t>("{ y:0 }", "ushort"), 0);
1950   TEST_EQ(TestValue<int32_t>("{ y:2147483647 }", "int"), 2147483647);
1951   TEST_EQ(TestValue<int32_t>("{ y:-2147483648 }", "int") + 1, -2147483647);
1952   TEST_EQ(TestValue<uint32_t>("{ y:4294967295 }", "uint"), 4294967295);
1953   TEST_EQ(TestValue<uint32_t>("{ y:0 }", "uint"), 0);
1954   TEST_EQ(TestValue<int64_t>("{ y:9223372036854775807 }", "long"),
1955           9223372036854775807LL);
1956   TEST_EQ(TestValue<int64_t>("{ y:-9223372036854775808 }", "long") + 1LL,
1957           -9223372036854775807LL);
1958   TEST_EQ(TestValue<uint64_t>("{ y:18446744073709551615 }", "ulong"),
1959           18446744073709551615ULL);
1960   TEST_EQ(TestValue<uint64_t>("{ y:0 }", "ulong"), 0);
1961   TEST_EQ(TestValue<uint64_t>("{ y: 18446744073709551615 }", "uint64"),
1962           18446744073709551615ULL);
1963   // check that the default works
1964   TEST_EQ(TestValue<uint64_t>(nullptr, "uint64 = 18446744073709551615"),
1965           18446744073709551615ULL);
1966 }
1967
1968 void ValidFloatTest() {
1969   // check rounding to infinity
1970   TEST_EQ(TestValue<float>("{ y:+3.4029e+38 }", "float"), +infinityf);
1971   TEST_EQ(TestValue<float>("{ y:-3.4029e+38 }", "float"), -infinityf);
1972   TEST_EQ(TestValue<double>("{ y:+1.7977e+308 }", "double"), +infinityd);
1973   TEST_EQ(TestValue<double>("{ y:-1.7977e+308 }", "double"), -infinityd);
1974
1975   TEST_EQ(
1976       FloatCompare(TestValue<float>("{ y:0.0314159e+2 }", "float"), 3.14159f),
1977       true);
1978   // float in string
1979   TEST_EQ(FloatCompare(TestValue<float>("{ y:\" 0.0314159e+2  \" }", "float"),
1980                        3.14159f),
1981           true);
1982
1983   TEST_EQ(TestValue<float>("{ y:1 }", "float"), 1.0f);
1984   TEST_EQ(TestValue<float>("{ y:1.0 }", "float"), 1.0f);
1985   TEST_EQ(TestValue<float>("{ y:1. }", "float"), 1.0f);
1986   TEST_EQ(TestValue<float>("{ y:+1. }", "float"), 1.0f);
1987   TEST_EQ(TestValue<float>("{ y:-1. }", "float"), -1.0f);
1988   TEST_EQ(TestValue<float>("{ y:1.e0 }", "float"), 1.0f);
1989   TEST_EQ(TestValue<float>("{ y:1.e+0 }", "float"), 1.0f);
1990   TEST_EQ(TestValue<float>("{ y:1.e-0 }", "float"), 1.0f);
1991   TEST_EQ(TestValue<float>("{ y:0.125 }", "float"), 0.125f);
1992   TEST_EQ(TestValue<float>("{ y:.125 }", "float"), 0.125f);
1993   TEST_EQ(TestValue<float>("{ y:-.125 }", "float"), -0.125f);
1994   TEST_EQ(TestValue<float>("{ y:+.125 }", "float"), +0.125f);
1995   TEST_EQ(TestValue<float>("{ y:5 }", "float"), 5.0f);
1996   TEST_EQ(TestValue<float>("{ y:\"5\" }", "float"), 5.0f);
1997
1998 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
1999   // Old MSVC versions may have problem with this check.
2000   // https://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/
2001   TEST_EQ(TestValue<double>("{ y:6.9294956446009195e15 }", "double"),
2002           6929495644600920.0);
2003   // check nan's
2004   TEST_EQ(std::isnan(TestValue<double>("{ y:nan }", "double")), true);
2005   TEST_EQ(std::isnan(TestValue<float>("{ y:nan }", "float")), true);
2006   TEST_EQ(std::isnan(TestValue<float>("{ y:\"nan\" }", "float")), true);
2007   TEST_EQ(std::isnan(TestValue<float>("{ y:+nan }", "float")), true);
2008   TEST_EQ(std::isnan(TestValue<float>("{ y:-nan }", "float")), true);
2009   TEST_EQ(std::isnan(TestValue<float>(nullptr, "float=nan")), true);
2010   TEST_EQ(std::isnan(TestValue<float>(nullptr, "float=-nan")), true);
2011   // check inf
2012   TEST_EQ(TestValue<float>("{ y:inf }", "float"), infinityf);
2013   TEST_EQ(TestValue<float>("{ y:\"inf\" }", "float"), infinityf);
2014   TEST_EQ(TestValue<float>("{ y:+inf }", "float"), infinityf);
2015   TEST_EQ(TestValue<float>("{ y:-inf }", "float"), -infinityf);
2016   TEST_EQ(TestValue<float>(nullptr, "float=inf"), infinityf);
2017   TEST_EQ(TestValue<float>(nullptr, "float=-inf"), -infinityf);
2018   TestValue<double>(
2019       "{ y: [0.2, .2, 1.0, -1.0, -2., 2., 1e0, -1e0, 1.0e0, -1.0e0, -3.e2, "
2020       "3.0e2] }",
2021       "[double]");
2022   TestValue<float>(
2023       "{ y: [0.2, .2, 1.0, -1.0, -2., 2., 1e0, -1e0, 1.0e0, -1.0e0, -3.e2, "
2024       "3.0e2] }",
2025       "[float]");
2026
2027   // Test binary format of float point.
2028   // https://en.cppreference.com/w/cpp/language/floating_literal
2029   // 0x11.12p-1 = (1*16^1 + 2*16^0 + 3*16^-1 + 4*16^-2) * 2^-1 =
2030   TEST_EQ(TestValue<double>("{ y:0x12.34p-1 }", "double"), 9.1015625);
2031   // hex fraction 1.2 (decimal 1.125) scaled by 2^3, that is 9.0
2032   TEST_EQ(TestValue<float>("{ y:-0x0.2p0 }", "float"), -0.125f);
2033   TEST_EQ(TestValue<float>("{ y:-0x.2p1 }", "float"), -0.25f);
2034   TEST_EQ(TestValue<float>("{ y:0x1.2p3 }", "float"), 9.0f);
2035   TEST_EQ(TestValue<float>("{ y:0x10.1p0 }", "float"), 16.0625f);
2036   TEST_EQ(TestValue<double>("{ y:0x1.2p3 }", "double"), 9.0);
2037   TEST_EQ(TestValue<double>("{ y:0x10.1p0 }", "double"), 16.0625);
2038   TEST_EQ(TestValue<double>("{ y:0xC.68p+2 }", "double"), 49.625);
2039   TestValue<double>("{ y: [0x20.4ep1, +0x20.4ep1, -0x20.4ep1] }", "[double]");
2040   TestValue<float>("{ y: [0x20.4ep1, +0x20.4ep1, -0x20.4ep1] }", "[float]");
2041
2042 #else   // FLATBUFFERS_HAS_NEW_STRTOD
2043   TEST_OUTPUT_LINE("FLATBUFFERS_HAS_NEW_STRTOD tests skipped");
2044 #endif  // !FLATBUFFERS_HAS_NEW_STRTOD
2045 }
2046
2047 void InvalidFloatTest() {
2048   auto invalid_msg = "invalid number";
2049   auto comma_msg = "expecting: ,";
2050   TestError("table T { F:float; } root_type T; { F:1,0 }", "");
2051   TestError("table T { F:float; } root_type T; { F:. }", "");
2052   TestError("table T { F:float; } root_type T; { F:- }", invalid_msg);
2053   TestError("table T { F:float; } root_type T; { F:+ }", invalid_msg);
2054   TestError("table T { F:float; } root_type T; { F:-. }", invalid_msg);
2055   TestError("table T { F:float; } root_type T; { F:+. }", invalid_msg);
2056   TestError("table T { F:float; } root_type T; { F:.e }", "");
2057   TestError("table T { F:float; } root_type T; { F:-e }", invalid_msg);
2058   TestError("table T { F:float; } root_type T; { F:+e }", invalid_msg);
2059   TestError("table T { F:float; } root_type T; { F:-.e }", invalid_msg);
2060   TestError("table T { F:float; } root_type T; { F:+.e }", invalid_msg);
2061   TestError("table T { F:float; } root_type T; { F:-e1 }", invalid_msg);
2062   TestError("table T { F:float; } root_type T; { F:+e1 }", invalid_msg);
2063   TestError("table T { F:float; } root_type T; { F:1.0e+ }", invalid_msg);
2064   TestError("table T { F:float; } root_type T; { F:1.0e- }", invalid_msg);
2065   // exponent pP is mandatory for hex-float
2066   TestError("table T { F:float; } root_type T; { F:0x0 }", invalid_msg);
2067   TestError("table T { F:float; } root_type T; { F:-0x. }", invalid_msg);
2068   TestError("table T { F:float; } root_type T; { F:0x. }", invalid_msg);
2069   TestError("table T { F:float; } root_type T; { F:0Xe }", invalid_msg);
2070   TestError("table T { F:float; } root_type T; { F:\"0Xe\" }", invalid_msg);
2071   TestError("table T { F:float; } root_type T; { F:\"nan(1)\" }", invalid_msg);
2072   // eE not exponent in hex-float!
2073   TestError("table T { F:float; } root_type T; { F:0x0.0e+ }", invalid_msg);
2074   TestError("table T { F:float; } root_type T; { F:0x0.0e- }", invalid_msg);
2075   TestError("table T { F:float; } root_type T; { F:0x0.0p }", invalid_msg);
2076   TestError("table T { F:float; } root_type T; { F:0x0.0p+ }", invalid_msg);
2077   TestError("table T { F:float; } root_type T; { F:0x0.0p- }", invalid_msg);
2078   TestError("table T { F:float; } root_type T; { F:0x0.0pa1 }", invalid_msg);
2079   TestError("table T { F:float; } root_type T; { F:0x0.0e+ }", invalid_msg);
2080   TestError("table T { F:float; } root_type T; { F:0x0.0e- }", invalid_msg);
2081   TestError("table T { F:float; } root_type T; { F:0x0.0e+0 }", invalid_msg);
2082   TestError("table T { F:float; } root_type T; { F:0x0.0e-0 }", invalid_msg);
2083   TestError("table T { F:float; } root_type T; { F:0x0.0ep+ }", invalid_msg);
2084   TestError("table T { F:float; } root_type T; { F:0x0.0ep- }", invalid_msg);
2085   TestError("table T { F:float; } root_type T; { F:1.2.3 }", invalid_msg);
2086   TestError("table T { F:float; } root_type T; { F:1.2.e3 }", invalid_msg);
2087   TestError("table T { F:float; } root_type T; { F:1.2e.3 }", invalid_msg);
2088   TestError("table T { F:float; } root_type T; { F:1.2e0.3 }", invalid_msg);
2089   TestError("table T { F:float; } root_type T; { F:1.2e3. }", invalid_msg);
2090   TestError("table T { F:float; } root_type T; { F:1.2e3.0 }", invalid_msg);
2091   TestError("table T { F:float; } root_type T; { F:+-1.0 }", invalid_msg);
2092   TestError("table T { F:float; } root_type T; { F:1.0e+-1 }", invalid_msg);
2093   TestError("table T { F:float; } root_type T; { F:\"1.0e+-1\" }", invalid_msg);
2094   TestError("table T { F:float; } root_type T; { F:1.e0e }", comma_msg);
2095   TestError("table T { F:float; } root_type T; { F:0x1.p0e }", comma_msg);
2096   TestError("table T { F:float; } root_type T; { F:\" 0x10 \" }", invalid_msg);
2097   // floats in string
2098   TestError("table T { F:float; } root_type T; { F:\"1,2.\" }", invalid_msg);
2099   TestError("table T { F:float; } root_type T; { F:\"1.2e3.\" }", invalid_msg);
2100   TestError("table T { F:float; } root_type T; { F:\"0x1.p0e\" }", invalid_msg);
2101   TestError("table T { F:float; } root_type T; { F:\"0x1.0\" }", invalid_msg);
2102   TestError("table T { F:float; } root_type T; { F:\" 0x1.0\" }", invalid_msg);
2103   TestError("table T { F:float; } root_type T; { F:\"+ 0\" }", invalid_msg);
2104   // disable escapes for "number-in-string"
2105   TestError("table T { F:float; } root_type T; { F:\"\\f1.2e3.\" }", "invalid");
2106   TestError("table T { F:float; } root_type T; { F:\"\\t1.2e3.\" }", "invalid");
2107   TestError("table T { F:float; } root_type T; { F:\"\\n1.2e3.\" }", "invalid");
2108   TestError("table T { F:float; } root_type T; { F:\"\\r1.2e3.\" }", "invalid");
2109   TestError("table T { F:float; } root_type T; { F:\"4\\x005\" }", "invalid");
2110   TestError("table T { F:float; } root_type T; { F:\"\'12\'\" }", invalid_msg);
2111   // null is not a number constant!
2112   TestError("table T { F:float; } root_type T; { F:\"null\" }", invalid_msg);
2113   TestError("table T { F:float; } root_type T; { F:null }", invalid_msg);
2114 }
2115
2116 void GenerateTableTextTest() {
2117   std::string schemafile;
2118   std::string jsonfile;
2119   bool ok =
2120       flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
2121                             false, &schemafile) &&
2122       flatbuffers::LoadFile((test_data_path + "monsterdata_test.json").c_str(),
2123                             false, &jsonfile);
2124   TEST_EQ(ok, true);
2125   auto include_test_path =
2126       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
2127   const char *include_directories[] = { test_data_path.c_str(),
2128                                         include_test_path.c_str(), nullptr };
2129   flatbuffers::IDLOptions opt;
2130   opt.indent_step = -1;
2131   flatbuffers::Parser parser(opt);
2132   ok = parser.Parse(schemafile.c_str(), include_directories) &&
2133        parser.Parse(jsonfile.c_str(), include_directories);
2134   TEST_EQ(ok, true);
2135   // Test root table
2136   const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
2137   std::string jsongen;
2138   auto result = GenerateTextFromTable(parser, monster, "MyGame.Example.Monster",
2139                                       &jsongen);
2140   TEST_EQ(result, true);
2141   // Test sub table
2142   const Vec3 *pos = monster->pos();
2143   jsongen.clear();
2144   result = GenerateTextFromTable(parser, pos, "MyGame.Example.Vec3", &jsongen);
2145   TEST_EQ(result, true);
2146   TEST_EQ_STR(
2147       jsongen.c_str(),
2148       "{x: 1.0,y: 2.0,z: 3.0,test1: 3.0,test2: \"Green\",test3: {a: 5,b: 6}}");
2149   const Test &test3 = pos->test3();
2150   jsongen.clear();
2151   result =
2152       GenerateTextFromTable(parser, &test3, "MyGame.Example.Test", &jsongen);
2153   TEST_EQ(result, true);
2154   TEST_EQ_STR(jsongen.c_str(), "{a: 5,b: 6}");
2155   const Test *test4 = monster->test4()->Get(0);
2156   jsongen.clear();
2157   result =
2158       GenerateTextFromTable(parser, test4, "MyGame.Example.Test", &jsongen);
2159   TEST_EQ(result, true);
2160   TEST_EQ_STR(jsongen.c_str(), "{a: 10,b: 20}");
2161 }
2162
2163 template<typename T>
2164 void NumericUtilsTestInteger(const char *lower, const char *upper) {
2165   T x;
2166   TEST_EQ(flatbuffers::StringToNumber("1q", &x), false);
2167   TEST_EQ(x, 0);
2168   TEST_EQ(flatbuffers::StringToNumber(upper, &x), false);
2169   TEST_EQ(x, flatbuffers::numeric_limits<T>::max());
2170   TEST_EQ(flatbuffers::StringToNumber(lower, &x), false);
2171   auto expval = flatbuffers::is_unsigned<T>::value
2172                     ? flatbuffers::numeric_limits<T>::max()
2173                     : flatbuffers::numeric_limits<T>::lowest();
2174   TEST_EQ(x, expval);
2175 }
2176
2177 template<typename T>
2178 void NumericUtilsTestFloat(const char *lower, const char *upper) {
2179   T f;
2180   TEST_EQ(flatbuffers::StringToNumber("", &f), false);
2181   TEST_EQ(flatbuffers::StringToNumber("1q", &f), false);
2182   TEST_EQ(f, 0);
2183   TEST_EQ(flatbuffers::StringToNumber(upper, &f), true);
2184   TEST_EQ(f, +flatbuffers::numeric_limits<T>::infinity());
2185   TEST_EQ(flatbuffers::StringToNumber(lower, &f), true);
2186   TEST_EQ(f, -flatbuffers::numeric_limits<T>::infinity());
2187 }
2188
2189 void NumericUtilsTest() {
2190   NumericUtilsTestInteger<uint64_t>("-1", "18446744073709551616");
2191   NumericUtilsTestInteger<uint8_t>("-1", "256");
2192   NumericUtilsTestInteger<int64_t>("-9223372036854775809",
2193                                    "9223372036854775808");
2194   NumericUtilsTestInteger<int8_t>("-129", "128");
2195   NumericUtilsTestFloat<float>("-3.4029e+38", "+3.4029e+38");
2196   NumericUtilsTestFloat<float>("-1.7977e+308", "+1.7977e+308");
2197 }
2198
2199 void IsAsciiUtilsTest() {
2200   char c = -128;
2201   for (int cnt = 0; cnt < 256; cnt++) {
2202     auto alpha = (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
2203     auto dec = (('0' <= c) && (c <= '9'));
2204     auto hex = (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'));
2205     TEST_EQ(flatbuffers::is_alpha(c), alpha);
2206     TEST_EQ(flatbuffers::is_alnum(c), alpha || dec);
2207     TEST_EQ(flatbuffers::is_digit(c), dec);
2208     TEST_EQ(flatbuffers::is_xdigit(c), dec || hex);
2209     c += 1;
2210   }
2211 }
2212
2213 void UnicodeTest() {
2214   flatbuffers::Parser parser;
2215   // Without setting allow_non_utf8 = true, we treat \x sequences as byte
2216   // sequences which are then validated as UTF-8.
2217   TEST_EQ(parser.Parse("table T { F:string; }"
2218                        "root_type T;"
2219                        "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2220                        "\\u5225\\u30B5\\u30A4\\u30C8\\xE2\\x82\\xAC\\u0080\\uD8"
2221                        "3D\\uDE0E\" }"),
2222           true);
2223   std::string jsongen;
2224   parser.opts.indent_step = -1;
2225   auto result =
2226       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2227   TEST_EQ(result, true);
2228   TEST_EQ_STR(jsongen.c_str(),
2229               "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2230               "\\u5225\\u30B5\\u30A4\\u30C8\\u20AC\\u0080\\uD83D\\uDE0E\"}");
2231 }
2232
2233 void UnicodeTestAllowNonUTF8() {
2234   flatbuffers::Parser parser;
2235   parser.opts.allow_non_utf8 = true;
2236   TEST_EQ(
2237       parser.Parse(
2238           "table T { F:string; }"
2239           "root_type T;"
2240           "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2241           "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
2242       true);
2243   std::string jsongen;
2244   parser.opts.indent_step = -1;
2245   auto result =
2246       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2247   TEST_EQ(result, true);
2248   TEST_EQ_STR(
2249       jsongen.c_str(),
2250       "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2251       "\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}");
2252 }
2253
2254 void UnicodeTestGenerateTextFailsOnNonUTF8() {
2255   flatbuffers::Parser parser;
2256   // Allow non-UTF-8 initially to model what happens when we load a binary
2257   // flatbuffer from disk which contains non-UTF-8 strings.
2258   parser.opts.allow_non_utf8 = true;
2259   TEST_EQ(
2260       parser.Parse(
2261           "table T { F:string; }"
2262           "root_type T;"
2263           "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2264           "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
2265       true);
2266   std::string jsongen;
2267   parser.opts.indent_step = -1;
2268   // Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates
2269   // failure.
2270   parser.opts.allow_non_utf8 = false;
2271   auto result =
2272       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2273   TEST_EQ(result, false);
2274 }
2275
2276 void UnicodeSurrogatesTest() {
2277   flatbuffers::Parser parser;
2278
2279   TEST_EQ(parser.Parse("table T { F:string (id: 0); }"
2280                        "root_type T;"
2281                        "{ F:\"\\uD83D\\uDCA9\"}"),
2282           true);
2283   auto root = flatbuffers::GetRoot<flatbuffers::Table>(
2284       parser.builder_.GetBufferPointer());
2285   auto string = root->GetPointer<flatbuffers::String *>(
2286       flatbuffers::FieldIndexToOffset(0));
2287   TEST_EQ_STR(string->c_str(), "\xF0\x9F\x92\xA9");
2288 }
2289
2290 void UnicodeInvalidSurrogatesTest() {
2291   TestError(
2292       "table T { F:string; }"
2293       "root_type T;"
2294       "{ F:\"\\uD800\"}",
2295       "unpaired high surrogate");
2296   TestError(
2297       "table T { F:string; }"
2298       "root_type T;"
2299       "{ F:\"\\uD800abcd\"}",
2300       "unpaired high surrogate");
2301   TestError(
2302       "table T { F:string; }"
2303       "root_type T;"
2304       "{ F:\"\\uD800\\n\"}",
2305       "unpaired high surrogate");
2306   TestError(
2307       "table T { F:string; }"
2308       "root_type T;"
2309       "{ F:\"\\uD800\\uD800\"}",
2310       "multiple high surrogates");
2311   TestError(
2312       "table T { F:string; }"
2313       "root_type T;"
2314       "{ F:\"\\uDC00\"}",
2315       "unpaired low surrogate");
2316 }
2317
2318 void InvalidUTF8Test() {
2319   // "1 byte" pattern, under min length of 2 bytes
2320   TestError(
2321       "table T { F:string; }"
2322       "root_type T;"
2323       "{ F:\"\x80\"}",
2324       "illegal UTF-8 sequence");
2325   // 2 byte pattern, string too short
2326   TestError(
2327       "table T { F:string; }"
2328       "root_type T;"
2329       "{ F:\"\xDF\"}",
2330       "illegal UTF-8 sequence");
2331   // 3 byte pattern, string too short
2332   TestError(
2333       "table T { F:string; }"
2334       "root_type T;"
2335       "{ F:\"\xEF\xBF\"}",
2336       "illegal UTF-8 sequence");
2337   // 4 byte pattern, string too short
2338   TestError(
2339       "table T { F:string; }"
2340       "root_type T;"
2341       "{ F:\"\xF7\xBF\xBF\"}",
2342       "illegal UTF-8 sequence");
2343   // "5 byte" pattern, string too short
2344   TestError(
2345       "table T { F:string; }"
2346       "root_type T;"
2347       "{ F:\"\xFB\xBF\xBF\xBF\"}",
2348       "illegal UTF-8 sequence");
2349   // "6 byte" pattern, string too short
2350   TestError(
2351       "table T { F:string; }"
2352       "root_type T;"
2353       "{ F:\"\xFD\xBF\xBF\xBF\xBF\"}",
2354       "illegal UTF-8 sequence");
2355   // "7 byte" pattern, string too short
2356   TestError(
2357       "table T { F:string; }"
2358       "root_type T;"
2359       "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\"}",
2360       "illegal UTF-8 sequence");
2361   // "5 byte" pattern, over max length of 4 bytes
2362   TestError(
2363       "table T { F:string; }"
2364       "root_type T;"
2365       "{ F:\"\xFB\xBF\xBF\xBF\xBF\"}",
2366       "illegal UTF-8 sequence");
2367   // "6 byte" pattern, over max length of 4 bytes
2368   TestError(
2369       "table T { F:string; }"
2370       "root_type T;"
2371       "{ F:\"\xFD\xBF\xBF\xBF\xBF\xBF\"}",
2372       "illegal UTF-8 sequence");
2373   // "7 byte" pattern, over max length of 4 bytes
2374   TestError(
2375       "table T { F:string; }"
2376       "root_type T;"
2377       "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\xBF\"}",
2378       "illegal UTF-8 sequence");
2379
2380   // Three invalid encodings for U+000A (\n, aka NEWLINE)
2381   TestError(
2382       "table T { F:string; }"
2383       "root_type T;"
2384       "{ F:\"\xC0\x8A\"}",
2385       "illegal UTF-8 sequence");
2386   TestError(
2387       "table T { F:string; }"
2388       "root_type T;"
2389       "{ F:\"\xE0\x80\x8A\"}",
2390       "illegal UTF-8 sequence");
2391   TestError(
2392       "table T { F:string; }"
2393       "root_type T;"
2394       "{ F:\"\xF0\x80\x80\x8A\"}",
2395       "illegal UTF-8 sequence");
2396
2397   // Two invalid encodings for U+00A9 (COPYRIGHT SYMBOL)
2398   TestError(
2399       "table T { F:string; }"
2400       "root_type T;"
2401       "{ F:\"\xE0\x81\xA9\"}",
2402       "illegal UTF-8 sequence");
2403   TestError(
2404       "table T { F:string; }"
2405       "root_type T;"
2406       "{ F:\"\xF0\x80\x81\xA9\"}",
2407       "illegal UTF-8 sequence");
2408
2409   // Invalid encoding for U+20AC (EURO SYMBOL)
2410   TestError(
2411       "table T { F:string; }"
2412       "root_type T;"
2413       "{ F:\"\xF0\x82\x82\xAC\"}",
2414       "illegal UTF-8 sequence");
2415
2416   // UTF-16 surrogate values between U+D800 and U+DFFF cannot be encoded in
2417   // UTF-8
2418   TestError(
2419       "table T { F:string; }"
2420       "root_type T;"
2421       // U+10400 "encoded" as U+D801 U+DC00
2422       "{ F:\"\xED\xA0\x81\xED\xB0\x80\"}",
2423       "illegal UTF-8 sequence");
2424
2425   // Check independence of identifier from locale.
2426   std::string locale_ident;
2427   locale_ident += "table T { F";
2428   locale_ident += static_cast<char>(-32);  // unsigned 0xE0
2429   locale_ident += " :string; }";
2430   locale_ident += "root_type T;";
2431   locale_ident += "{}";
2432   TestError(locale_ident.c_str(), "");
2433 }
2434
2435 void UnknownFieldsTest() {
2436   flatbuffers::IDLOptions opts;
2437   opts.skip_unexpected_fields_in_json = true;
2438   flatbuffers::Parser parser(opts);
2439
2440   TEST_EQ(parser.Parse("table T { str:string; i:int;}"
2441                        "root_type T;"
2442                        "{ str:\"test\","
2443                        "unknown_string:\"test\","
2444                        "\"unknown_string\":\"test\","
2445                        "unknown_int:10,"
2446                        "unknown_float:1.0,"
2447                        "unknown_array: [ 1, 2, 3, 4],"
2448                        "unknown_object: { i: 10 },"
2449                        "\"unknown_object\": { \"i\": 10 },"
2450                        "i:10}"),
2451           true);
2452
2453   std::string jsongen;
2454   parser.opts.indent_step = -1;
2455   auto result =
2456       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2457   TEST_EQ(result, true);
2458   TEST_EQ_STR(jsongen.c_str(), "{str: \"test\",i: 10}");
2459 }
2460
2461 void ParseUnionTest() {
2462   // Unions must be parseable with the type field following the object.
2463   flatbuffers::Parser parser;
2464   TEST_EQ(parser.Parse("table T { A:int; }"
2465                        "union U { T }"
2466                        "table V { X:U; }"
2467                        "root_type V;"
2468                        "{ X:{ A:1 }, X_type: T }"),
2469           true);
2470   // Unions must be parsable with prefixed namespace.
2471   flatbuffers::Parser parser2;
2472   TEST_EQ(parser2.Parse("namespace N; table A {} namespace; union U { N.A }"
2473                         "table B { e:U; } root_type B;"
2474                         "{ e_type: N_A, e: {} }"),
2475           true);
2476 }
2477
2478 void InvalidNestedFlatbufferTest() {
2479   // First, load and parse FlatBuffer schema (.fbs)
2480   std::string schemafile;
2481   TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
2482                                 false, &schemafile),
2483           true);
2484   auto include_test_path =
2485       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
2486   const char *include_directories[] = { test_data_path.c_str(),
2487                                         include_test_path.c_str(), nullptr };
2488   flatbuffers::Parser parser1;
2489   TEST_EQ(parser1.Parse(schemafile.c_str(), include_directories), true);
2490
2491   // "color" inside nested flatbuffer contains invalid enum value
2492   TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: "
2493                         "\"Leela\", color: \"nonexistent\"}}"),
2494           false);
2495 }
2496
2497 void EvolutionTest() {
2498   // VS10 does not support typed enums, exclude from tests
2499 #if !defined(_MSC_VER) || _MSC_VER >= 1700
2500   const int NUM_VERSIONS = 2;
2501   std::string schemas[NUM_VERSIONS];
2502   std::string jsonfiles[NUM_VERSIONS];
2503   std::vector<uint8_t> binaries[NUM_VERSIONS];
2504
2505   flatbuffers::IDLOptions idl_opts;
2506   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2507   flatbuffers::Parser parser(idl_opts);
2508
2509   // Load all the schema versions and their associated data.
2510   for (int i = 0; i < NUM_VERSIONS; ++i) {
2511     std::string schema = test_data_path + "evolution_test/evolution_v" +
2512                          flatbuffers::NumToString(i + 1) + ".fbs";
2513     TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
2514     std::string json = test_data_path + "evolution_test/evolution_v" +
2515                        flatbuffers::NumToString(i + 1) + ".json";
2516     TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));
2517
2518     TEST_ASSERT(parser.Parse(schemas[i].c_str()));
2519     TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));
2520
2521     auto bufLen = parser.builder_.GetSize();
2522     auto buf = parser.builder_.GetBufferPointer();
2523     binaries[i].reserve(bufLen);
2524     std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
2525   }
2526
2527   // Assert that all the verifiers for the different schema versions properly
2528   // verify any version data.
2529   for (int i = 0; i < NUM_VERSIONS; ++i) {
2530     flatbuffers::Verifier verifier(&binaries[i].front(), binaries[i].size());
2531     TEST_ASSERT(Evolution::V1::VerifyRootBuffer(verifier));
2532     TEST_ASSERT(Evolution::V2::VerifyRootBuffer(verifier));
2533   }
2534
2535   // Test backwards compatibility by reading old data with an evolved schema.
2536   auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front());
2537   // field 'k' is new in version 2, so it should be null.
2538   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->k());
2539   // field 'l' is new in version 2 with a default of 56.
2540   TEST_EQ(root_v1_viewed_from_v2->l(), 56);
2541   // field 'c' of 'TableA' is new in version 2, so it should be null.
2542   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->e()->c());
2543   // 'TableC' was added to field 'c' union in version 2, so it should be null.
2544   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->c_as_TableC());
2545   // The field 'c' union should be of type 'TableB' regardless of schema version
2546   TEST_ASSERT(root_v1_viewed_from_v2->c_type() == Evolution::V2::Union::TableB);
2547   // The field 'f' was renamed to 'ff' in version 2, it should still be
2548   // readable.
2549   TEST_EQ(root_v1_viewed_from_v2->ff()->a(), 16);
2550
2551   // Test forwards compatibility by reading new data with an old schema.
2552   auto root_v2_viewed_from_v1 = Evolution::V1::GetRoot(&binaries[1].front());
2553   // The field 'c' union in version 2 is a new table (index = 3) and should
2554   // still be accessible, but not interpretable.
2555   TEST_EQ(static_cast<uint8_t>(root_v2_viewed_from_v1->c_type()), 3);
2556   TEST_NOTNULL(root_v2_viewed_from_v1->c());
2557   // The field 'd' enum in verison 2 has new members and should still be
2558   // accessible, but not interpretable.
2559   TEST_EQ(static_cast<int8_t>(root_v2_viewed_from_v1->d()), 3);
2560   // The field 'a' in version 2 is deprecated and should return the default
2561   // value (0) instead of the value stored in the in the buffer (42).
2562   TEST_EQ(root_v2_viewed_from_v1->a(), 0);
2563   // The field 'ff' was originally named 'f' in version 1, it should still be
2564   // readable.
2565   TEST_EQ(root_v2_viewed_from_v1->f()->a(), 35);
2566 #endif
2567 }
2568
2569 void UnionDeprecationTest() {
2570   const int NUM_VERSIONS = 2;
2571   std::string schemas[NUM_VERSIONS];
2572   std::string jsonfiles[NUM_VERSIONS];
2573   std::vector<uint8_t> binaries[NUM_VERSIONS];
2574
2575   flatbuffers::IDLOptions idl_opts;
2576   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2577   flatbuffers::Parser parser(idl_opts);
2578
2579   // Load all the schema versions and their associated data.
2580   for (int i = 0; i < NUM_VERSIONS; ++i) {
2581     std::string schema = test_data_path + "evolution_test/evolution_v" +
2582                          flatbuffers::NumToString(i + 1) + ".fbs";
2583     TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
2584     std::string json = test_data_path + "evolution_test/evolution_v" +
2585                        flatbuffers::NumToString(i + 1) + ".json";
2586     TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));
2587
2588     TEST_ASSERT(parser.Parse(schemas[i].c_str()));
2589     TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));
2590
2591     auto bufLen = parser.builder_.GetSize();
2592     auto buf = parser.builder_.GetBufferPointer();
2593     binaries[i].reserve(bufLen);
2594     std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
2595   }
2596
2597   auto v2 = parser.LookupStruct("Evolution.V2.Root");
2598   TEST_NOTNULL(v2);
2599   auto j_type_field = v2->fields.Lookup("j_type");
2600   TEST_NOTNULL(j_type_field);
2601   TEST_ASSERT(j_type_field->deprecated);
2602 }
2603
2604 void UnionVectorTest() {
2605   // load FlatBuffer fbs schema and json.
2606   std::string schemafile, jsonfile;
2607   TEST_EQ(flatbuffers::LoadFile(
2608               (test_data_path + "union_vector/union_vector.fbs").c_str(), false,
2609               &schemafile),
2610           true);
2611   TEST_EQ(flatbuffers::LoadFile(
2612               (test_data_path + "union_vector/union_vector.json").c_str(),
2613               false, &jsonfile),
2614           true);
2615
2616   // parse schema.
2617   flatbuffers::IDLOptions idl_opts;
2618   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2619   flatbuffers::Parser parser(idl_opts);
2620   TEST_EQ(parser.Parse(schemafile.c_str()), true);
2621
2622   flatbuffers::FlatBufferBuilder fbb;
2623
2624   // union types.
2625   std::vector<uint8_t> types;
2626   types.push_back(static_cast<uint8_t>(Character_Belle));
2627   types.push_back(static_cast<uint8_t>(Character_MuLan));
2628   types.push_back(static_cast<uint8_t>(Character_BookFan));
2629   types.push_back(static_cast<uint8_t>(Character_Other));
2630   types.push_back(static_cast<uint8_t>(Character_Unused));
2631
2632   // union values.
2633   std::vector<flatbuffers::Offset<void>> characters;
2634   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
2635   characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
2636   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
2637   characters.push_back(fbb.CreateString("Other").Union());
2638   characters.push_back(fbb.CreateString("Unused").Union());
2639
2640   // create Movie.
2641   const auto movie_offset =
2642       CreateMovie(fbb, Character_Rapunzel,
2643                   fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
2644                   fbb.CreateVector(types), fbb.CreateVector(characters));
2645   FinishMovieBuffer(fbb, movie_offset);
2646
2647   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
2648   TEST_EQ(VerifyMovieBuffer(verifier), true);
2649
2650   auto flat_movie = GetMovie(fbb.GetBufferPointer());
2651
2652   auto TestMovie = [](const Movie *movie) {
2653     TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
2654
2655     auto cts = movie->characters_type();
2656     TEST_EQ(movie->characters_type()->size(), 5);
2657     TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
2658     TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
2659     TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
2660     TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
2661     TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
2662
2663     auto rapunzel = movie->main_character_as_Rapunzel();
2664     TEST_NOTNULL(rapunzel);
2665     TEST_EQ(rapunzel->hair_length(), 6);
2666
2667     auto cs = movie->characters();
2668     TEST_EQ(cs->size(), 5);
2669     auto belle = cs->GetAs<BookReader>(0);
2670     TEST_EQ(belle->books_read(), 7);
2671     auto mu_lan = cs->GetAs<Attacker>(1);
2672     TEST_EQ(mu_lan->sword_attack_damage(), 5);
2673     auto book_fan = cs->GetAs<BookReader>(2);
2674     TEST_EQ(book_fan->books_read(), 2);
2675     auto other = cs->GetAsString(3);
2676     TEST_EQ_STR(other->c_str(), "Other");
2677     auto unused = cs->GetAsString(4);
2678     TEST_EQ_STR(unused->c_str(), "Unused");
2679   };
2680
2681   TestMovie(flat_movie);
2682
2683   // Also test the JSON we loaded above.
2684   TEST_EQ(parser.Parse(jsonfile.c_str()), true);
2685   auto jbuf = parser.builder_.GetBufferPointer();
2686   flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
2687   TEST_EQ(VerifyMovieBuffer(jverifier), true);
2688   TestMovie(GetMovie(jbuf));
2689
2690   auto movie_object = flat_movie->UnPack();
2691   TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
2692   TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
2693   TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
2694   TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
2695   TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
2696   TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
2697
2698   fbb.Clear();
2699   fbb.Finish(Movie::Pack(fbb, movie_object));
2700
2701   delete movie_object;
2702
2703   auto repacked_movie = GetMovie(fbb.GetBufferPointer());
2704
2705   TestMovie(repacked_movie);
2706
2707   // Generate text using mini-reflection.
2708   auto s =
2709       flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
2710   TEST_EQ_STR(
2711       s.c_str(),
2712       "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
2713       "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
2714       "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
2715       "{ books_read: 2 }, \"Other\", \"Unused\" ] }");
2716
2717   flatbuffers::ToStringVisitor visitor("\n", true, "  ");
2718   IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor);
2719   TEST_EQ_STR(visitor.s.c_str(),
2720               "{\n"
2721               "  \"main_character_type\": \"Rapunzel\",\n"
2722               "  \"main_character\": {\n"
2723               "    \"hair_length\": 6\n"
2724               "  },\n"
2725               "  \"characters_type\": [\n"
2726               "    \"Belle\",\n"
2727               "    \"MuLan\",\n"
2728               "    \"BookFan\",\n"
2729               "    \"Other\",\n"
2730               "    \"Unused\"\n"
2731               "  ],\n"
2732               "  \"characters\": [\n"
2733               "    {\n"
2734               "      \"books_read\": 7\n"
2735               "    },\n"
2736               "    {\n"
2737               "      \"sword_attack_damage\": 5\n"
2738               "    },\n"
2739               "    {\n"
2740               "      \"books_read\": 2\n"
2741               "    },\n"
2742               "    \"Other\",\n"
2743               "    \"Unused\"\n"
2744               "  ]\n"
2745               "}");
2746
2747   // Generate text using parsed schema.
2748   std::string jsongen;
2749   auto result = GenerateText(parser, fbb.GetBufferPointer(), &jsongen);
2750   TEST_EQ(result, true);
2751   TEST_EQ_STR(jsongen.c_str(),
2752               "{\n"
2753               "  main_character_type: \"Rapunzel\",\n"
2754               "  main_character: {\n"
2755               "    hair_length: 6\n"
2756               "  },\n"
2757               "  characters_type: [\n"
2758               "    \"Belle\",\n"
2759               "    \"MuLan\",\n"
2760               "    \"BookFan\",\n"
2761               "    \"Other\",\n"
2762               "    \"Unused\"\n"
2763               "  ],\n"
2764               "  characters: [\n"
2765               "    {\n"
2766               "      books_read: 7\n"
2767               "    },\n"
2768               "    {\n"
2769               "      sword_attack_damage: 5\n"
2770               "    },\n"
2771               "    {\n"
2772               "      books_read: 2\n"
2773               "    },\n"
2774               "    \"Other\",\n"
2775               "    \"Unused\"\n"
2776               "  ]\n"
2777               "}\n");
2778
2779   // Simple test with reflection.
2780   parser.Serialize();
2781   auto schema = reflection::GetSchema(parser.builder_.GetBufferPointer());
2782   auto ok = flatbuffers::Verify(*schema, *schema->root_table(),
2783                                 fbb.GetBufferPointer(), fbb.GetSize());
2784   TEST_EQ(ok, true);
2785
2786   flatbuffers::Parser parser2(idl_opts);
2787   TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
2788                         "union Any { Bool }"
2789                         "table Root { a:Any; }"
2790                         "root_type Root;"),
2791           true);
2792   TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
2793 }
2794
2795 void ConformTest() {
2796   flatbuffers::Parser parser;
2797   TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);
2798
2799   auto test_conform = [](flatbuffers::Parser &parser1, const char *test,
2800                          const char *expected_err) {
2801     flatbuffers::Parser parser2;
2802     TEST_EQ(parser2.Parse(test), true);
2803     auto err = parser2.ConformTo(parser1);
2804     TEST_NOTNULL(strstr(err.c_str(), expected_err));
2805   };
2806
2807   test_conform(parser, "table T { A:byte; }", "types differ for field");
2808   test_conform(parser, "table T { B:int; A:int; }", "offsets differ for field");
2809   test_conform(parser, "table T { A:int = 1; }", "defaults differ for field");
2810   test_conform(parser, "table T { B:float; }",
2811                "field renamed to different type");
2812   test_conform(parser, "enum E:byte { B, A }", "values differ for enum");
2813 }
2814
2815 void ParseProtoBufAsciiTest() {
2816   // We can put the parser in a mode where it will accept JSON that looks more
2817   // like Protobuf ASCII, for users that have data in that format.
2818   // This uses no "" for field names (which we already support by default,
2819   // omits `,`, `:` before `{` and a couple of other features.
2820   flatbuffers::Parser parser;
2821   parser.opts.protobuf_ascii_alike = true;
2822   TEST_EQ(
2823       parser.Parse("table S { B:int; } table T { A:[int]; C:S; } root_type T;"),
2824       true);
2825   TEST_EQ(parser.Parse("{ A [1 2] C { B:2 }}"), true);
2826   // Similarly, in text output, it should omit these.
2827   std::string text;
2828   auto ok = flatbuffers::GenerateText(
2829       parser, parser.builder_.GetBufferPointer(), &text);
2830   TEST_EQ(ok, true);
2831   TEST_EQ_STR(text.c_str(),
2832               "{\n  A [\n    1\n    2\n  ]\n  C {\n    B: 2\n  }\n}\n");
2833 }
2834
2835 void FlexBuffersTest() {
2836   flexbuffers::Builder slb(512,
2837                            flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
2838
2839   // Write the equivalent of:
2840   // { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ],
2841   // foo: 100, bool: true, mymap: { foo: "Fred" } }
2842   // clang-format off
2843   #ifndef FLATBUFFERS_CPP98_STL
2844     // It's possible to do this without std::function support as well.
2845     slb.Map([&]() {
2846        slb.Vector("vec", [&]() {
2847         slb += -100;  // Equivalent to slb.Add(-100) or slb.Int(-100);
2848         slb += "Fred";
2849         slb.IndirectFloat(4.0f);
2850         auto i_f = slb.LastValue();
2851         uint8_t blob[] = { 77 };
2852         slb.Blob(blob, 1);
2853         slb += false;
2854         slb.ReuseValue(i_f);
2855       });
2856       int ints[] = { 1, 2, 3 };
2857       slb.Vector("bar", ints, 3);
2858       slb.FixedTypedVector("bar3", ints, 3);
2859       bool bools[] = {true, false, true, false};
2860       slb.Vector("bools", bools, 4);
2861       slb.Bool("bool", true);
2862       slb.Double("foo", 100);
2863       slb.Map("mymap", [&]() {
2864         slb.String("foo", "Fred");  // Testing key and string reuse.
2865       });
2866     });
2867     slb.Finish();
2868   #else
2869     // It's possible to do this without std::function support as well.
2870     slb.Map([](flexbuffers::Builder& slb2) {
2871        slb2.Vector("vec", [](flexbuffers::Builder& slb3) {
2872         slb3 += -100;  // Equivalent to slb.Add(-100) or slb.Int(-100);
2873         slb3 += "Fred";
2874         slb3.IndirectFloat(4.0f);
2875         auto i_f = slb3.LastValue();
2876         uint8_t blob[] = { 77 };
2877         slb3.Blob(blob, 1);
2878         slb3 += false;
2879         slb3.ReuseValue(i_f);
2880       }, slb2);
2881       int ints[] = { 1, 2, 3 };
2882       slb2.Vector("bar", ints, 3);
2883       slb2.FixedTypedVector("bar3", ints, 3);
2884       slb2.Bool("bool", true);
2885       slb2.Double("foo", 100);
2886       slb2.Map("mymap", [](flexbuffers::Builder& slb3) {
2887         slb3.String("foo", "Fred");  // Testing key and string reuse.
2888       }, slb2);
2889     }, slb);
2890     slb.Finish();
2891   #endif  // FLATBUFFERS_CPP98_STL
2892
2893   #ifdef FLATBUFFERS_TEST_VERBOSE
2894     for (size_t i = 0; i < slb.GetBuffer().size(); i++)
2895       printf("%d ", flatbuffers::vector_data(slb.GetBuffer())[i]);
2896     printf("\n");
2897   #endif
2898   // clang-format on
2899
2900   auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap();
2901   TEST_EQ(map.size(), 7);
2902   auto vec = map["vec"].AsVector();
2903   TEST_EQ(vec.size(), 6);
2904   TEST_EQ(vec[0].AsInt64(), -100);
2905   TEST_EQ_STR(vec[1].AsString().c_str(), "Fred");
2906   TEST_EQ(vec[1].AsInt64(), 0);  // Number parsing failed.
2907   TEST_EQ(vec[2].AsDouble(), 4.0);
2908   TEST_EQ(vec[2].AsString().IsTheEmptyString(), true);  // Wrong Type.
2909   TEST_EQ_STR(vec[2].AsString().c_str(), "");     // This still works though.
2910   TEST_EQ_STR(vec[2].ToString().c_str(), "4.0");  // Or have it converted.
2911   // Few tests for templated version of As.
2912   TEST_EQ(vec[0].As<int64_t>(), -100);
2913   TEST_EQ_STR(vec[1].As<std::string>().c_str(), "Fred");
2914   TEST_EQ(vec[1].As<int64_t>(), 0);  // Number parsing failed.
2915   TEST_EQ(vec[2].As<double>(), 4.0);
2916   // Test that the blob can be accessed.
2917   TEST_EQ(vec[3].IsBlob(), true);
2918   auto blob = vec[3].AsBlob();
2919   TEST_EQ(blob.size(), 1);
2920   TEST_EQ(blob.data()[0], 77);
2921   TEST_EQ(vec[4].IsBool(), true);   // Check if type is a bool
2922   TEST_EQ(vec[4].AsBool(), false);  // Check if value is false
2923   TEST_EQ(vec[5].AsDouble(), 4.0);  // This is shared with vec[2] !
2924   auto tvec = map["bar"].AsTypedVector();
2925   TEST_EQ(tvec.size(), 3);
2926   TEST_EQ(tvec[2].AsInt8(), 3);
2927   auto tvec3 = map["bar3"].AsFixedTypedVector();
2928   TEST_EQ(tvec3.size(), 3);
2929   TEST_EQ(tvec3[2].AsInt8(), 3);
2930   TEST_EQ(map["bool"].AsBool(), true);
2931   auto tvecb = map["bools"].AsTypedVector();
2932   TEST_EQ(tvecb.ElementType(), flexbuffers::FBT_BOOL);
2933   TEST_EQ(map["foo"].AsUInt8(), 100);
2934   TEST_EQ(map["unknown"].IsNull(), true);
2935   auto mymap = map["mymap"].AsMap();
2936   // These should be equal by pointer equality, since key and value are shared.
2937   TEST_EQ(mymap.Keys()[0].AsKey(), map.Keys()[4].AsKey());
2938   TEST_EQ(mymap.Values()[0].AsString().c_str(), vec[1].AsString().c_str());
2939   // We can mutate values in the buffer.
2940   TEST_EQ(vec[0].MutateInt(-99), true);
2941   TEST_EQ(vec[0].AsInt64(), -99);
2942   TEST_EQ(vec[1].MutateString("John"), true);  // Size must match.
2943   TEST_EQ_STR(vec[1].AsString().c_str(), "John");
2944   TEST_EQ(vec[1].MutateString("Alfred"), false);  // Too long.
2945   TEST_EQ(vec[2].MutateFloat(2.0f), true);
2946   TEST_EQ(vec[2].AsFloat(), 2.0f);
2947   TEST_EQ(vec[2].MutateFloat(3.14159), false);  // Double does not fit in float.
2948   TEST_EQ(vec[4].AsBool(), false);              // Is false before change
2949   TEST_EQ(vec[4].MutateBool(true), true);       // Can change a bool
2950   TEST_EQ(vec[4].AsBool(), true);               // Changed bool is now true
2951
2952   // Parse from JSON:
2953   flatbuffers::Parser parser;
2954   slb.Clear();
2955   auto jsontest = "{ a: [ 123, 456.0 ], b: \"hello\", c: true, d: false }";
2956   TEST_EQ(parser.ParseFlexBuffer(jsontest, nullptr, &slb), true);
2957   auto jroot = flexbuffers::GetRoot(slb.GetBuffer());
2958   auto jmap = jroot.AsMap();
2959   auto jvec = jmap["a"].AsVector();
2960   TEST_EQ(jvec[0].AsInt64(), 123);
2961   TEST_EQ(jvec[1].AsDouble(), 456.0);
2962   TEST_EQ_STR(jmap["b"].AsString().c_str(), "hello");
2963   TEST_EQ(jmap["c"].IsBool(), true);   // Parsed correctly to a bool
2964   TEST_EQ(jmap["c"].AsBool(), true);   // Parsed correctly to true
2965   TEST_EQ(jmap["d"].IsBool(), true);   // Parsed correctly to a bool
2966   TEST_EQ(jmap["d"].AsBool(), false);  // Parsed correctly to false
2967   // And from FlexBuffer back to JSON:
2968   auto jsonback = jroot.ToString();
2969   TEST_EQ_STR(jsontest, jsonback.c_str());
2970
2971   slb.Clear();
2972   slb.Vector([&]() {
2973     for (int i = 0; i < 130; ++i) slb.Add(static_cast<uint8_t>(255));
2974     slb.Vector([&]() {
2975       for (int i = 0; i < 130; ++i) slb.Add(static_cast<uint8_t>(255));
2976       slb.Vector([] {});
2977     });
2978   });
2979   slb.Finish();
2980   TEST_EQ(slb.GetSize(), 664);
2981 }
2982
2983 void FlexBuffersDeprecatedTest() {
2984   // FlexBuffers as originally designed had a flaw involving the
2985   // FBT_VECTOR_STRING datatype, and this test documents/tests the fix for it.
2986   // Discussion: https://github.com/google/flatbuffers/issues/5627
2987   flexbuffers::Builder slb;
2988   // FBT_VECTOR_* are "typed vectors" where all elements are of the same type.
2989   // Problem is, when storing FBT_STRING elements, it relies on that type to
2990   // get the bit-width for the size field of the string, which in this case
2991   // isn't present, and instead defaults to 8-bit. This means that any strings
2992   // stored inside such a vector, when accessed thru the old API that returns
2993   // a String reference, will appear to be truncated if the string stored is
2994   // actually >=256 bytes.
2995   std::string test_data(300, 'A');
2996   auto start = slb.StartVector();
2997   // This one will have a 16-bit size field.
2998   slb.String(test_data);
2999   // This one will have an 8-bit size field.
3000   slb.String("hello");
3001   // We're asking this to be serialized as a typed vector (true), but not
3002   // fixed size (false). The type will be FBT_VECTOR_STRING with a bit-width
3003   // of whatever the offsets in the vector need, the bit-widths of the strings
3004   // are not stored(!) <- the actual design flaw.
3005   // Note that even in the fixed code, we continue to serialize the elements of
3006   // FBT_VECTOR_STRING as FBT_STRING, since there may be old code out there
3007   // reading new data that we want to continue to function.
3008   // Thus, FBT_VECTOR_STRING, while deprecated, will always be represented the
3009   // same way, the fix lies on the reading side.
3010   slb.EndVector(start, true, false);
3011   slb.Finish();
3012   // So now lets read this data back.
3013   // For existing data, since we have no way of knowing what the actual
3014   // bit-width of the size field of the string is, we are going to ignore this
3015   // field, and instead treat these strings as FBT_KEY (null-terminated), so we
3016   // can deal with strings of arbitrary length. This of course truncates strings
3017   // with embedded nulls, but we think that that is preferrable over truncating
3018   // strings >= 256 bytes.
3019   auto vec = flexbuffers::GetRoot(slb.GetBuffer()).AsTypedVector();
3020   // Even though this was serialized as FBT_VECTOR_STRING, it is read as
3021   // FBT_VECTOR_KEY:
3022   TEST_EQ(vec.ElementType(), flexbuffers::FBT_KEY);
3023   // Access the long string. Previously, this would return a string of size 1,
3024   // since it would read the high-byte of the 16-bit length.
3025   // This should now correctly test the full 300 bytes, using AsKey():
3026   TEST_EQ_STR(vec[0].AsKey(), test_data.c_str());
3027   // Old code that called AsString will continue to work, as the String
3028   // accessor objects now use a cached size that can come from a key as well.
3029   TEST_EQ_STR(vec[0].AsString().c_str(), test_data.c_str());
3030   // Short strings work as before:
3031   TEST_EQ_STR(vec[1].AsKey(), "hello");
3032   TEST_EQ_STR(vec[1].AsString().c_str(), "hello");
3033   // So, while existing code and data mostly "just work" with the fixes applied
3034   // to AsTypedVector and AsString, what do you do going forward?
3035   // Code accessing existing data doesn't necessarily need to change, though
3036   // you could consider using AsKey instead of AsString for a) documenting
3037   // that you are accessing keys, or b) a speedup if you don't actually use
3038   // the string size.
3039   // For new data, or data that doesn't need to be backwards compatible,
3040   // instead serialize as FBT_VECTOR (call EndVector with typed = false, then
3041   // read elements with AsString), or, for maximum compactness, use
3042   // FBT_VECTOR_KEY (call slb.Key above instead, read with AsKey or AsString).
3043 }
3044
3045 void TypeAliasesTest() {
3046   flatbuffers::FlatBufferBuilder builder;
3047
3048   builder.Finish(CreateTypeAliases(
3049       builder, flatbuffers::numeric_limits<int8_t>::min(),
3050       flatbuffers::numeric_limits<uint8_t>::max(),
3051       flatbuffers::numeric_limits<int16_t>::min(),
3052       flatbuffers::numeric_limits<uint16_t>::max(),
3053       flatbuffers::numeric_limits<int32_t>::min(),
3054       flatbuffers::numeric_limits<uint32_t>::max(),
3055       flatbuffers::numeric_limits<int64_t>::min(),
3056       flatbuffers::numeric_limits<uint64_t>::max(), 2.3f, 2.3));
3057
3058   auto p = builder.GetBufferPointer();
3059   auto ta = flatbuffers::GetRoot<TypeAliases>(p);
3060
3061   TEST_EQ(ta->i8(), flatbuffers::numeric_limits<int8_t>::min());
3062   TEST_EQ(ta->u8(), flatbuffers::numeric_limits<uint8_t>::max());
3063   TEST_EQ(ta->i16(), flatbuffers::numeric_limits<int16_t>::min());
3064   TEST_EQ(ta->u16(), flatbuffers::numeric_limits<uint16_t>::max());
3065   TEST_EQ(ta->i32(), flatbuffers::numeric_limits<int32_t>::min());
3066   TEST_EQ(ta->u32(), flatbuffers::numeric_limits<uint32_t>::max());
3067   TEST_EQ(ta->i64(), flatbuffers::numeric_limits<int64_t>::min());
3068   TEST_EQ(ta->u64(), flatbuffers::numeric_limits<uint64_t>::max());
3069   TEST_EQ(ta->f32(), 2.3f);
3070   TEST_EQ(ta->f64(), 2.3);
3071   using namespace flatbuffers;  // is_same
3072   static_assert(is_same<decltype(ta->i8()), int8_t>::value, "invalid type");
3073   static_assert(is_same<decltype(ta->i16()), int16_t>::value, "invalid type");
3074   static_assert(is_same<decltype(ta->i32()), int32_t>::value, "invalid type");
3075   static_assert(is_same<decltype(ta->i64()), int64_t>::value, "invalid type");
3076   static_assert(is_same<decltype(ta->u8()), uint8_t>::value, "invalid type");
3077   static_assert(is_same<decltype(ta->u16()), uint16_t>::value, "invalid type");
3078   static_assert(is_same<decltype(ta->u32()), uint32_t>::value, "invalid type");
3079   static_assert(is_same<decltype(ta->u64()), uint64_t>::value, "invalid type");
3080   static_assert(is_same<decltype(ta->f32()), float>::value, "invalid type");
3081   static_assert(is_same<decltype(ta->f64()), double>::value, "invalid type");
3082 }
3083
3084 void EndianSwapTest() {
3085   TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
3086   TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
3087           0x78563412);
3088   TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
3089           0xEFCDAB9078563412);
3090   TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
3091 }
3092
3093 void UninitializedVectorTest() {
3094   flatbuffers::FlatBufferBuilder builder;
3095
3096   Test *buf = nullptr;
3097   auto vector_offset =
3098       builder.CreateUninitializedVectorOfStructs<Test>(2, &buf);
3099   TEST_NOTNULL(buf);
3100   buf[0] = Test(10, 20);
3101   buf[1] = Test(30, 40);
3102
3103   auto required_name = builder.CreateString("myMonster");
3104   auto monster_builder = MonsterBuilder(builder);
3105   monster_builder.add_name(
3106       required_name);  // required field mandated for monster.
3107   monster_builder.add_test4(vector_offset);
3108   builder.Finish(monster_builder.Finish());
3109
3110   auto p = builder.GetBufferPointer();
3111   auto uvt = flatbuffers::GetRoot<Monster>(p);
3112   TEST_NOTNULL(uvt);
3113   auto vec = uvt->test4();
3114   TEST_NOTNULL(vec);
3115   auto test_0 = vec->Get(0);
3116   auto test_1 = vec->Get(1);
3117   TEST_EQ(test_0->a(), 10);
3118   TEST_EQ(test_0->b(), 20);
3119   TEST_EQ(test_1->a(), 30);
3120   TEST_EQ(test_1->b(), 40);
3121 }
3122
3123 void EqualOperatorTest() {
3124   MonsterT a;
3125   MonsterT b;
3126   TEST_EQ(b == a, true);
3127   TEST_EQ(b != a, false);
3128
3129   b.mana = 33;
3130   TEST_EQ(b == a, false);
3131   TEST_EQ(b != a, true);
3132   b.mana = 150;
3133   TEST_EQ(b == a, true);
3134   TEST_EQ(b != a, false);
3135
3136   b.inventory.push_back(3);
3137   TEST_EQ(b == a, false);
3138   TEST_EQ(b != a, true);
3139   b.inventory.clear();
3140   TEST_EQ(b == a, true);
3141   TEST_EQ(b != a, false);
3142
3143   b.test.type = Any_Monster;
3144   TEST_EQ(b == a, false);
3145   TEST_EQ(b != a, true);
3146 }
3147
3148 // For testing any binaries, e.g. from fuzzing.
3149 void LoadVerifyBinaryTest() {
3150   std::string binary;
3151   if (flatbuffers::LoadFile(
3152           (test_data_path + "fuzzer/your-filename-here").c_str(), true,
3153           &binary)) {
3154     flatbuffers::Verifier verifier(
3155         reinterpret_cast<const uint8_t *>(binary.data()), binary.size());
3156     TEST_EQ(VerifyMonsterBuffer(verifier), true);
3157   }
3158 }
3159
3160 void CreateSharedStringTest() {
3161   flatbuffers::FlatBufferBuilder builder;
3162   const auto one1 = builder.CreateSharedString("one");
3163   const auto two = builder.CreateSharedString("two");
3164   const auto one2 = builder.CreateSharedString("one");
3165   TEST_EQ(one1.o, one2.o);
3166   const auto onetwo = builder.CreateSharedString("onetwo");
3167   TEST_EQ(onetwo.o != one1.o, true);
3168   TEST_EQ(onetwo.o != two.o, true);
3169
3170   // Support for embedded nulls
3171   const char chars_b[] = { 'a', '\0', 'b' };
3172   const char chars_c[] = { 'a', '\0', 'c' };
3173   const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b));
3174   const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c));
3175   const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b));
3176   TEST_EQ(null_b1.o != null_c.o, true);  // Issue#5058 repro
3177   TEST_EQ(null_b1.o, null_b2.o);
3178
3179   // Put the strings into an array for round trip verification.
3180   const flatbuffers::Offset<flatbuffers::String> array[7] = {
3181     one1, two, one2, onetwo, null_b1, null_c, null_b2
3182   };
3183   const auto vector_offset =
3184       builder.CreateVector(array, flatbuffers::uoffset_t(7));
3185   MonsterBuilder monster_builder(builder);
3186   monster_builder.add_name(two);
3187   monster_builder.add_testarrayofstring(vector_offset);
3188   builder.Finish(monster_builder.Finish());
3189
3190   // Read the Monster back.
3191   const auto *monster =
3192       flatbuffers::GetRoot<Monster>(builder.GetBufferPointer());
3193   TEST_EQ_STR(monster->name()->c_str(), "two");
3194   const auto *testarrayofstring = monster->testarrayofstring();
3195   TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7));
3196   const auto &a = *testarrayofstring;
3197   TEST_EQ_STR(a[0]->c_str(), "one");
3198   TEST_EQ_STR(a[1]->c_str(), "two");
3199   TEST_EQ_STR(a[2]->c_str(), "one");
3200   TEST_EQ_STR(a[3]->c_str(), "onetwo");
3201   TEST_EQ(a[4]->str(), (std::string(chars_b, sizeof(chars_b))));
3202   TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c))));
3203   TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b))));
3204
3205   // Make sure String::operator< works, too, since it is related to
3206   // StringOffsetCompare.
3207   TEST_EQ((*a[0]) < (*a[1]), true);
3208   TEST_EQ((*a[1]) < (*a[0]), false);
3209   TEST_EQ((*a[1]) < (*a[2]), false);
3210   TEST_EQ((*a[2]) < (*a[1]), true);
3211   TEST_EQ((*a[4]) < (*a[3]), true);
3212   TEST_EQ((*a[5]) < (*a[4]), false);
3213   TEST_EQ((*a[5]) < (*a[4]), false);
3214   TEST_EQ((*a[6]) < (*a[5]), true);
3215 }
3216
3217 #if !defined(FLATBUFFERS_SPAN_MINIMAL)
3218 void FlatbuffersSpanTest() {
3219   // Compile-time checking of non-const [] to const [] conversions.
3220   using flatbuffers::internal::is_span_convertable;
3221   (void)is_span_convertable<int, 1, int, 1>::type(123);
3222   (void)is_span_convertable<const int, 1, int, 1>::type(123);
3223   (void)is_span_convertable<const int64_t, 1, int64_t, 1>::type(123);
3224   (void)is_span_convertable<const uint64_t, 1, uint64_t, 1>::type(123);
3225   (void)is_span_convertable<const int, 1, const int, 1>::type(123);
3226   (void)is_span_convertable<const int64_t, 1, const int64_t, 1>::type(123);
3227   (void)is_span_convertable<const uint64_t, 1, const uint64_t, 1>::type(123);
3228
3229   using flatbuffers::span;
3230   span<char, 0> c1;
3231   TEST_EQ(c1.size(), 0);
3232   span<char, flatbuffers::dynamic_extent> c2;
3233   TEST_EQ(c2.size(), 0);
3234   span<char> c3;
3235   TEST_EQ(c3.size(), 0);
3236   TEST_ASSERT(c1.empty() && c2.empty() && c3.empty());
3237
3238   int i_data7[7] = { 0, 1, 2, 3, 4, 5, 6 };
3239   span<int, 7> i1(&i_data7[0], 7);
3240   span<int> i2(i1);  // make dynamic from static
3241   TEST_EQ(i1.size(), 7);
3242   TEST_EQ(i1.empty(), false);
3243   TEST_EQ(i1.size(), i2.size());
3244   TEST_EQ(i1.data(), i_data7);
3245   TEST_EQ(i1[2], 2);
3246   // Make const span from a non-const one.
3247   span<const int, 7> i3(i1);
3248   // Construct from a C-array.
3249   span<int, 7> i4(i_data7);
3250   span<const int, 7> i5(i_data7);
3251   span<int> i6(i_data7);
3252   span<const int> i7(i_data7);
3253   TEST_EQ(i7.size(), 7);
3254   // Check construction from a const array.
3255   const int i_cdata5[5] = { 4, 3, 2, 1, 0 };
3256   span<const int, 5> i8(i_cdata5);
3257   span<const int> i9(i_cdata5);
3258   TEST_EQ(i9.size(), 5);
3259   // Construction from a (ptr, size) pair.
3260   span<int, 7> i10(i_data7, 7);
3261   span<int> i11(i_data7, 7);
3262   TEST_EQ(i11.size(), 7);
3263   span<const int, 5> i12(i_cdata5, 5);
3264   span<const int> i13(i_cdata5, 5);
3265   TEST_EQ(i13.size(), 5);
3266   // Construction from std::array.
3267   std::array<int, 6> i_arr6 = { { 0, 1, 2, 3, 4, 5 } };
3268   span<int, 6> i14(i_arr6);
3269   span<const int, 6> i15(i_arr6);
3270   span<int> i16(i_arr6);
3271   span<const int> i17(i_arr6);
3272   TEST_EQ(i17.size(), 6);
3273   const std::array<int, 8> i_carr8 = { { 0, 1, 2, 3, 4, 5, 6, 7 } };
3274   span<const int, 8> i18(i_carr8);
3275   span<const int> i19(i_carr8);
3276   TEST_EQ(i18.size(), 8);
3277   TEST_EQ(i19.size(), 8);
3278   TEST_EQ(i19[7], 7);
3279   // Check compatibility with flatbuffers::Array.
3280   int fbs_int3_underlaying[3] = { 0 };
3281   int fbs_int3_data[3] = { 1, 2, 3 };
3282   auto &fbs_int3 = flatbuffers::CastToArray(fbs_int3_underlaying);
3283   fbs_int3.CopyFromSpan(fbs_int3_data);
3284   TEST_EQ(fbs_int3.Get(1), 2);
3285   const int fbs_cint3_data[3] = { 2, 3, 4 };
3286   fbs_int3.CopyFromSpan(fbs_cint3_data);
3287   TEST_EQ(fbs_int3.Get(1), 3);
3288   // Check with Array<Enum, N>
3289   enum class Dummy : uint16_t { Zero = 0, One, Two };
3290   Dummy fbs_dummy3_underlaying[3] = {};
3291   Dummy fbs_dummy3_data[3] = { Dummy::One, Dummy::Two, Dummy::Two };
3292   auto &fbs_dummy3 = flatbuffers::CastToArray(fbs_dummy3_underlaying);
3293   fbs_dummy3.CopyFromSpan(fbs_dummy3_data);
3294   TEST_EQ(fbs_dummy3.Get(1), Dummy::Two);
3295 }
3296 #else
3297 void FlatbuffersSpanTest() {}
3298 #endif
3299
3300 void FixedLengthArrayTest() {
3301   // VS10 does not support typed enums, exclude from tests
3302 #if !defined(_MSC_VER) || _MSC_VER >= 1700
3303   // Generate an ArrayTable containing one ArrayStruct.
3304   flatbuffers::FlatBufferBuilder fbb;
3305   MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
3306   TEST_NOTNULL(nStruct0.mutable_a());
3307   nStruct0.mutable_a()->Mutate(0, 1);
3308   nStruct0.mutable_a()->Mutate(1, 2);
3309   TEST_NOTNULL(nStruct0.mutable_c());
3310   nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
3311   nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
3312   TEST_NOTNULL(nStruct0.mutable_d());
3313   nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
3314   nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
3315   MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
3316   TEST_NOTNULL(nStruct1.mutable_a());
3317   nStruct1.mutable_a()->Mutate(0, 3);
3318   nStruct1.mutable_a()->Mutate(1, 4);
3319   TEST_NOTNULL(nStruct1.mutable_c());
3320   nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
3321   nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
3322   TEST_NOTNULL(nStruct1.mutable_d());
3323   nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
3324   nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
3325   MyGame::Example::ArrayStruct aStruct(2, 12, 1);
3326   TEST_NOTNULL(aStruct.b());
3327   TEST_NOTNULL(aStruct.mutable_b());
3328   TEST_NOTNULL(aStruct.mutable_d());
3329   TEST_NOTNULL(aStruct.mutable_f());
3330   for (int i = 0; i < aStruct.b()->size(); i++)
3331     aStruct.mutable_b()->Mutate(i, i + 1);
3332   aStruct.mutable_d()->Mutate(0, nStruct0);
3333   aStruct.mutable_d()->Mutate(1, nStruct1);
3334   auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
3335   MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
3336
3337   // Verify correctness of the ArrayTable.
3338   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
3339   MyGame::Example::VerifyArrayTableBuffer(verifier);
3340   auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
3341   auto mArStruct = p->mutable_a();
3342   TEST_NOTNULL(mArStruct);
3343   TEST_NOTNULL(mArStruct->b());
3344   TEST_NOTNULL(mArStruct->d());
3345   TEST_NOTNULL(mArStruct->f());
3346   TEST_NOTNULL(mArStruct->mutable_b());
3347   TEST_NOTNULL(mArStruct->mutable_d());
3348   TEST_NOTNULL(mArStruct->mutable_f());
3349   mArStruct->mutable_b()->Mutate(14, -14);
3350   TEST_EQ(mArStruct->a(), 2);
3351   TEST_EQ(mArStruct->b()->size(), 15);
3352   TEST_EQ(mArStruct->b()->Get(aStruct.b()->size() - 1), -14);
3353   TEST_EQ(mArStruct->c(), 12);
3354   TEST_NOTNULL(mArStruct->d()->Get(0));
3355   TEST_NOTNULL(mArStruct->d()->Get(0)->a());
3356   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(0), 1);
3357   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(1), 2);
3358   TEST_NOTNULL(mArStruct->d()->Get(1));
3359   TEST_NOTNULL(mArStruct->d()->Get(1)->a());
3360   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(0), 3);
3361   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 4);
3362   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
3363   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
3364   mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
3365   TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1));
3366   TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b());
3367   TEST_NOTNULL(mArStruct->d()->Get(0)->c());
3368   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0));
3369   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1));
3370   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
3371           mArStruct->d()->Get(0)->d()->Get(0));
3372   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
3373           mArStruct->d()->Get(0)->d()->Get(1));
3374   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b());
3375   TEST_NOTNULL(mArStruct->d()->Get(1)->c());
3376   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0));
3377   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1));
3378   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
3379           mArStruct->d()->Get(1)->d()->Get(0));
3380   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
3381           mArStruct->d()->Get(1)->d()->Get(1));
3382   for (int i = 0; i < mArStruct->b()->size() - 1; i++)
3383     TEST_EQ(mArStruct->b()->Get(i), i + 1);
3384   // Check alignment
3385   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->d()) % 8);
3386   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->f()) % 8);
3387
3388   // Check if default constructor set all memory zero
3389   const size_t arr_size = sizeof(MyGame::Example::ArrayStruct);
3390   char non_zero_memory[arr_size];
3391   // set memory chunk of size ArrayStruct to 1's
3392   std::memset(static_cast<void *>(non_zero_memory), 1, arr_size);
3393   // after placement-new it should be all 0's
3394 #if defined (_MSC_VER) && defined (_DEBUG)
3395   #undef new
3396 #endif
3397   MyGame::Example::ArrayStruct *ap = new (non_zero_memory) MyGame::Example::ArrayStruct;
3398 #if defined (_MSC_VER) && defined (_DEBUG)
3399   #define new DEBUG_NEW
3400 #endif
3401   (void)ap;
3402   for (size_t i = 0; i < arr_size; ++i) {
3403     TEST_EQ(non_zero_memory[i], 0);
3404   }
3405 #endif
3406 }
3407
3408 #if !defined(FLATBUFFERS_SPAN_MINIMAL) && (!defined(_MSC_VER) || _MSC_VER >= 1700)
3409 void FixedLengthArrayConstructorTest() {
3410   const int32_t nested_a[2] = { 1, 2 };
3411   MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A,
3412                                             MyGame::Example::TestEnum::B };
3413   const int64_t int64_2[2] = { -2, -1 };
3414
3415   std::array<MyGame::Example::NestedStruct, 2> init_d = {
3416     { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
3417                                     nested_c, int64_2),
3418       MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::A,
3419                                     nested_c,
3420                                     std::array<int64_t, 2>{ { 12, 13 } }) }
3421   };
3422
3423   MyGame::Example::ArrayStruct arr_struct(
3424       8.125,
3425       std::array<int32_t, 0xF>{
3426           { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
3427       -17, init_d, 10, int64_2);
3428   TEST_EQ(arr_struct.a(), 8.125);
3429   TEST_EQ(arr_struct.b()->Get(2), 3);
3430   TEST_EQ(arr_struct.c(), -17);
3431
3432   TEST_NOTNULL(arr_struct.d());
3433   const auto &arr_d_0 = *arr_struct.d()->Get(0);
3434   TEST_EQ(arr_d_0.a()->Get(0), 1);
3435   TEST_EQ(arr_d_0.a()->Get(1), 2);
3436   TEST_EQ(arr_d_0.b(), MyGame::Example::TestEnum::B);
3437   TEST_EQ(arr_d_0.c()->Get(0), MyGame::Example::TestEnum::A);
3438   TEST_EQ(arr_d_0.c()->Get(1), MyGame::Example::TestEnum::B);
3439   TEST_EQ(arr_d_0.d()->Get(0), -2);
3440   TEST_EQ(arr_d_0.d()->Get(1), -1);
3441   const auto &arr_d_1 = *arr_struct.d()->Get(1);
3442   TEST_EQ(arr_d_1.a()->Get(0), 1);
3443   TEST_EQ(arr_d_1.a()->Get(1), 2);
3444   TEST_EQ(arr_d_1.b(), MyGame::Example::TestEnum::A);
3445   TEST_EQ(arr_d_1.c()->Get(0), MyGame::Example::TestEnum::A);
3446   TEST_EQ(arr_d_1.c()->Get(1), MyGame::Example::TestEnum::B);
3447   TEST_EQ(arr_d_1.d()->Get(0), 12);
3448   TEST_EQ(arr_d_1.d()->Get(1), 13);
3449
3450   TEST_EQ(arr_struct.e(), 10);
3451   TEST_EQ(arr_struct.f()->Get(0), -2);
3452   TEST_EQ(arr_struct.f()->Get(1), -1);
3453 }
3454 #else
3455 void FixedLengthArrayConstructorTest() {
3456 }
3457 #endif
3458
3459 void NativeTypeTest() {
3460   const int N = 3;
3461
3462   Geometry::ApplicationDataT src_data;
3463   src_data.vectors.reserve(N);
3464
3465   for (int i = 0; i < N; ++i) {
3466     src_data.vectors.push_back(
3467         Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f));
3468   }
3469
3470   flatbuffers::FlatBufferBuilder fbb;
3471   fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data));
3472
3473   auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer());
3474
3475   for (int i = 0; i < N; ++i) {
3476     Native::Vector3D &v = dstDataT->vectors[i];
3477     TEST_EQ(v.x, 10 * i + 0.1f);
3478     TEST_EQ(v.y, 10 * i + 0.2f);
3479     TEST_EQ(v.z, 10 * i + 0.3f);
3480   }
3481 }
3482
3483 void FixedLengthArrayJsonTest(bool binary) {
3484   // VS10 does not support typed enums, exclude from tests
3485 #if !defined(_MSC_VER) || _MSC_VER >= 1700
3486   // load FlatBuffer schema (.fbs) and JSON from disk
3487   std::string schemafile;
3488   std::string jsonfile;
3489   TEST_EQ(
3490       flatbuffers::LoadFile(
3491           (test_data_path + "arrays_test." + (binary ? "bfbs" : "fbs")).c_str(),
3492           binary, &schemafile),
3493       true);
3494   TEST_EQ(flatbuffers::LoadFile((test_data_path + "arrays_test.golden").c_str(),
3495                                 false, &jsonfile),
3496           true);
3497
3498   // parse schema first, so we can use it to parse the data after
3499   flatbuffers::Parser parserOrg, parserGen;
3500   if (binary) {
3501     flatbuffers::Verifier verifier(
3502         reinterpret_cast<const uint8_t *>(schemafile.c_str()),
3503         schemafile.size());
3504     TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
3505     TEST_EQ(parserOrg.Deserialize((const uint8_t *)schemafile.c_str(),
3506                                   schemafile.size()),
3507             true);
3508     TEST_EQ(parserGen.Deserialize((const uint8_t *)schemafile.c_str(),
3509                                   schemafile.size()),
3510             true);
3511   } else {
3512     TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
3513     TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
3514   }
3515   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
3516
3517   // First, verify it, just in case:
3518   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
3519                                     parserOrg.builder_.GetSize());
3520   TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
3521
3522   // Export to JSON
3523   std::string jsonGen;
3524   TEST_EQ(
3525       GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
3526       true);
3527
3528   // Import from JSON
3529   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
3530
3531   // Verify buffer from generated JSON
3532   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
3533                                     parserGen.builder_.GetSize());
3534   TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
3535
3536   // Compare generated buffer to original
3537   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
3538   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
3539                       parserGen.builder_.GetBufferPointer(),
3540                       parserOrg.builder_.GetSize()),
3541           0);
3542 #else
3543   (void)binary;
3544 #endif
3545 }
3546
3547 void TestEmbeddedBinarySchema() {
3548   // load JSON from disk
3549   std::string jsonfile;
3550   TEST_EQ(flatbuffers::LoadFile(
3551               (test_data_path + "monsterdata_test.golden").c_str(), false,
3552               &jsonfile),
3553           true);
3554
3555   // parse schema first, so we can use it to parse the data after
3556   flatbuffers::Parser parserOrg, parserGen;
3557   flatbuffers::Verifier verifier(MyGame::Example::MonsterBinarySchema::data(),
3558                                  MyGame::Example::MonsterBinarySchema::size());
3559   TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
3560   TEST_EQ(parserOrg.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
3561                                 MyGame::Example::MonsterBinarySchema::size()),
3562           true);
3563   TEST_EQ(parserGen.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
3564                                 MyGame::Example::MonsterBinarySchema::size()),
3565           true);
3566   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
3567
3568   // First, verify it, just in case:
3569   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
3570                                     parserOrg.builder_.GetSize());
3571   TEST_EQ(VerifyMonsterBuffer(verifierOrg), true);
3572
3573   // Export to JSON
3574   std::string jsonGen;
3575   TEST_EQ(
3576       GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
3577       true);
3578
3579   // Import from JSON
3580   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
3581
3582   // Verify buffer from generated JSON
3583   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
3584                                     parserGen.builder_.GetSize());
3585   TEST_EQ(VerifyMonsterBuffer(verifierGen), true);
3586
3587   // Compare generated buffer to original
3588   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
3589   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
3590                       parserGen.builder_.GetBufferPointer(),
3591                       parserOrg.builder_.GetSize()),
3592           0);
3593 }
3594
3595 void OptionalScalarsTest() {
3596   // Simple schemas and a "has optional scalar" sentinal.
3597   std::vector<std::string> schemas;
3598   schemas.push_back("table Monster { mana : int; }");
3599   schemas.push_back("table Monster { mana : int = 42; }");
3600   schemas.push_back("table Monster { mana : int =  null; }");
3601   schemas.push_back("table Monster { mana : long; }");
3602   schemas.push_back("table Monster { mana : long = 42; }");
3603   schemas.push_back("table Monster { mana : long = null; }");
3604   schemas.push_back("table Monster { mana : float; }");
3605   schemas.push_back("table Monster { mana : float = 42; }");
3606   schemas.push_back("table Monster { mana : float = null; }");
3607   schemas.push_back("table Monster { mana : double; }");
3608   schemas.push_back("table Monster { mana : double = 42; }");
3609   schemas.push_back("table Monster { mana : double = null; }");
3610   schemas.push_back("table Monster { mana : bool; }");
3611   schemas.push_back("table Monster { mana : bool = 42; }");
3612   schemas.push_back("table Monster { mana : bool = null; }");
3613   schemas.push_back("enum Enum: int {A=0, B=1} "
3614                     "table Monster { mana : Enum; }");
3615   schemas.push_back("enum Enum: int {A=0, B=1} "
3616                     "table Monster { mana : Enum = B; }");
3617   schemas.push_back("enum Enum: int {A=0, B=1} "
3618                     "table Monster { mana : Enum = null; }");
3619
3620   // Check the FieldDef is correctly set.
3621   for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
3622     const bool has_null = schema->find("null") != std::string::npos;
3623     flatbuffers::Parser parser;
3624     TEST_ASSERT(parser.Parse(schema->c_str()));
3625     const auto *mana = parser.structs_.Lookup("Monster")->fields.Lookup("mana");
3626     TEST_EQ(mana->optional, has_null);
3627   }
3628
3629   // Test if nullable scalars are allowed for each language.
3630   for (unsigned lang = 1; lang < flatbuffers::IDLOptions::kMAX; lang <<= 1) {
3631     flatbuffers::IDLOptions opts;
3632     opts.lang_to_generate = lang;
3633     if (false == flatbuffers::Parser::SupportsOptionalScalars(opts)) {
3634       continue;
3635     }
3636     for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
3637       flatbuffers::Parser parser(opts);
3638       auto done = parser.Parse(schema->c_str());
3639       TEST_EQ_STR(parser.error_.c_str(), "");
3640       TEST_ASSERT(done);
3641     }
3642   }
3643
3644   // test C++ nullable
3645   flatbuffers::FlatBufferBuilder fbb;
3646   FinishScalarStuffBuffer(
3647       fbb, optional_scalars::CreateScalarStuff(fbb, 1, static_cast<int8_t>(2)));
3648   auto opts = optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer());
3649   TEST_ASSERT(!opts->maybe_bool());
3650   TEST_ASSERT(!opts->maybe_f32().has_value());
3651   TEST_ASSERT(opts->maybe_i8().has_value());
3652   TEST_EQ(opts->maybe_i8().value(), 2);
3653   TEST_ASSERT(opts->mutate_maybe_i8(3));
3654   TEST_ASSERT(opts->maybe_i8().has_value());
3655   TEST_EQ(opts->maybe_i8().value(), 3);
3656   TEST_ASSERT(!opts->mutate_maybe_i16(-10));
3657
3658   optional_scalars::ScalarStuffT obj;
3659   TEST_ASSERT(!obj.maybe_bool);
3660   TEST_ASSERT(!obj.maybe_f32.has_value());
3661   opts->UnPackTo(&obj);
3662   TEST_ASSERT(!obj.maybe_bool);
3663   TEST_ASSERT(!obj.maybe_f32.has_value());
3664   TEST_ASSERT(obj.maybe_i8.has_value() && obj.maybe_i8.value() == 3);
3665   TEST_ASSERT(obj.maybe_i8 && *obj.maybe_i8 == 3);
3666   obj.maybe_i32 = -1;
3667   obj.maybe_enum = optional_scalars::OptionalByte_Two;
3668
3669   fbb.Clear();
3670   FinishScalarStuffBuffer(fbb, optional_scalars::ScalarStuff::Pack(fbb, &obj));
3671   opts = optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer());
3672   TEST_ASSERT(opts->maybe_i8().has_value());
3673   TEST_EQ(opts->maybe_i8().value(), 3);
3674   TEST_ASSERT(opts->maybe_i32().has_value());
3675   TEST_EQ(opts->maybe_i32().value(), -1);
3676   TEST_EQ(opts->maybe_enum().value(), optional_scalars::OptionalByte_Two);
3677   TEST_ASSERT(opts->maybe_i32() == flatbuffers::Optional<int64_t>(-1));
3678 }
3679
3680 void ParseFlexbuffersFromJsonWithNullTest() {
3681   // Test nulls are handled appropriately through flexbuffers to exercise other
3682   // code paths of ParseSingleValue in the optional scalars change.
3683   // TODO(cneo): Json -> Flatbuffers test once some language can generate code
3684   // with optional scalars.
3685   {
3686     char json[] = "{\"opt_field\": 123 }";
3687     flatbuffers::Parser parser;
3688     flexbuffers::Builder flexbuild;
3689     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3690     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3691     TEST_EQ(root.AsMap()["opt_field"].AsInt64(), 123);
3692   }
3693   {
3694     char json[] = "{\"opt_field\": 123.4 }";
3695     flatbuffers::Parser parser;
3696     flexbuffers::Builder flexbuild;
3697     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3698     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3699     TEST_EQ(root.AsMap()["opt_field"].AsDouble(), 123.4);
3700   }
3701   {
3702     char json[] = "{\"opt_field\": null }";
3703     flatbuffers::Parser parser;
3704     flexbuffers::Builder flexbuild;
3705     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3706     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3707     TEST_ASSERT(!root.AsMap().IsTheEmptyMap());
3708     TEST_ASSERT(root.AsMap()["opt_field"].IsNull());
3709     TEST_EQ(root.ToString(), std::string("{ opt_field: null }"));
3710   }
3711 }
3712
3713 int FlatBufferTests() {
3714   // clang-format off
3715
3716   // Run our various test suites:
3717
3718   std::string rawbuf;
3719   auto flatbuf1 = CreateFlatBufferTest(rawbuf);
3720   #if !defined(FLATBUFFERS_CPP98_STL)
3721     auto flatbuf = std::move(flatbuf1);  // Test move assignment.
3722   #else
3723     auto &flatbuf = flatbuf1;
3724   #endif // !defined(FLATBUFFERS_CPP98_STL)
3725
3726   TriviallyCopyableTest();
3727
3728   AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()),
3729                        rawbuf.length());
3730   AccessFlatBufferTest(flatbuf.data(), flatbuf.size());
3731
3732   MutateFlatBuffersTest(flatbuf.data(), flatbuf.size());
3733
3734   ObjectFlatBuffersTest(flatbuf.data());
3735
3736   MiniReflectFlatBuffersTest(flatbuf.data());
3737   MiniReflectFixedLengthArrayTest();
3738
3739   SizePrefixedTest();
3740
3741   #ifndef FLATBUFFERS_NO_FILE_TESTS
3742     #ifdef FLATBUFFERS_TEST_PATH_PREFIX
3743       test_data_path = FLATBUFFERS_STRING(FLATBUFFERS_TEST_PATH_PREFIX) +
3744                        test_data_path;
3745     #endif
3746     ParseAndGenerateTextTest(false);
3747     ParseAndGenerateTextTest(true);
3748     FixedLengthArrayJsonTest(false);
3749     FixedLengthArrayJsonTest(true);
3750     ReflectionTest(flatbuf.data(), flatbuf.size());
3751     ParseProtoTest();
3752     ParseProtoTestWithSuffix();
3753     ParseProtoTestWithIncludes();
3754     EvolutionTest();
3755     UnionDeprecationTest();
3756     UnionVectorTest();
3757     LoadVerifyBinaryTest();
3758     GenerateTableTextTest();
3759     TestEmbeddedBinarySchema();
3760   #endif
3761   // clang-format on
3762
3763   FuzzTest1();
3764   FuzzTest2();
3765
3766   ErrorTest();
3767   ValueTest();
3768   EnumValueTest();
3769   EnumStringsTest();
3770   EnumNamesTest();
3771   EnumOutOfRangeTest();
3772   IntegerOutOfRangeTest();
3773   IntegerBoundaryTest();
3774   UnicodeTest();
3775   UnicodeTestAllowNonUTF8();
3776   UnicodeTestGenerateTextFailsOnNonUTF8();
3777   UnicodeSurrogatesTest();
3778   UnicodeInvalidSurrogatesTest();
3779   InvalidUTF8Test();
3780   UnknownFieldsTest();
3781   ParseUnionTest();
3782   InvalidNestedFlatbufferTest();
3783   ConformTest();
3784   ParseProtoBufAsciiTest();
3785   TypeAliasesTest();
3786   EndianSwapTest();
3787   CreateSharedStringTest();
3788   JsonDefaultTest();
3789   JsonEnumsTest();
3790   FlexBuffersTest();
3791   FlexBuffersDeprecatedTest();
3792   UninitializedVectorTest();
3793   EqualOperatorTest();
3794   NumericUtilsTest();
3795   IsAsciiUtilsTest();
3796   ValidFloatTest();
3797   InvalidFloatTest();
3798   TestMonsterExtraFloats();
3799   FixedLengthArrayTest();
3800   NativeTypeTest();
3801   OptionalScalarsTest();
3802   ParseFlexbuffersFromJsonWithNullTest();
3803   FlatbuffersSpanTest();
3804   FixedLengthArrayConstructorTest();
3805   return 0;
3806 }
3807
3808 int main(int /*argc*/, const char * /*argv*/[]) {
3809   InitTestEngine();
3810
3811   std::string req_locale;
3812   if (flatbuffers::ReadEnvironmentVariable("FLATBUFFERS_TEST_LOCALE",
3813                                            &req_locale)) {
3814     TEST_OUTPUT_LINE("The environment variable FLATBUFFERS_TEST_LOCALE=%s",
3815                      req_locale.c_str());
3816     req_locale = flatbuffers::RemoveStringQuotes(req_locale);
3817     std::string the_locale;
3818     TEST_ASSERT_FUNC(
3819         flatbuffers::SetGlobalTestLocale(req_locale.c_str(), &the_locale));
3820     TEST_OUTPUT_LINE("The global C-locale changed: %s", the_locale.c_str());
3821   }
3822
3823   FlatBufferTests();
3824   FlatBufferBuilderTest();
3825
3826   if (!testing_fails) {
3827     TEST_OUTPUT_LINE("ALL TESTS PASSED");
3828   } else {
3829     TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
3830   }
3831   return CloseTestEngine();
3832 }