Optional-ness in reflection (#6097)
[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   #include "flatbuffers/stl_emulation.h"
27   namespace std {
28     using flatbuffers::unique_ptr;
29   }
30 #endif
31 // clang-format on
32
33 #include "monster_test_generated.h"
34 #include "namespace_test/namespace_test1_generated.h"
35 #include "namespace_test/namespace_test2_generated.h"
36 #include "union_vector/union_vector_generated.h"
37 #include "monster_extra_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 // Parse a .proto schema, output as .fbs
1112 void ParseProtoTest() {
1113   // load the .proto and the golden file from disk
1114   std::string protofile;
1115   std::string goldenfile;
1116   std::string goldenunionfile;
1117   TEST_EQ(
1118       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1119                             false, &protofile),
1120       true);
1121   TEST_EQ(
1122       flatbuffers::LoadFile((test_data_path + "prototest/test.golden").c_str(),
1123                             false, &goldenfile),
1124       true);
1125   TEST_EQ(flatbuffers::LoadFile(
1126               (test_data_path + "prototest/test_union.golden").c_str(), false,
1127               &goldenunionfile),
1128           true);
1129
1130   flatbuffers::IDLOptions opts;
1131   opts.include_dependence_headers = false;
1132   opts.proto_mode = true;
1133
1134   // Parse proto.
1135   flatbuffers::Parser parser(opts);
1136   auto protopath = test_data_path + "prototest/";
1137   const char *include_directories[] = { protopath.c_str(), nullptr };
1138   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1139
1140   // Generate fbs.
1141   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1142
1143   // Ensure generated file is parsable.
1144   flatbuffers::Parser parser2;
1145   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1146   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1147
1148   // Parse proto with --oneof-union option.
1149   opts.proto_oneof_union = true;
1150   flatbuffers::Parser parser3(opts);
1151   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1152
1153   // Generate fbs.
1154   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1155
1156   // Ensure generated file is parsable.
1157   flatbuffers::Parser parser4;
1158   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1159   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1160 }
1161
1162 // Parse a .proto schema, output as .fbs
1163 void ParseProtoTestWithSuffix() {
1164   // load the .proto and the golden file from disk
1165   std::string protofile;
1166   std::string goldenfile;
1167   std::string goldenunionfile;
1168   TEST_EQ(
1169       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1170                             false, &protofile),
1171       true);
1172   TEST_EQ(flatbuffers::LoadFile(
1173               (test_data_path + "prototest/test_suffix.golden").c_str(), false,
1174               &goldenfile),
1175           true);
1176   TEST_EQ(flatbuffers::LoadFile(
1177               (test_data_path + "prototest/test_union_suffix.golden").c_str(),
1178               false, &goldenunionfile),
1179           true);
1180
1181   flatbuffers::IDLOptions opts;
1182   opts.include_dependence_headers = false;
1183   opts.proto_mode = true;
1184   opts.proto_namespace_suffix = "test_namespace_suffix";
1185
1186   // Parse proto.
1187   flatbuffers::Parser parser(opts);
1188   auto protopath = test_data_path + "prototest/";
1189   const char *include_directories[] = { protopath.c_str(), nullptr };
1190   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1191
1192   // Generate fbs.
1193   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1194
1195   // Ensure generated file is parsable.
1196   flatbuffers::Parser parser2;
1197   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1198   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1199
1200   // Parse proto with --oneof-union option.
1201   opts.proto_oneof_union = true;
1202   flatbuffers::Parser parser3(opts);
1203   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1204
1205   // Generate fbs.
1206   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1207
1208   // Ensure generated file is parsable.
1209   flatbuffers::Parser parser4;
1210   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1211   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1212 }
1213
1214 // Parse a .proto schema, output as .fbs
1215 void ParseProtoTestWithIncludes() {
1216   // load the .proto and the golden file from disk
1217   std::string protofile;
1218   std::string goldenfile;
1219   std::string goldenunionfile;
1220   std::string importprotofile;
1221   TEST_EQ(
1222       flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
1223                             false, &protofile),
1224       true);
1225   TEST_EQ(flatbuffers::LoadFile(
1226               (test_data_path + "prototest/imported.proto").c_str(), false,
1227               &importprotofile),
1228           true);
1229   TEST_EQ(flatbuffers::LoadFile(
1230               (test_data_path + "prototest/test_include.golden").c_str(), false,
1231               &goldenfile),
1232           true);
1233   TEST_EQ(flatbuffers::LoadFile(
1234               (test_data_path + "prototest/test_union_include.golden").c_str(),
1235               false, &goldenunionfile),
1236           true);
1237
1238   flatbuffers::IDLOptions opts;
1239   opts.include_dependence_headers = true;
1240   opts.proto_mode = true;
1241
1242   // Parse proto.
1243   flatbuffers::Parser parser(opts);
1244   auto protopath = test_data_path + "prototest/";
1245   const char *include_directories[] = { protopath.c_str(), nullptr };
1246   TEST_EQ(parser.Parse(protofile.c_str(), include_directories), true);
1247
1248   // Generate fbs.
1249   auto fbs = flatbuffers::GenerateFBS(parser, "test");
1250
1251   // Generate fbs from import.proto
1252   flatbuffers::Parser import_parser(opts);
1253   TEST_EQ(import_parser.Parse(importprotofile.c_str(), include_directories),
1254           true);
1255   auto import_fbs = flatbuffers::GenerateFBS(import_parser, "test");
1256
1257   // Ensure generated file is parsable.
1258   flatbuffers::Parser parser2;
1259   TEST_EQ(
1260       parser2.Parse(import_fbs.c_str(), include_directories, "imported.fbs"),
1261       true);
1262   TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true);
1263   TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
1264
1265   // Parse proto with --oneof-union option.
1266   opts.proto_oneof_union = true;
1267   flatbuffers::Parser parser3(opts);
1268   TEST_EQ(parser3.Parse(protofile.c_str(), include_directories), true);
1269
1270   // Generate fbs.
1271   auto fbs_union = flatbuffers::GenerateFBS(parser3, "test");
1272
1273   // Ensure generated file is parsable.
1274   flatbuffers::Parser parser4;
1275   TEST_EQ(parser4.Parse(import_fbs.c_str(), nullptr, "imported.fbs"), true);
1276   TEST_EQ(parser4.Parse(fbs_union.c_str(), nullptr), true);
1277   TEST_EQ_STR(fbs_union.c_str(), goldenunionfile.c_str());
1278 }
1279
1280 template<typename T>
1281 void CompareTableFieldValue(flatbuffers::Table *table,
1282                             flatbuffers::voffset_t voffset, T val) {
1283   T read = table->GetField(voffset, static_cast<T>(0));
1284   TEST_EQ(read, val);
1285 }
1286
1287 // Low level stress/fuzz test: serialize/deserialize a variety of
1288 // different kinds of data in different combinations
1289 void FuzzTest1() {
1290   // Values we're testing against: chosen to ensure no bits get chopped
1291   // off anywhere, and also be different from eachother.
1292   const uint8_t bool_val = true;
1293   const int8_t char_val = -127;  // 0x81
1294   const uint8_t uchar_val = 0xFF;
1295   const int16_t short_val = -32222;  // 0x8222;
1296   const uint16_t ushort_val = 0xFEEE;
1297   const int32_t int_val = 0x83333333;
1298   const uint32_t uint_val = 0xFDDDDDDD;
1299   const int64_t long_val = 0x8444444444444444LL;
1300   const uint64_t ulong_val = 0xFCCCCCCCCCCCCCCCULL;
1301   const float float_val = 3.14159f;
1302   const double double_val = 3.14159265359;
1303
1304   const int test_values_max = 11;
1305   const flatbuffers::voffset_t fields_per_object = 4;
1306   const int num_fuzz_objects = 10000;  // The higher, the more thorough :)
1307
1308   flatbuffers::FlatBufferBuilder builder;
1309
1310   lcg_reset();  // Keep it deterministic.
1311
1312   flatbuffers::uoffset_t objects[num_fuzz_objects];
1313
1314   // Generate num_fuzz_objects random objects each consisting of
1315   // fields_per_object fields, each of a random type.
1316   for (int i = 0; i < num_fuzz_objects; i++) {
1317     auto start = builder.StartTable();
1318     for (flatbuffers::voffset_t f = 0; f < fields_per_object; f++) {
1319       int choice = lcg_rand() % test_values_max;
1320       auto off = flatbuffers::FieldIndexToOffset(f);
1321       switch (choice) {
1322         case 0: builder.AddElement<uint8_t>(off, bool_val, 0); break;
1323         case 1: builder.AddElement<int8_t>(off, char_val, 0); break;
1324         case 2: builder.AddElement<uint8_t>(off, uchar_val, 0); break;
1325         case 3: builder.AddElement<int16_t>(off, short_val, 0); break;
1326         case 4: builder.AddElement<uint16_t>(off, ushort_val, 0); break;
1327         case 5: builder.AddElement<int32_t>(off, int_val, 0); break;
1328         case 6: builder.AddElement<uint32_t>(off, uint_val, 0); break;
1329         case 7: builder.AddElement<int64_t>(off, long_val, 0); break;
1330         case 8: builder.AddElement<uint64_t>(off, ulong_val, 0); break;
1331         case 9: builder.AddElement<float>(off, float_val, 0); break;
1332         case 10: builder.AddElement<double>(off, double_val, 0); break;
1333       }
1334     }
1335     objects[i] = builder.EndTable(start);
1336   }
1337   builder.PreAlign<flatbuffers::largest_scalar_t>(0);  // Align whole buffer.
1338
1339   lcg_reset();  // Reset.
1340
1341   uint8_t *eob = builder.GetCurrentBufferPointer() + builder.GetSize();
1342
1343   // Test that all objects we generated are readable and return the
1344   // expected values. We generate random objects in the same order
1345   // so this is deterministic.
1346   for (int i = 0; i < num_fuzz_objects; i++) {
1347     auto table = reinterpret_cast<flatbuffers::Table *>(eob - objects[i]);
1348     for (flatbuffers::voffset_t f = 0; f < fields_per_object; f++) {
1349       int choice = lcg_rand() % test_values_max;
1350       flatbuffers::voffset_t off = flatbuffers::FieldIndexToOffset(f);
1351       switch (choice) {
1352         case 0: CompareTableFieldValue(table, off, bool_val); break;
1353         case 1: CompareTableFieldValue(table, off, char_val); break;
1354         case 2: CompareTableFieldValue(table, off, uchar_val); break;
1355         case 3: CompareTableFieldValue(table, off, short_val); break;
1356         case 4: CompareTableFieldValue(table, off, ushort_val); break;
1357         case 5: CompareTableFieldValue(table, off, int_val); break;
1358         case 6: CompareTableFieldValue(table, off, uint_val); break;
1359         case 7: CompareTableFieldValue(table, off, long_val); break;
1360         case 8: CompareTableFieldValue(table, off, ulong_val); break;
1361         case 9: CompareTableFieldValue(table, off, float_val); break;
1362         case 10: CompareTableFieldValue(table, off, double_val); break;
1363       }
1364     }
1365   }
1366 }
1367
1368 // High level stress/fuzz test: generate a big schema and
1369 // matching json data in random combinations, then parse both,
1370 // generate json back from the binary, and compare with the original.
1371 void FuzzTest2() {
1372   lcg_reset();  // Keep it deterministic.
1373
1374   const int num_definitions = 30;
1375   const int num_struct_definitions = 5;  // Subset of num_definitions.
1376   const int fields_per_definition = 15;
1377   const int instances_per_definition = 5;
1378   const int deprecation_rate = 10;  // 1 in deprecation_rate fields will
1379                                     // be deprecated.
1380
1381   std::string schema = "namespace test;\n\n";
1382
1383   struct RndDef {
1384     std::string instances[instances_per_definition];
1385
1386     // Since we're generating schema and corresponding data in tandem,
1387     // this convenience function adds strings to both at once.
1388     static void Add(RndDef (&definitions_l)[num_definitions],
1389                     std::string &schema_l, const int instances_per_definition_l,
1390                     const char *schema_add, const char *instance_add,
1391                     int definition) {
1392       schema_l += schema_add;
1393       for (int i = 0; i < instances_per_definition_l; i++)
1394         definitions_l[definition].instances[i] += instance_add;
1395     }
1396   };
1397
1398   // clang-format off
1399   #define AddToSchemaAndInstances(schema_add, instance_add) \
1400     RndDef::Add(definitions, schema, instances_per_definition, \
1401                 schema_add, instance_add, definition)
1402
1403   #define Dummy() \
1404     RndDef::Add(definitions, schema, instances_per_definition, \
1405                 "byte", "1", definition)
1406   // clang-format on
1407
1408   RndDef definitions[num_definitions];
1409
1410   // We are going to generate num_definitions, the first
1411   // num_struct_definitions will be structs, the rest tables. For each
1412   // generate random fields, some of which may be struct/table types
1413   // referring to previously generated structs/tables.
1414   // Simultanenously, we generate instances_per_definition JSON data
1415   // definitions, which will have identical structure to the schema
1416   // being generated. We generate multiple instances such that when creating
1417   // hierarchy, we get some variety by picking one randomly.
1418   for (int definition = 0; definition < num_definitions; definition++) {
1419     std::string definition_name = "D" + flatbuffers::NumToString(definition);
1420
1421     bool is_struct = definition < num_struct_definitions;
1422
1423     AddToSchemaAndInstances(
1424         ((is_struct ? "struct " : "table ") + definition_name + " {\n").c_str(),
1425         "{\n");
1426
1427     for (int field = 0; field < fields_per_definition; field++) {
1428       const bool is_last_field = field == fields_per_definition - 1;
1429
1430       // Deprecate 1 in deprecation_rate fields. Only table fields can be
1431       // deprecated.
1432       // Don't deprecate the last field to avoid dangling commas in JSON.
1433       const bool deprecated =
1434           !is_struct && !is_last_field && (lcg_rand() % deprecation_rate == 0);
1435
1436       std::string field_name = "f" + flatbuffers::NumToString(field);
1437       AddToSchemaAndInstances(("  " + field_name + ":").c_str(),
1438                               deprecated ? "" : (field_name + ": ").c_str());
1439       // Pick random type:
1440       auto base_type = static_cast<flatbuffers::BaseType>(
1441           lcg_rand() % (flatbuffers::BASE_TYPE_UNION + 1));
1442       switch (base_type) {
1443         case flatbuffers::BASE_TYPE_STRING:
1444           if (is_struct) {
1445             Dummy();  // No strings in structs.
1446           } else {
1447             AddToSchemaAndInstances("string", deprecated ? "" : "\"hi\"");
1448           }
1449           break;
1450         case flatbuffers::BASE_TYPE_VECTOR:
1451           if (is_struct) {
1452             Dummy();  // No vectors in structs.
1453           } else {
1454             AddToSchemaAndInstances("[ubyte]",
1455                                     deprecated ? "" : "[\n0,\n1,\n255\n]");
1456           }
1457           break;
1458         case flatbuffers::BASE_TYPE_NONE:
1459         case flatbuffers::BASE_TYPE_UTYPE:
1460         case flatbuffers::BASE_TYPE_STRUCT:
1461         case flatbuffers::BASE_TYPE_UNION:
1462           if (definition) {
1463             // Pick a random previous definition and random data instance of
1464             // that definition.
1465             int defref = lcg_rand() % definition;
1466             int instance = lcg_rand() % instances_per_definition;
1467             AddToSchemaAndInstances(
1468                 ("D" + flatbuffers::NumToString(defref)).c_str(),
1469                 deprecated ? ""
1470                            : definitions[defref].instances[instance].c_str());
1471           } else {
1472             // If this is the first definition, we have no definition we can
1473             // refer to.
1474             Dummy();
1475           }
1476           break;
1477         case flatbuffers::BASE_TYPE_BOOL:
1478           AddToSchemaAndInstances(
1479               "bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
1480           break;
1481         case flatbuffers::BASE_TYPE_ARRAY:
1482           if (!is_struct) {
1483             AddToSchemaAndInstances(
1484                 "ubyte",
1485                 deprecated ? "" : "255");  // No fixed-length arrays in tables.
1486           } else {
1487             AddToSchemaAndInstances("[int:3]", deprecated ? "" : "[\n,\n,\n]");
1488           }
1489           break;
1490         default:
1491           // All the scalar types.
1492           schema += flatbuffers::kTypeNames[base_type];
1493
1494           if (!deprecated) {
1495             // We want each instance to use its own random value.
1496             for (int inst = 0; inst < instances_per_definition; inst++)
1497               definitions[definition].instances[inst] +=
1498                   flatbuffers::IsFloat(base_type)
1499                       ? flatbuffers::NumToString<double>(lcg_rand() % 128)
1500                             .c_str()
1501                       : flatbuffers::NumToString<int>(lcg_rand() % 128).c_str();
1502           }
1503       }
1504       AddToSchemaAndInstances(deprecated ? "(deprecated);\n" : ";\n",
1505                               deprecated ? "" : is_last_field ? "\n" : ",\n");
1506     }
1507     AddToSchemaAndInstances("}\n\n", "}");
1508   }
1509
1510   schema += "root_type D" + flatbuffers::NumToString(num_definitions - 1);
1511   schema += ";\n";
1512
1513   flatbuffers::Parser parser;
1514
1515   // Will not compare against the original if we don't write defaults
1516   parser.builder_.ForceDefaults(true);
1517
1518   // Parse the schema, parse the generated data, then generate text back
1519   // from the binary and compare against the original.
1520   TEST_EQ(parser.Parse(schema.c_str()), true);
1521
1522   const std::string &json =
1523       definitions[num_definitions - 1].instances[0] + "\n";
1524
1525   TEST_EQ(parser.Parse(json.c_str()), true);
1526
1527   std::string jsongen;
1528   parser.opts.indent_step = 0;
1529   auto result =
1530       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
1531   TEST_EQ(result, true);
1532
1533   if (jsongen != json) {
1534     // These strings are larger than a megabyte, so we show the bytes around
1535     // the first bytes that are different rather than the whole string.
1536     size_t len = std::min(json.length(), jsongen.length());
1537     for (size_t i = 0; i < len; i++) {
1538       if (json[i] != jsongen[i]) {
1539         i -= std::min(static_cast<size_t>(10), i);  // show some context;
1540         size_t end = std::min(len, i + 20);
1541         for (; i < end; i++)
1542           TEST_OUTPUT_LINE("at %d: found \"%c\", expected \"%c\"\n",
1543                            static_cast<int>(i), jsongen[i], json[i]);
1544         break;
1545       }
1546     }
1547     TEST_NOTNULL(nullptr);  //-V501 (this comment supresses CWE-570 warning)
1548   }
1549
1550   // clang-format off
1551   #ifdef FLATBUFFERS_TEST_VERBOSE
1552     TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n",
1553                      static_cast<int>(schema.length() / 1024),
1554                      static_cast<int>(json.length() / 1024));
1555   #endif
1556   // clang-format on
1557 }
1558
1559 // Test that parser errors are actually generated.
1560 void TestError_(const char *src, const char *error_substr, bool strict_json,
1561                 const char *file, int line, const char *func) {
1562   flatbuffers::IDLOptions opts;
1563   opts.strict_json = strict_json;
1564   flatbuffers::Parser parser(opts);
1565   if (parser.Parse(src)) {
1566     TestFail("true", "false",
1567              ("parser.Parse(\"" + std::string(src) + "\")").c_str(), file, line,
1568              func);
1569   } else if (!strstr(parser.error_.c_str(), error_substr)) {
1570     TestFail(error_substr, parser.error_.c_str(),
1571              ("parser.Parse(\"" + std::string(src) + "\")").c_str(), file, line,
1572              func);
1573   }
1574 }
1575
1576 void TestError_(const char *src, const char *error_substr, const char *file,
1577                 int line, const char *func) {
1578   TestError_(src, error_substr, false, file, line, func);
1579 }
1580
1581 #ifdef _WIN32
1582 #  define TestError(src, ...) \
1583     TestError_(src, __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__)
1584 #else
1585 #  define TestError(src, ...) \
1586     TestError_(src, __VA_ARGS__, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1587 #endif
1588
1589 // Test that parsing errors occur as we'd expect.
1590 // Also useful for coverage, making sure these paths are run.
1591 void ErrorTest() {
1592   // In order they appear in idl_parser.cpp
1593   TestError("table X { Y:byte; } root_type X; { Y: 999 }", "does not fit");
1594   TestError("\"\0", "illegal");
1595   TestError("\"\\q", "escape code");
1596   TestError("table ///", "documentation");
1597   TestError("@", "illegal");
1598   TestError("table 1", "expecting");
1599   TestError("table X { Y:[[int]]; }", "nested vector");
1600   TestError("table X { Y:1; }", "illegal type");
1601   TestError("table X { Y:int; Y:int; }", "field already");
1602   TestError("table Y {} table X { Y:int; }", "same as table");
1603   TestError("struct X { Y:string; }", "only scalar");
1604   TestError("table X { Y:string = \"\"; }", "default values");
1605   TestError("struct X { a:uint = 42; }", "default values");
1606   TestError("enum Y:byte { Z = 1 } table X { y:Y; }", "not part of enum");
1607   TestError("struct X { Y:int (deprecated); }", "deprecate");
1608   TestError("union Z { X } table X { Y:Z; } root_type X; { Y: {}, A:1 }",
1609             "missing type field");
1610   TestError("union Z { X } table X { Y:Z; } root_type X; { Y_type: 99, Y: {",
1611             "type id");
1612   TestError("table X { Y:int; } root_type X; { Z:", "unknown field");
1613   TestError("table X { Y:int; } root_type X; { Y:", "string constant", true);
1614   TestError("table X { Y:int; } root_type X; { \"Y\":1, }", "string constant",
1615             true);
1616   TestError(
1617       "struct X { Y:int; Z:int; } table W { V:X; } root_type W; "
1618       "{ V:{ Y:1 } }",
1619       "wrong number");
1620   TestError("enum E:byte { A } table X { Y:E; } root_type X; { Y:U }",
1621             "unknown enum value");
1622   TestError("table X { Y:byte; } root_type X; { Y:; }", "starting");
1623   TestError("enum X:byte { Y } enum X {", "enum already");
1624   TestError("enum X:float {}", "underlying");
1625   TestError("enum X:byte { Y, Y }", "value already");
1626   TestError("enum X:byte { Y=2, Z=2 }", "unique");
1627   TestError("table X { Y:int; } table X {", "datatype already");
1628   TestError("struct X (force_align: 7) { Y:int; }", "force_align");
1629   TestError("struct X {}", "size 0");
1630   TestError("{}", "no root");
1631   TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file");
1632   TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",
1633             "end of file");
1634   TestError("root_type X;", "unknown root");
1635   TestError("struct X { Y:int; } root_type X;", "a table");
1636   TestError("union X { Y }", "referenced");
1637   TestError("union Z { X } struct X { Y:int; }", "only tables");
1638   TestError("table X { Y:[int]; YLength:int; }", "clash");
1639   TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once");
1640   // float to integer conversion is forbidden
1641   TestError("table X { Y:int; } root_type X; { Y:1.0 }", "float");
1642   TestError("table X { Y:bool; } root_type X; { Y:1.0 }", "float");
1643   TestError("enum X:bool { Y = true }", "must be integral");
1644   // Array of non-scalar
1645   TestError("table X { x:int; } struct Y { y:[X:2]; }",
1646             "may contain only scalar or struct fields");
1647   // Non-snake case field names
1648   TestError("table X { Y: int; } root_type Y: {Y:1.0}", "snake_case");
1649 }
1650
1651 template<typename T>
1652 T TestValue(const char *json, const char *type_name,
1653             const char *decls = nullptr) {
1654   flatbuffers::Parser parser;
1655   parser.builder_.ForceDefaults(true);  // return defaults
1656   auto check_default = json ? false : true;
1657   if (check_default) { parser.opts.output_default_scalars_in_json = true; }
1658   // Simple schema.
1659   std::string schema = std::string(decls ? decls : "") + "\n" +
1660                        "table X { y:" + std::string(type_name) +
1661                        "; } root_type X;";
1662   auto schema_done = parser.Parse(schema.c_str());
1663   TEST_EQ_STR(parser.error_.c_str(), "");
1664   TEST_EQ(schema_done, true);
1665
1666   auto done = parser.Parse(check_default ? "{}" : json);
1667   TEST_EQ_STR(parser.error_.c_str(), "");
1668   TEST_EQ(done, true);
1669
1670   // Check with print.
1671   std::string print_back;
1672   parser.opts.indent_step = -1;
1673   TEST_EQ(GenerateText(parser, parser.builder_.GetBufferPointer(), &print_back),
1674           true);
1675   // restore value from its default
1676   if (check_default) { TEST_EQ(parser.Parse(print_back.c_str()), true); }
1677
1678   auto root = flatbuffers::GetRoot<flatbuffers::Table>(
1679       parser.builder_.GetBufferPointer());
1680   return root->GetField<T>(flatbuffers::FieldIndexToOffset(0), 0);
1681 }
1682
1683 bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; }
1684
1685 // Additional parser testing not covered elsewhere.
1686 void ValueTest() {
1687   // Test scientific notation numbers.
1688   TEST_EQ(
1689       FloatCompare(TestValue<float>("{ y:0.0314159e+2 }", "float"), 3.14159f),
1690       true);
1691   // number in string
1692   TEST_EQ(FloatCompare(TestValue<float>("{ y:\"0.0314159e+2\" }", "float"),
1693                        3.14159f),
1694           true);
1695
1696   // Test conversion functions.
1697   TEST_EQ(FloatCompare(TestValue<float>("{ y:cos(rad(180)) }", "float"), -1),
1698           true);
1699
1700   // int embedded to string
1701   TEST_EQ(TestValue<int>("{ y:\"-876\" }", "int=-123"), -876);
1702   TEST_EQ(TestValue<int>("{ y:\"876\" }", "int=-123"), 876);
1703
1704   // Test negative hex constant.
1705   TEST_EQ(TestValue<int>("{ y:-0x8ea0 }", "int=-0x8ea0"), -36512);
1706   TEST_EQ(TestValue<int>(nullptr, "int=-0x8ea0"), -36512);
1707
1708   // positive hex constant
1709   TEST_EQ(TestValue<int>("{ y:0x1abcdef }", "int=0x1"), 0x1abcdef);
1710   // with optional '+' sign
1711   TEST_EQ(TestValue<int>("{ y:+0x1abcdef }", "int=+0x1"), 0x1abcdef);
1712   // hex in string
1713   TEST_EQ(TestValue<int>("{ y:\"0x1abcdef\" }", "int=+0x1"), 0x1abcdef);
1714
1715   // Make sure we do unsigned 64bit correctly.
1716   TEST_EQ(TestValue<uint64_t>("{ y:12335089644688340133 }", "ulong"),
1717           12335089644688340133ULL);
1718
1719   // bool in string
1720   TEST_EQ(TestValue<bool>("{ y:\"false\" }", "bool=true"), false);
1721   TEST_EQ(TestValue<bool>("{ y:\"true\" }", "bool=\"true\""), true);
1722   TEST_EQ(TestValue<bool>("{ y:'false' }", "bool=true"), false);
1723   TEST_EQ(TestValue<bool>("{ y:'true' }", "bool=\"true\""), true);
1724
1725   // check comments before and after json object
1726   TEST_EQ(TestValue<int>("/*before*/ { y:1 } /*after*/", "int"), 1);
1727   TEST_EQ(TestValue<int>("//before \n { y:1 } //after", "int"), 1);
1728 }
1729
1730 void NestedListTest() {
1731   flatbuffers::Parser parser1;
1732   TEST_EQ(parser1.Parse("struct Test { a:short; b:byte; } table T { F:[Test]; }"
1733                         "root_type T;"
1734                         "{ F:[ [10,20], [30,40]] }"),
1735           true);
1736 }
1737
1738 void EnumStringsTest() {
1739   flatbuffers::Parser parser1;
1740   TEST_EQ(parser1.Parse("enum E:byte { A, B, C } table T { F:[E]; }"
1741                         "root_type T;"
1742                         "{ F:[ A, B, \"C\", \"A B C\" ] }"),
1743           true);
1744   flatbuffers::Parser parser2;
1745   TEST_EQ(parser2.Parse("enum E:byte { A, B, C } table T { F:[int]; }"
1746                         "root_type T;"
1747                         "{ F:[ \"E.C\", \"E.A E.B E.C\" ] }"),
1748           true);
1749   // unsigned bit_flags
1750   flatbuffers::Parser parser3;
1751   TEST_EQ(
1752       parser3.Parse("enum E:uint16 (bit_flags) { F0, F07=7, F08, F14=14, F15 }"
1753                     " table T { F: E = \"F15 F08\"; }"
1754                     "root_type T;"),
1755       true);
1756 }
1757
1758 void EnumNamesTest() {
1759   TEST_EQ_STR("Red", EnumNameColor(Color_Red));
1760   TEST_EQ_STR("Green", EnumNameColor(Color_Green));
1761   TEST_EQ_STR("Blue", EnumNameColor(Color_Blue));
1762   // Check that Color to string don't crash while decode a mixture of Colors.
1763   // 1) Example::Color enum is enum with unfixed underlying type.
1764   // 2) Valid enum range: [0; 2^(ceil(log2(Color_ANY))) - 1].
1765   // Consequence: A value is out of this range will lead to UB (since C++17).
1766   // For details see C++17 standard or explanation on the SO:
1767   // stackoverflow.com/questions/18195312/what-happens-if-you-static-cast-invalid-value-to-enum-class
1768   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(0)));
1769   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY - 1)));
1770   TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY + 1)));
1771 }
1772
1773 void EnumOutOfRangeTest() {
1774   TestError("enum X:byte { Y = 128 }", "enum value does not fit");
1775   TestError("enum X:byte { Y = -129 }", "enum value does not fit");
1776   TestError("enum X:byte { Y = 126, Z0, Z1 }", "enum value does not fit");
1777   TestError("enum X:ubyte { Y = -1 }", "enum value does not fit");
1778   TestError("enum X:ubyte { Y = 256 }", "enum value does not fit");
1779   TestError("enum X:ubyte { Y = 255, Z }", "enum value does not fit");
1780   TestError("table Y{} union X { Y = -1 }", "enum value does not fit");
1781   TestError("table Y{} union X { Y = 256 }", "enum value does not fit");
1782   TestError("table Y{} union X { Y = 255, Z:Y }", "enum value does not fit");
1783   TestError("enum X:int { Y = -2147483649 }", "enum value does not fit");
1784   TestError("enum X:int { Y = 2147483648 }", "enum value does not fit");
1785   TestError("enum X:uint { Y = -1 }", "enum value does not fit");
1786   TestError("enum X:uint { Y = 4294967297 }", "enum value does not fit");
1787   TestError("enum X:long { Y = 9223372036854775808 }", "does not fit");
1788   TestError("enum X:long { Y = 9223372036854775807, Z }",
1789             "enum value does not fit");
1790   TestError("enum X:ulong { Y = -1 }", "does not fit");
1791   TestError("enum X:ubyte (bit_flags) { Y=8 }", "bit flag out");
1792   TestError("enum X:byte (bit_flags) { Y=7 }", "must be unsigned");  // -128
1793   // bit_flgs out of range
1794   TestError("enum X:ubyte (bit_flags) { Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8 }",
1795             "out of range");
1796 }
1797
1798 void EnumValueTest() {
1799   // json: "{ Y:0 }", schema: table X { y: "E"}
1800   // 0 in enum (V=0) E then Y=0 is valid.
1801   TEST_EQ(TestValue<int>("{ y:0 }", "E", "enum E:int { V }"), 0);
1802   TEST_EQ(TestValue<int>("{ y:V }", "E", "enum E:int { V }"), 0);
1803   // A default value of Y is 0.
1804   TEST_EQ(TestValue<int>("{ }", "E", "enum E:int { V }"), 0);
1805   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { V=5 }"), 5);
1806   // Generate json with defaults and check.
1807   TEST_EQ(TestValue<int>(nullptr, "E=V", "enum E:int { V=5 }"), 5);
1808   // 5 in enum
1809   TEST_EQ(TestValue<int>("{ y:5 }", "E", "enum E:int { Z, V=5 }"), 5);
1810   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { Z, V=5 }"), 5);
1811   // Generate json with defaults and check.
1812   TEST_EQ(TestValue<int>(nullptr, "E", "enum E:int { Z, V=5 }"), 0);
1813   TEST_EQ(TestValue<int>(nullptr, "E=V", "enum E:int { Z, V=5 }"), 5);
1814   // u84 test
1815   TEST_EQ(TestValue<uint64_t>(nullptr, "E=V",
1816                               "enum E:ulong { V = 13835058055282163712 }"),
1817           13835058055282163712ULL);
1818   TEST_EQ(TestValue<uint64_t>(nullptr, "E=V",
1819                               "enum E:ulong { V = 18446744073709551615 }"),
1820           18446744073709551615ULL);
1821   // Assign non-enum value to enum field. Is it right?
1822   TEST_EQ(TestValue<int>("{ y:7 }", "E", "enum E:int { V = 0 }"), 7);
1823   // Check that non-ascending values are valid.
1824   TEST_EQ(TestValue<int>("{ y:5 }", "E=V", "enum E:int { Z=10, V=5 }"), 5);
1825 }
1826
1827 void IntegerOutOfRangeTest() {
1828   TestError("table T { F:byte; } root_type T; { F:128 }",
1829             "constant does not fit");
1830   TestError("table T { F:byte; } root_type T; { F:-129 }",
1831             "constant does not fit");
1832   TestError("table T { F:ubyte; } root_type T; { F:256 }",
1833             "constant does not fit");
1834   TestError("table T { F:ubyte; } root_type T; { F:-1 }",
1835             "constant does not fit");
1836   TestError("table T { F:short; } root_type T; { F:32768 }",
1837             "constant does not fit");
1838   TestError("table T { F:short; } root_type T; { F:-32769 }",
1839             "constant does not fit");
1840   TestError("table T { F:ushort; } root_type T; { F:65536 }",
1841             "constant does not fit");
1842   TestError("table T { F:ushort; } root_type T; { F:-1 }",
1843             "constant does not fit");
1844   TestError("table T { F:int; } root_type T; { F:2147483648 }",
1845             "constant does not fit");
1846   TestError("table T { F:int; } root_type T; { F:-2147483649 }",
1847             "constant does not fit");
1848   TestError("table T { F:uint; } root_type T; { F:4294967296 }",
1849             "constant does not fit");
1850   TestError("table T { F:uint; } root_type T; { F:-1 }",
1851             "constant does not fit");
1852   // Check fixed width aliases
1853   TestError("table X { Y:uint8; } root_type X; { Y: -1 }", "does not fit");
1854   TestError("table X { Y:uint8; } root_type X; { Y: 256 }", "does not fit");
1855   TestError("table X { Y:uint16; } root_type X; { Y: -1 }", "does not fit");
1856   TestError("table X { Y:uint16; } root_type X; { Y: 65536 }", "does not fit");
1857   TestError("table X { Y:uint32; } root_type X; { Y: -1 }", "");
1858   TestError("table X { Y:uint32; } root_type X; { Y: 4294967296 }",
1859             "does not fit");
1860   TestError("table X { Y:uint64; } root_type X; { Y: -1 }", "");
1861   TestError("table X { Y:uint64; } root_type X; { Y: -9223372036854775809 }",
1862             "does not fit");
1863   TestError("table X { Y:uint64; } root_type X; { Y: 18446744073709551616 }",
1864             "does not fit");
1865
1866   TestError("table X { Y:int8; } root_type X; { Y: -129 }", "does not fit");
1867   TestError("table X { Y:int8; } root_type X; { Y: 128 }", "does not fit");
1868   TestError("table X { Y:int16; } root_type X; { Y: -32769 }", "does not fit");
1869   TestError("table X { Y:int16; } root_type X; { Y: 32768 }", "does not fit");
1870   TestError("table X { Y:int32; } root_type X; { Y: -2147483649 }", "");
1871   TestError("table X { Y:int32; } root_type X; { Y: 2147483648 }",
1872             "does not fit");
1873   TestError("table X { Y:int64; } root_type X; { Y: -9223372036854775809 }",
1874             "does not fit");
1875   TestError("table X { Y:int64; } root_type X; { Y: 9223372036854775808 }",
1876             "does not fit");
1877   // check out-of-int64 as int8
1878   TestError("table X { Y:int8; } root_type X; { Y: -9223372036854775809 }",
1879             "does not fit");
1880   TestError("table X { Y:int8; } root_type X; { Y: 9223372036854775808 }",
1881             "does not fit");
1882
1883   // Check default values
1884   TestError("table X { Y:int64=-9223372036854775809; } root_type X; {}",
1885             "does not fit");
1886   TestError("table X { Y:int64= 9223372036854775808; } root_type X; {}",
1887             "does not fit");
1888   TestError("table X { Y:uint64; } root_type X; { Y: -1 }", "");
1889   TestError("table X { Y:uint64=-9223372036854775809; } root_type X; {}",
1890             "does not fit");
1891   TestError("table X { Y:uint64= 18446744073709551616; } root_type X; {}",
1892             "does not fit");
1893 }
1894
1895 void IntegerBoundaryTest() {
1896   // Check numerical compatibility with non-C++ languages.
1897   // By the C++ standard, std::numerical_limits<int64_t>::min() ==
1898   // -9223372036854775807 (-2^63+1) or less* The Flatbuffers grammar and most of
1899   // the languages (C#, Java, Rust) expect that minimum values are: -128,
1900   // -32768,.., -9223372036854775808. Since C++20,
1901   // static_cast<int64>(0x8000000000000000ULL) is well-defined two's complement
1902   // cast. Therefore -9223372036854775808 should be valid negative value.
1903   TEST_EQ(flatbuffers::numeric_limits<int8_t>::min(), -128);
1904   TEST_EQ(flatbuffers::numeric_limits<int8_t>::max(), 127);
1905   TEST_EQ(flatbuffers::numeric_limits<int16_t>::min(), -32768);
1906   TEST_EQ(flatbuffers::numeric_limits<int16_t>::max(), 32767);
1907   TEST_EQ(flatbuffers::numeric_limits<int32_t>::min() + 1, -2147483647);
1908   TEST_EQ(flatbuffers::numeric_limits<int32_t>::max(), 2147483647ULL);
1909   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min() + 1LL,
1910           -9223372036854775807LL);
1911   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(), 9223372036854775807ULL);
1912   TEST_EQ(flatbuffers::numeric_limits<uint8_t>::max(), 255);
1913   TEST_EQ(flatbuffers::numeric_limits<uint16_t>::max(), 65535);
1914   TEST_EQ(flatbuffers::numeric_limits<uint32_t>::max(), 4294967295ULL);
1915   TEST_EQ(flatbuffers::numeric_limits<uint64_t>::max(),
1916           18446744073709551615ULL);
1917
1918   TEST_EQ(TestValue<int8_t>("{ y:127 }", "byte"), 127);
1919   TEST_EQ(TestValue<int8_t>("{ y:-128 }", "byte"), -128);
1920   TEST_EQ(TestValue<uint8_t>("{ y:255 }", "ubyte"), 255);
1921   TEST_EQ(TestValue<uint8_t>("{ y:0 }", "ubyte"), 0);
1922   TEST_EQ(TestValue<int16_t>("{ y:32767 }", "short"), 32767);
1923   TEST_EQ(TestValue<int16_t>("{ y:-32768 }", "short"), -32768);
1924   TEST_EQ(TestValue<uint16_t>("{ y:65535 }", "ushort"), 65535);
1925   TEST_EQ(TestValue<uint16_t>("{ y:0 }", "ushort"), 0);
1926   TEST_EQ(TestValue<int32_t>("{ y:2147483647 }", "int"), 2147483647);
1927   TEST_EQ(TestValue<int32_t>("{ y:-2147483648 }", "int") + 1, -2147483647);
1928   TEST_EQ(TestValue<uint32_t>("{ y:4294967295 }", "uint"), 4294967295);
1929   TEST_EQ(TestValue<uint32_t>("{ y:0 }", "uint"), 0);
1930   TEST_EQ(TestValue<int64_t>("{ y:9223372036854775807 }", "long"),
1931           9223372036854775807LL);
1932   TEST_EQ(TestValue<int64_t>("{ y:-9223372036854775808 }", "long") + 1LL,
1933           -9223372036854775807LL);
1934   TEST_EQ(TestValue<uint64_t>("{ y:18446744073709551615 }", "ulong"),
1935           18446744073709551615ULL);
1936   TEST_EQ(TestValue<uint64_t>("{ y:0 }", "ulong"), 0);
1937   TEST_EQ(TestValue<uint64_t>("{ y: 18446744073709551615 }", "uint64"),
1938           18446744073709551615ULL);
1939   // check that the default works
1940   TEST_EQ(TestValue<uint64_t>(nullptr, "uint64 = 18446744073709551615"),
1941           18446744073709551615ULL);
1942 }
1943
1944 void ValidFloatTest() {
1945   // check rounding to infinity
1946   TEST_EQ(TestValue<float>("{ y:+3.4029e+38 }", "float"), +infinityf);
1947   TEST_EQ(TestValue<float>("{ y:-3.4029e+38 }", "float"), -infinityf);
1948   TEST_EQ(TestValue<double>("{ y:+1.7977e+308 }", "double"), +infinityd);
1949   TEST_EQ(TestValue<double>("{ y:-1.7977e+308 }", "double"), -infinityd);
1950
1951   TEST_EQ(
1952       FloatCompare(TestValue<float>("{ y:0.0314159e+2 }", "float"), 3.14159f),
1953       true);
1954   // float in string
1955   TEST_EQ(FloatCompare(TestValue<float>("{ y:\" 0.0314159e+2  \" }", "float"),
1956                        3.14159f),
1957           true);
1958
1959   TEST_EQ(TestValue<float>("{ y:1 }", "float"), 1.0f);
1960   TEST_EQ(TestValue<float>("{ y:1.0 }", "float"), 1.0f);
1961   TEST_EQ(TestValue<float>("{ y:1. }", "float"), 1.0f);
1962   TEST_EQ(TestValue<float>("{ y:+1. }", "float"), 1.0f);
1963   TEST_EQ(TestValue<float>("{ y:-1. }", "float"), -1.0f);
1964   TEST_EQ(TestValue<float>("{ y:1.e0 }", "float"), 1.0f);
1965   TEST_EQ(TestValue<float>("{ y:1.e+0 }", "float"), 1.0f);
1966   TEST_EQ(TestValue<float>("{ y:1.e-0 }", "float"), 1.0f);
1967   TEST_EQ(TestValue<float>("{ y:0.125 }", "float"), 0.125f);
1968   TEST_EQ(TestValue<float>("{ y:.125 }", "float"), 0.125f);
1969   TEST_EQ(TestValue<float>("{ y:-.125 }", "float"), -0.125f);
1970   TEST_EQ(TestValue<float>("{ y:+.125 }", "float"), +0.125f);
1971   TEST_EQ(TestValue<float>("{ y:5 }", "float"), 5.0f);
1972   TEST_EQ(TestValue<float>("{ y:\"5\" }", "float"), 5.0f);
1973
1974 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
1975   // Old MSVC versions may have problem with this check.
1976   // https://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/
1977   TEST_EQ(TestValue<double>("{ y:6.9294956446009195e15 }", "double"),
1978           6929495644600920.0);
1979   // check nan's
1980   TEST_EQ(std::isnan(TestValue<double>("{ y:nan }", "double")), true);
1981   TEST_EQ(std::isnan(TestValue<float>("{ y:nan }", "float")), true);
1982   TEST_EQ(std::isnan(TestValue<float>("{ y:\"nan\" }", "float")), true);
1983   TEST_EQ(std::isnan(TestValue<float>("{ y:+nan }", "float")), true);
1984   TEST_EQ(std::isnan(TestValue<float>("{ y:-nan }", "float")), true);
1985   TEST_EQ(std::isnan(TestValue<float>(nullptr, "float=nan")), true);
1986   TEST_EQ(std::isnan(TestValue<float>(nullptr, "float=-nan")), true);
1987   // check inf
1988   TEST_EQ(TestValue<float>("{ y:inf }", "float"), infinityf);
1989   TEST_EQ(TestValue<float>("{ y:\"inf\" }", "float"), infinityf);
1990   TEST_EQ(TestValue<float>("{ y:+inf }", "float"), infinityf);
1991   TEST_EQ(TestValue<float>("{ y:-inf }", "float"), -infinityf);
1992   TEST_EQ(TestValue<float>(nullptr, "float=inf"), infinityf);
1993   TEST_EQ(TestValue<float>(nullptr, "float=-inf"), -infinityf);
1994   TestValue<double>(
1995       "{ y: [0.2, .2, 1.0, -1.0, -2., 2., 1e0, -1e0, 1.0e0, -1.0e0, -3.e2, "
1996       "3.0e2] }",
1997       "[double]");
1998   TestValue<float>(
1999       "{ y: [0.2, .2, 1.0, -1.0, -2., 2., 1e0, -1e0, 1.0e0, -1.0e0, -3.e2, "
2000       "3.0e2] }",
2001       "[float]");
2002
2003   // Test binary format of float point.
2004   // https://en.cppreference.com/w/cpp/language/floating_literal
2005   // 0x11.12p-1 = (1*16^1 + 2*16^0 + 3*16^-1 + 4*16^-2) * 2^-1 =
2006   TEST_EQ(TestValue<double>("{ y:0x12.34p-1 }", "double"), 9.1015625);
2007   // hex fraction 1.2 (decimal 1.125) scaled by 2^3, that is 9.0
2008   TEST_EQ(TestValue<float>("{ y:-0x0.2p0 }", "float"), -0.125f);
2009   TEST_EQ(TestValue<float>("{ y:-0x.2p1 }", "float"), -0.25f);
2010   TEST_EQ(TestValue<float>("{ y:0x1.2p3 }", "float"), 9.0f);
2011   TEST_EQ(TestValue<float>("{ y:0x10.1p0 }", "float"), 16.0625f);
2012   TEST_EQ(TestValue<double>("{ y:0x1.2p3 }", "double"), 9.0);
2013   TEST_EQ(TestValue<double>("{ y:0x10.1p0 }", "double"), 16.0625);
2014   TEST_EQ(TestValue<double>("{ y:0xC.68p+2 }", "double"), 49.625);
2015   TestValue<double>("{ y: [0x20.4ep1, +0x20.4ep1, -0x20.4ep1] }", "[double]");
2016   TestValue<float>("{ y: [0x20.4ep1, +0x20.4ep1, -0x20.4ep1] }", "[float]");
2017
2018 #else   // FLATBUFFERS_HAS_NEW_STRTOD
2019   TEST_OUTPUT_LINE("FLATBUFFERS_HAS_NEW_STRTOD tests skipped");
2020 #endif  // !FLATBUFFERS_HAS_NEW_STRTOD
2021 }
2022
2023 void InvalidFloatTest() {
2024   auto invalid_msg = "invalid number";
2025   auto comma_msg = "expecting: ,";
2026   TestError("table T { F:float; } root_type T; { F:1,0 }", "");
2027   TestError("table T { F:float; } root_type T; { F:. }", "");
2028   TestError("table T { F:float; } root_type T; { F:- }", invalid_msg);
2029   TestError("table T { F:float; } root_type T; { F:+ }", invalid_msg);
2030   TestError("table T { F:float; } root_type T; { F:-. }", invalid_msg);
2031   TestError("table T { F:float; } root_type T; { F:+. }", invalid_msg);
2032   TestError("table T { F:float; } root_type T; { F:.e }", "");
2033   TestError("table T { F:float; } root_type T; { F:-e }", invalid_msg);
2034   TestError("table T { F:float; } root_type T; { F:+e }", invalid_msg);
2035   TestError("table T { F:float; } root_type T; { F:-.e }", invalid_msg);
2036   TestError("table T { F:float; } root_type T; { F:+.e }", invalid_msg);
2037   TestError("table T { F:float; } root_type T; { F:-e1 }", invalid_msg);
2038   TestError("table T { F:float; } root_type T; { F:+e1 }", invalid_msg);
2039   TestError("table T { F:float; } root_type T; { F:1.0e+ }", invalid_msg);
2040   TestError("table T { F:float; } root_type T; { F:1.0e- }", invalid_msg);
2041   // exponent pP is mandatory for hex-float
2042   TestError("table T { F:float; } root_type T; { F:0x0 }", invalid_msg);
2043   TestError("table T { F:float; } root_type T; { F:-0x. }", invalid_msg);
2044   TestError("table T { F:float; } root_type T; { F:0x. }", invalid_msg);
2045   TestError("table T { F:float; } root_type T; { F:0Xe }", invalid_msg);
2046   TestError("table T { F:float; } root_type T; { F:\"0Xe\" }", invalid_msg);
2047   TestError("table T { F:float; } root_type T; { F:\"nan(1)\" }", invalid_msg);
2048   // eE not exponent in hex-float!
2049   TestError("table T { F:float; } root_type T; { F:0x0.0e+ }", invalid_msg);
2050   TestError("table T { F:float; } root_type T; { F:0x0.0e- }", invalid_msg);
2051   TestError("table T { F:float; } root_type T; { F:0x0.0p }", invalid_msg);
2052   TestError("table T { F:float; } root_type T; { F:0x0.0p+ }", invalid_msg);
2053   TestError("table T { F:float; } root_type T; { F:0x0.0p- }", invalid_msg);
2054   TestError("table T { F:float; } root_type T; { F:0x0.0pa1 }", invalid_msg);
2055   TestError("table T { F:float; } root_type T; { F:0x0.0e+ }", invalid_msg);
2056   TestError("table T { F:float; } root_type T; { F:0x0.0e- }", invalid_msg);
2057   TestError("table T { F:float; } root_type T; { F:0x0.0e+0 }", invalid_msg);
2058   TestError("table T { F:float; } root_type T; { F:0x0.0e-0 }", invalid_msg);
2059   TestError("table T { F:float; } root_type T; { F:0x0.0ep+ }", invalid_msg);
2060   TestError("table T { F:float; } root_type T; { F:0x0.0ep- }", invalid_msg);
2061   TestError("table T { F:float; } root_type T; { F:1.2.3 }", invalid_msg);
2062   TestError("table T { F:float; } root_type T; { F:1.2.e3 }", invalid_msg);
2063   TestError("table T { F:float; } root_type T; { F:1.2e.3 }", invalid_msg);
2064   TestError("table T { F:float; } root_type T; { F:1.2e0.3 }", invalid_msg);
2065   TestError("table T { F:float; } root_type T; { F:1.2e3. }", invalid_msg);
2066   TestError("table T { F:float; } root_type T; { F:1.2e3.0 }", invalid_msg);
2067   TestError("table T { F:float; } root_type T; { F:+-1.0 }", invalid_msg);
2068   TestError("table T { F:float; } root_type T; { F:1.0e+-1 }", invalid_msg);
2069   TestError("table T { F:float; } root_type T; { F:\"1.0e+-1\" }", invalid_msg);
2070   TestError("table T { F:float; } root_type T; { F:1.e0e }", comma_msg);
2071   TestError("table T { F:float; } root_type T; { F:0x1.p0e }", comma_msg);
2072   TestError("table T { F:float; } root_type T; { F:\" 0x10 \" }", invalid_msg);
2073   // floats in string
2074   TestError("table T { F:float; } root_type T; { F:\"1,2.\" }", invalid_msg);
2075   TestError("table T { F:float; } root_type T; { F:\"1.2e3.\" }", invalid_msg);
2076   TestError("table T { F:float; } root_type T; { F:\"0x1.p0e\" }", invalid_msg);
2077   TestError("table T { F:float; } root_type T; { F:\"0x1.0\" }", invalid_msg);
2078   TestError("table T { F:float; } root_type T; { F:\" 0x1.0\" }", invalid_msg);
2079   TestError("table T { F:float; } root_type T; { F:\"+ 0\" }", invalid_msg);
2080   // disable escapes for "number-in-string"
2081   TestError("table T { F:float; } root_type T; { F:\"\\f1.2e3.\" }", "invalid");
2082   TestError("table T { F:float; } root_type T; { F:\"\\t1.2e3.\" }", "invalid");
2083   TestError("table T { F:float; } root_type T; { F:\"\\n1.2e3.\" }", "invalid");
2084   TestError("table T { F:float; } root_type T; { F:\"\\r1.2e3.\" }", "invalid");
2085   TestError("table T { F:float; } root_type T; { F:\"4\\x005\" }", "invalid");
2086   TestError("table T { F:float; } root_type T; { F:\"\'12\'\" }", invalid_msg);
2087   // null is not a number constant!
2088   TestError("table T { F:float; } root_type T; { F:\"null\" }", invalid_msg);
2089   TestError("table T { F:float; } root_type T; { F:null }", invalid_msg);
2090 }
2091
2092 void GenerateTableTextTest() {
2093   std::string schemafile;
2094   std::string jsonfile;
2095   bool ok =
2096       flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
2097                             false, &schemafile) &&
2098       flatbuffers::LoadFile((test_data_path + "monsterdata_test.json").c_str(),
2099                             false, &jsonfile);
2100   TEST_EQ(ok, true);
2101   auto include_test_path =
2102       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
2103   const char *include_directories[] = { test_data_path.c_str(),
2104                                         include_test_path.c_str(), nullptr };
2105   flatbuffers::IDLOptions opt;
2106   opt.indent_step = -1;
2107   flatbuffers::Parser parser(opt);
2108   ok = parser.Parse(schemafile.c_str(), include_directories) &&
2109        parser.Parse(jsonfile.c_str(), include_directories);
2110   TEST_EQ(ok, true);
2111   // Test root table
2112   const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
2113   std::string jsongen;
2114   auto result = GenerateTextFromTable(parser, monster, "MyGame.Example.Monster",
2115                                       &jsongen);
2116   TEST_EQ(result, true);
2117   // Test sub table
2118   const Vec3 *pos = monster->pos();
2119   jsongen.clear();
2120   result = GenerateTextFromTable(parser, pos, "MyGame.Example.Vec3", &jsongen);
2121   TEST_EQ(result, true);
2122   TEST_EQ_STR(
2123       jsongen.c_str(),
2124       "{x: 1.0,y: 2.0,z: 3.0,test1: 3.0,test2: \"Green\",test3: {a: 5,b: 6}}");
2125   const Test &test3 = pos->test3();
2126   jsongen.clear();
2127   result =
2128       GenerateTextFromTable(parser, &test3, "MyGame.Example.Test", &jsongen);
2129   TEST_EQ(result, true);
2130   TEST_EQ_STR(jsongen.c_str(), "{a: 5,b: 6}");
2131   const Test *test4 = monster->test4()->Get(0);
2132   jsongen.clear();
2133   result =
2134       GenerateTextFromTable(parser, test4, "MyGame.Example.Test", &jsongen);
2135   TEST_EQ(result, true);
2136   TEST_EQ_STR(jsongen.c_str(), "{a: 10,b: 20}");
2137 }
2138
2139 template<typename T>
2140 void NumericUtilsTestInteger(const char *lower, const char *upper) {
2141   T x;
2142   TEST_EQ(flatbuffers::StringToNumber("1q", &x), false);
2143   TEST_EQ(x, 0);
2144   TEST_EQ(flatbuffers::StringToNumber(upper, &x), false);
2145   TEST_EQ(x, flatbuffers::numeric_limits<T>::max());
2146   TEST_EQ(flatbuffers::StringToNumber(lower, &x), false);
2147   auto expval = flatbuffers::is_unsigned<T>::value
2148                     ? flatbuffers::numeric_limits<T>::max()
2149                     : flatbuffers::numeric_limits<T>::lowest();
2150   TEST_EQ(x, expval);
2151 }
2152
2153 template<typename T>
2154 void NumericUtilsTestFloat(const char *lower, const char *upper) {
2155   T f;
2156   TEST_EQ(flatbuffers::StringToNumber("", &f), false);
2157   TEST_EQ(flatbuffers::StringToNumber("1q", &f), false);
2158   TEST_EQ(f, 0);
2159   TEST_EQ(flatbuffers::StringToNumber(upper, &f), true);
2160   TEST_EQ(f, +flatbuffers::numeric_limits<T>::infinity());
2161   TEST_EQ(flatbuffers::StringToNumber(lower, &f), true);
2162   TEST_EQ(f, -flatbuffers::numeric_limits<T>::infinity());
2163 }
2164
2165 void NumericUtilsTest() {
2166   NumericUtilsTestInteger<uint64_t>("-1", "18446744073709551616");
2167   NumericUtilsTestInteger<uint8_t>("-1", "256");
2168   NumericUtilsTestInteger<int64_t>("-9223372036854775809",
2169                                    "9223372036854775808");
2170   NumericUtilsTestInteger<int8_t>("-129", "128");
2171   NumericUtilsTestFloat<float>("-3.4029e+38", "+3.4029e+38");
2172   NumericUtilsTestFloat<float>("-1.7977e+308", "+1.7977e+308");
2173 }
2174
2175 void IsAsciiUtilsTest() {
2176   char c = -128;
2177   for (int cnt = 0; cnt < 256; cnt++) {
2178     auto alpha = (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
2179     auto dec = (('0' <= c) && (c <= '9'));
2180     auto hex = (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'));
2181     TEST_EQ(flatbuffers::is_alpha(c), alpha);
2182     TEST_EQ(flatbuffers::is_alnum(c), alpha || dec);
2183     TEST_EQ(flatbuffers::is_digit(c), dec);
2184     TEST_EQ(flatbuffers::is_xdigit(c), dec || hex);
2185     c += 1;
2186   }
2187 }
2188
2189 void UnicodeTest() {
2190   flatbuffers::Parser parser;
2191   // Without setting allow_non_utf8 = true, we treat \x sequences as byte
2192   // sequences which are then validated as UTF-8.
2193   TEST_EQ(parser.Parse("table T { F:string; }"
2194                        "root_type T;"
2195                        "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2196                        "\\u5225\\u30B5\\u30A4\\u30C8\\xE2\\x82\\xAC\\u0080\\uD8"
2197                        "3D\\uDE0E\" }"),
2198           true);
2199   std::string jsongen;
2200   parser.opts.indent_step = -1;
2201   auto result =
2202       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2203   TEST_EQ(result, true);
2204   TEST_EQ_STR(jsongen.c_str(),
2205               "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2206               "\\u5225\\u30B5\\u30A4\\u30C8\\u20AC\\u0080\\uD83D\\uDE0E\"}");
2207 }
2208
2209 void UnicodeTestAllowNonUTF8() {
2210   flatbuffers::Parser parser;
2211   parser.opts.allow_non_utf8 = true;
2212   TEST_EQ(
2213       parser.Parse(
2214           "table T { F:string; }"
2215           "root_type T;"
2216           "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2217           "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
2218       true);
2219   std::string jsongen;
2220   parser.opts.indent_step = -1;
2221   auto result =
2222       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2223   TEST_EQ(result, true);
2224   TEST_EQ_STR(
2225       jsongen.c_str(),
2226       "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2227       "\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}");
2228 }
2229
2230 void UnicodeTestGenerateTextFailsOnNonUTF8() {
2231   flatbuffers::Parser parser;
2232   // Allow non-UTF-8 initially to model what happens when we load a binary
2233   // flatbuffer from disk which contains non-UTF-8 strings.
2234   parser.opts.allow_non_utf8 = true;
2235   TEST_EQ(
2236       parser.Parse(
2237           "table T { F:string; }"
2238           "root_type T;"
2239           "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
2240           "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
2241       true);
2242   std::string jsongen;
2243   parser.opts.indent_step = -1;
2244   // Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates
2245   // failure.
2246   parser.opts.allow_non_utf8 = false;
2247   auto result =
2248       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2249   TEST_EQ(result, false);
2250 }
2251
2252 void UnicodeSurrogatesTest() {
2253   flatbuffers::Parser parser;
2254
2255   TEST_EQ(parser.Parse("table T { F:string (id: 0); }"
2256                        "root_type T;"
2257                        "{ F:\"\\uD83D\\uDCA9\"}"),
2258           true);
2259   auto root = flatbuffers::GetRoot<flatbuffers::Table>(
2260       parser.builder_.GetBufferPointer());
2261   auto string = root->GetPointer<flatbuffers::String *>(
2262       flatbuffers::FieldIndexToOffset(0));
2263   TEST_EQ_STR(string->c_str(), "\xF0\x9F\x92\xA9");
2264 }
2265
2266 void UnicodeInvalidSurrogatesTest() {
2267   TestError(
2268       "table T { F:string; }"
2269       "root_type T;"
2270       "{ F:\"\\uD800\"}",
2271       "unpaired high surrogate");
2272   TestError(
2273       "table T { F:string; }"
2274       "root_type T;"
2275       "{ F:\"\\uD800abcd\"}",
2276       "unpaired high surrogate");
2277   TestError(
2278       "table T { F:string; }"
2279       "root_type T;"
2280       "{ F:\"\\uD800\\n\"}",
2281       "unpaired high surrogate");
2282   TestError(
2283       "table T { F:string; }"
2284       "root_type T;"
2285       "{ F:\"\\uD800\\uD800\"}",
2286       "multiple high surrogates");
2287   TestError(
2288       "table T { F:string; }"
2289       "root_type T;"
2290       "{ F:\"\\uDC00\"}",
2291       "unpaired low surrogate");
2292 }
2293
2294 void InvalidUTF8Test() {
2295   // "1 byte" pattern, under min length of 2 bytes
2296   TestError(
2297       "table T { F:string; }"
2298       "root_type T;"
2299       "{ F:\"\x80\"}",
2300       "illegal UTF-8 sequence");
2301   // 2 byte pattern, string too short
2302   TestError(
2303       "table T { F:string; }"
2304       "root_type T;"
2305       "{ F:\"\xDF\"}",
2306       "illegal UTF-8 sequence");
2307   // 3 byte pattern, string too short
2308   TestError(
2309       "table T { F:string; }"
2310       "root_type T;"
2311       "{ F:\"\xEF\xBF\"}",
2312       "illegal UTF-8 sequence");
2313   // 4 byte pattern, string too short
2314   TestError(
2315       "table T { F:string; }"
2316       "root_type T;"
2317       "{ F:\"\xF7\xBF\xBF\"}",
2318       "illegal UTF-8 sequence");
2319   // "5 byte" pattern, string too short
2320   TestError(
2321       "table T { F:string; }"
2322       "root_type T;"
2323       "{ F:\"\xFB\xBF\xBF\xBF\"}",
2324       "illegal UTF-8 sequence");
2325   // "6 byte" pattern, string too short
2326   TestError(
2327       "table T { F:string; }"
2328       "root_type T;"
2329       "{ F:\"\xFD\xBF\xBF\xBF\xBF\"}",
2330       "illegal UTF-8 sequence");
2331   // "7 byte" pattern, string too short
2332   TestError(
2333       "table T { F:string; }"
2334       "root_type T;"
2335       "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\"}",
2336       "illegal UTF-8 sequence");
2337   // "5 byte" pattern, over max length of 4 bytes
2338   TestError(
2339       "table T { F:string; }"
2340       "root_type T;"
2341       "{ F:\"\xFB\xBF\xBF\xBF\xBF\"}",
2342       "illegal UTF-8 sequence");
2343   // "6 byte" pattern, over max length of 4 bytes
2344   TestError(
2345       "table T { F:string; }"
2346       "root_type T;"
2347       "{ F:\"\xFD\xBF\xBF\xBF\xBF\xBF\"}",
2348       "illegal UTF-8 sequence");
2349   // "7 byte" pattern, over max length of 4 bytes
2350   TestError(
2351       "table T { F:string; }"
2352       "root_type T;"
2353       "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\xBF\"}",
2354       "illegal UTF-8 sequence");
2355
2356   // Three invalid encodings for U+000A (\n, aka NEWLINE)
2357   TestError(
2358       "table T { F:string; }"
2359       "root_type T;"
2360       "{ F:\"\xC0\x8A\"}",
2361       "illegal UTF-8 sequence");
2362   TestError(
2363       "table T { F:string; }"
2364       "root_type T;"
2365       "{ F:\"\xE0\x80\x8A\"}",
2366       "illegal UTF-8 sequence");
2367   TestError(
2368       "table T { F:string; }"
2369       "root_type T;"
2370       "{ F:\"\xF0\x80\x80\x8A\"}",
2371       "illegal UTF-8 sequence");
2372
2373   // Two invalid encodings for U+00A9 (COPYRIGHT SYMBOL)
2374   TestError(
2375       "table T { F:string; }"
2376       "root_type T;"
2377       "{ F:\"\xE0\x81\xA9\"}",
2378       "illegal UTF-8 sequence");
2379   TestError(
2380       "table T { F:string; }"
2381       "root_type T;"
2382       "{ F:\"\xF0\x80\x81\xA9\"}",
2383       "illegal UTF-8 sequence");
2384
2385   // Invalid encoding for U+20AC (EURO SYMBOL)
2386   TestError(
2387       "table T { F:string; }"
2388       "root_type T;"
2389       "{ F:\"\xF0\x82\x82\xAC\"}",
2390       "illegal UTF-8 sequence");
2391
2392   // UTF-16 surrogate values between U+D800 and U+DFFF cannot be encoded in
2393   // UTF-8
2394   TestError(
2395       "table T { F:string; }"
2396       "root_type T;"
2397       // U+10400 "encoded" as U+D801 U+DC00
2398       "{ F:\"\xED\xA0\x81\xED\xB0\x80\"}",
2399       "illegal UTF-8 sequence");
2400
2401   // Check independence of identifier from locale.
2402   std::string locale_ident;
2403   locale_ident += "table T { F";
2404   locale_ident += static_cast<char>(-32);  // unsigned 0xE0
2405   locale_ident += " :string; }";
2406   locale_ident += "root_type T;";
2407   locale_ident += "{}";
2408   TestError(locale_ident.c_str(), "");
2409 }
2410
2411 void UnknownFieldsTest() {
2412   flatbuffers::IDLOptions opts;
2413   opts.skip_unexpected_fields_in_json = true;
2414   flatbuffers::Parser parser(opts);
2415
2416   TEST_EQ(parser.Parse("table T { str:string; i:int;}"
2417                        "root_type T;"
2418                        "{ str:\"test\","
2419                        "unknown_string:\"test\","
2420                        "\"unknown_string\":\"test\","
2421                        "unknown_int:10,"
2422                        "unknown_float:1.0,"
2423                        "unknown_array: [ 1, 2, 3, 4],"
2424                        "unknown_object: { i: 10 },"
2425                        "\"unknown_object\": { \"i\": 10 },"
2426                        "i:10}"),
2427           true);
2428
2429   std::string jsongen;
2430   parser.opts.indent_step = -1;
2431   auto result =
2432       GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
2433   TEST_EQ(result, true);
2434   TEST_EQ_STR(jsongen.c_str(), "{str: \"test\",i: 10}");
2435 }
2436
2437 void ParseUnionTest() {
2438   // Unions must be parseable with the type field following the object.
2439   flatbuffers::Parser parser;
2440   TEST_EQ(parser.Parse("table T { A:int; }"
2441                        "union U { T }"
2442                        "table V { X:U; }"
2443                        "root_type V;"
2444                        "{ X:{ A:1 }, X_type: T }"),
2445           true);
2446   // Unions must be parsable with prefixed namespace.
2447   flatbuffers::Parser parser2;
2448   TEST_EQ(parser2.Parse("namespace N; table A {} namespace; union U { N.A }"
2449                         "table B { e:U; } root_type B;"
2450                         "{ e_type: N_A, e: {} }"),
2451           true);
2452 }
2453
2454 void InvalidNestedFlatbufferTest() {
2455   // First, load and parse FlatBuffer schema (.fbs)
2456   std::string schemafile;
2457   TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
2458                                 false, &schemafile),
2459           true);
2460   auto include_test_path =
2461       flatbuffers::ConCatPathFileName(test_data_path, "include_test");
2462   const char *include_directories[] = { test_data_path.c_str(),
2463                                         include_test_path.c_str(), nullptr };
2464   flatbuffers::Parser parser1;
2465   TEST_EQ(parser1.Parse(schemafile.c_str(), include_directories), true);
2466
2467   // "color" inside nested flatbuffer contains invalid enum value
2468   TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: "
2469                         "\"Leela\", color: \"nonexistent\"}}"),
2470           false);
2471 }
2472
2473 void EvolutionTest() {
2474   // VS10 does not support typed enums, exclude from tests
2475 #if !defined(_MSC_VER) || _MSC_VER >= 1700
2476   const int NUM_VERSIONS = 2;
2477   std::string schemas[NUM_VERSIONS];
2478   std::string jsonfiles[NUM_VERSIONS];
2479   std::vector<uint8_t> binaries[NUM_VERSIONS];
2480
2481   flatbuffers::IDLOptions idl_opts;
2482   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2483   flatbuffers::Parser parser(idl_opts);
2484
2485   // Load all the schema versions and their associated data.
2486   for (int i = 0; i < NUM_VERSIONS; ++i) {
2487     std::string schema = test_data_path + "evolution_test/evolution_v" +
2488                          flatbuffers::NumToString(i + 1) + ".fbs";
2489     TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
2490     std::string json = test_data_path + "evolution_test/evolution_v" +
2491                        flatbuffers::NumToString(i + 1) + ".json";
2492     TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));
2493
2494     TEST_ASSERT(parser.Parse(schemas[i].c_str()));
2495     TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));
2496
2497     auto bufLen = parser.builder_.GetSize();
2498     auto buf = parser.builder_.GetBufferPointer();
2499     binaries[i].reserve(bufLen);
2500     std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
2501   }
2502
2503   // Assert that all the verifiers for the different schema versions properly
2504   // verify any version data.
2505   for (int i = 0; i < NUM_VERSIONS; ++i) {
2506     flatbuffers::Verifier verifier(&binaries[i].front(), binaries[i].size());
2507     TEST_ASSERT(Evolution::V1::VerifyRootBuffer(verifier));
2508     TEST_ASSERT(Evolution::V2::VerifyRootBuffer(verifier));
2509   }
2510
2511   // Test backwards compatibility by reading old data with an evolved schema.
2512   auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front());
2513   // field 'k' is new in version 2, so it should be null.
2514   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->k());
2515   // field 'l' is new in version 2 with a default of 56.
2516   TEST_EQ(root_v1_viewed_from_v2->l(), 56);
2517   // field 'c' of 'TableA' is new in version 2, so it should be null.
2518   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->e()->c());
2519   // 'TableC' was added to field 'c' union in version 2, so it should be null.
2520   TEST_ASSERT(nullptr == root_v1_viewed_from_v2->c_as_TableC());
2521   // The field 'c' union should be of type 'TableB' regardless of schema version
2522   TEST_ASSERT(root_v1_viewed_from_v2->c_type() == Evolution::V2::Union::TableB);
2523   // The field 'f' was renamed to 'ff' in version 2, it should still be
2524   // readable.
2525   TEST_EQ(root_v1_viewed_from_v2->ff()->a(), 16);
2526
2527   // Test forwards compatibility by reading new data with an old schema.
2528   auto root_v2_viewed_from_v1 = Evolution::V1::GetRoot(&binaries[1].front());
2529   // The field 'c' union in version 2 is a new table (index = 3) and should
2530   // still be accessible, but not interpretable.
2531   TEST_EQ(static_cast<uint8_t>(root_v2_viewed_from_v1->c_type()), 3);
2532   TEST_NOTNULL(root_v2_viewed_from_v1->c());
2533   // The field 'd' enum in verison 2 has new members and should still be
2534   // accessible, but not interpretable.
2535   TEST_EQ(static_cast<int8_t>(root_v2_viewed_from_v1->d()), 3);
2536   // The field 'a' in version 2 is deprecated and should return the default
2537   // value (0) instead of the value stored in the in the buffer (42).
2538   TEST_EQ(root_v2_viewed_from_v1->a(), 0);
2539   // The field 'ff' was originally named 'f' in version 1, it should still be
2540   // readable.
2541   TEST_EQ(root_v2_viewed_from_v1->f()->a(), 35);
2542 #endif
2543 }
2544
2545 void UnionDeprecationTest() {
2546   const int NUM_VERSIONS = 2;
2547   std::string schemas[NUM_VERSIONS];
2548   std::string jsonfiles[NUM_VERSIONS];
2549   std::vector<uint8_t> binaries[NUM_VERSIONS];
2550
2551   flatbuffers::IDLOptions idl_opts;
2552   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2553   flatbuffers::Parser parser(idl_opts);
2554
2555   // Load all the schema versions and their associated data.
2556   for (int i = 0; i < NUM_VERSIONS; ++i) {
2557     std::string schema = test_data_path + "evolution_test/evolution_v" +
2558                          flatbuffers::NumToString(i + 1) + ".fbs";
2559     TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
2560     std::string json = test_data_path + "evolution_test/evolution_v" +
2561                        flatbuffers::NumToString(i + 1) + ".json";
2562     TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));
2563
2564     TEST_ASSERT(parser.Parse(schemas[i].c_str()));
2565     TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));
2566
2567     auto bufLen = parser.builder_.GetSize();
2568     auto buf = parser.builder_.GetBufferPointer();
2569     binaries[i].reserve(bufLen);
2570     std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
2571   }
2572
2573   auto v2 = parser.LookupStruct("Evolution.V2.Root");
2574   TEST_NOTNULL(v2);
2575   auto j_type_field = v2->fields.Lookup("j_type");
2576   TEST_NOTNULL(j_type_field);
2577   TEST_ASSERT(j_type_field->deprecated);
2578 }
2579
2580 void UnionVectorTest() {
2581   // load FlatBuffer fbs schema and json.
2582   std::string schemafile, jsonfile;
2583   TEST_EQ(flatbuffers::LoadFile(
2584               (test_data_path + "union_vector/union_vector.fbs").c_str(), false,
2585               &schemafile),
2586           true);
2587   TEST_EQ(flatbuffers::LoadFile(
2588               (test_data_path + "union_vector/union_vector.json").c_str(),
2589               false, &jsonfile),
2590           true);
2591
2592   // parse schema.
2593   flatbuffers::IDLOptions idl_opts;
2594   idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
2595   flatbuffers::Parser parser(idl_opts);
2596   TEST_EQ(parser.Parse(schemafile.c_str()), true);
2597
2598   flatbuffers::FlatBufferBuilder fbb;
2599
2600   // union types.
2601   std::vector<uint8_t> types;
2602   types.push_back(static_cast<uint8_t>(Character_Belle));
2603   types.push_back(static_cast<uint8_t>(Character_MuLan));
2604   types.push_back(static_cast<uint8_t>(Character_BookFan));
2605   types.push_back(static_cast<uint8_t>(Character_Other));
2606   types.push_back(static_cast<uint8_t>(Character_Unused));
2607
2608   // union values.
2609   std::vector<flatbuffers::Offset<void>> characters;
2610   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
2611   characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
2612   characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
2613   characters.push_back(fbb.CreateString("Other").Union());
2614   characters.push_back(fbb.CreateString("Unused").Union());
2615
2616   // create Movie.
2617   const auto movie_offset =
2618       CreateMovie(fbb, Character_Rapunzel,
2619                   fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
2620                   fbb.CreateVector(types), fbb.CreateVector(characters));
2621   FinishMovieBuffer(fbb, movie_offset);
2622
2623   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
2624   TEST_EQ(VerifyMovieBuffer(verifier), true);
2625
2626   auto flat_movie = GetMovie(fbb.GetBufferPointer());
2627
2628   auto TestMovie = [](const Movie *movie) {
2629     TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
2630
2631     auto cts = movie->characters_type();
2632     TEST_EQ(movie->characters_type()->size(), 5);
2633     TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
2634     TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
2635     TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
2636     TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
2637     TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
2638
2639     auto rapunzel = movie->main_character_as_Rapunzel();
2640     TEST_NOTNULL(rapunzel);
2641     TEST_EQ(rapunzel->hair_length(), 6);
2642
2643     auto cs = movie->characters();
2644     TEST_EQ(cs->size(), 5);
2645     auto belle = cs->GetAs<BookReader>(0);
2646     TEST_EQ(belle->books_read(), 7);
2647     auto mu_lan = cs->GetAs<Attacker>(1);
2648     TEST_EQ(mu_lan->sword_attack_damage(), 5);
2649     auto book_fan = cs->GetAs<BookReader>(2);
2650     TEST_EQ(book_fan->books_read(), 2);
2651     auto other = cs->GetAsString(3);
2652     TEST_EQ_STR(other->c_str(), "Other");
2653     auto unused = cs->GetAsString(4);
2654     TEST_EQ_STR(unused->c_str(), "Unused");
2655   };
2656
2657   TestMovie(flat_movie);
2658
2659   // Also test the JSON we loaded above.
2660   TEST_EQ(parser.Parse(jsonfile.c_str()), true);
2661   auto jbuf = parser.builder_.GetBufferPointer();
2662   flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
2663   TEST_EQ(VerifyMovieBuffer(jverifier), true);
2664   TestMovie(GetMovie(jbuf));
2665
2666   auto movie_object = flat_movie->UnPack();
2667   TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
2668   TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
2669   TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
2670   TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
2671   TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
2672   TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
2673
2674   fbb.Clear();
2675   fbb.Finish(Movie::Pack(fbb, movie_object));
2676
2677   delete movie_object;
2678
2679   auto repacked_movie = GetMovie(fbb.GetBufferPointer());
2680
2681   TestMovie(repacked_movie);
2682
2683   // Generate text using mini-reflection.
2684   auto s =
2685       flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
2686   TEST_EQ_STR(
2687       s.c_str(),
2688       "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
2689       "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
2690       "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
2691       "{ books_read: 2 }, \"Other\", \"Unused\" ] }");
2692
2693   flatbuffers::ToStringVisitor visitor("\n", true, "  ");
2694   IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor);
2695   TEST_EQ_STR(visitor.s.c_str(),
2696               "{\n"
2697               "  \"main_character_type\": \"Rapunzel\",\n"
2698               "  \"main_character\": {\n"
2699               "    \"hair_length\": 6\n"
2700               "  },\n"
2701               "  \"characters_type\": [\n"
2702               "    \"Belle\",\n"
2703               "    \"MuLan\",\n"
2704               "    \"BookFan\",\n"
2705               "    \"Other\",\n"
2706               "    \"Unused\"\n"
2707               "  ],\n"
2708               "  \"characters\": [\n"
2709               "    {\n"
2710               "      \"books_read\": 7\n"
2711               "    },\n"
2712               "    {\n"
2713               "      \"sword_attack_damage\": 5\n"
2714               "    },\n"
2715               "    {\n"
2716               "      \"books_read\": 2\n"
2717               "    },\n"
2718               "    \"Other\",\n"
2719               "    \"Unused\"\n"
2720               "  ]\n"
2721               "}");
2722
2723   // Generate text using parsed schema.
2724   std::string jsongen;
2725   auto result = GenerateText(parser, fbb.GetBufferPointer(), &jsongen);
2726   TEST_EQ(result, true);
2727   TEST_EQ_STR(jsongen.c_str(),
2728               "{\n"
2729               "  main_character_type: \"Rapunzel\",\n"
2730               "  main_character: {\n"
2731               "    hair_length: 6\n"
2732               "  },\n"
2733               "  characters_type: [\n"
2734               "    \"Belle\",\n"
2735               "    \"MuLan\",\n"
2736               "    \"BookFan\",\n"
2737               "    \"Other\",\n"
2738               "    \"Unused\"\n"
2739               "  ],\n"
2740               "  characters: [\n"
2741               "    {\n"
2742               "      books_read: 7\n"
2743               "    },\n"
2744               "    {\n"
2745               "      sword_attack_damage: 5\n"
2746               "    },\n"
2747               "    {\n"
2748               "      books_read: 2\n"
2749               "    },\n"
2750               "    \"Other\",\n"
2751               "    \"Unused\"\n"
2752               "  ]\n"
2753               "}\n");
2754
2755   // Simple test with reflection.
2756   parser.Serialize();
2757   auto schema = reflection::GetSchema(parser.builder_.GetBufferPointer());
2758   auto ok = flatbuffers::Verify(*schema, *schema->root_table(),
2759                                 fbb.GetBufferPointer(), fbb.GetSize());
2760   TEST_EQ(ok, true);
2761
2762   flatbuffers::Parser parser2(idl_opts);
2763   TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
2764                         "union Any { Bool }"
2765                         "table Root { a:Any; }"
2766                         "root_type Root;"),
2767           true);
2768   TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
2769 }
2770
2771 void ConformTest() {
2772   flatbuffers::Parser parser;
2773   TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);
2774
2775   auto test_conform = [](flatbuffers::Parser &parser1, const char *test,
2776                          const char *expected_err) {
2777     flatbuffers::Parser parser2;
2778     TEST_EQ(parser2.Parse(test), true);
2779     auto err = parser2.ConformTo(parser1);
2780     TEST_NOTNULL(strstr(err.c_str(), expected_err));
2781   };
2782
2783   test_conform(parser, "table T { A:byte; }", "types differ for field");
2784   test_conform(parser, "table T { B:int; A:int; }", "offsets differ for field");
2785   test_conform(parser, "table T { A:int = 1; }", "defaults differ for field");
2786   test_conform(parser, "table T { B:float; }",
2787                "field renamed to different type");
2788   test_conform(parser, "enum E:byte { B, A }", "values differ for enum");
2789 }
2790
2791 void ParseProtoBufAsciiTest() {
2792   // We can put the parser in a mode where it will accept JSON that looks more
2793   // like Protobuf ASCII, for users that have data in that format.
2794   // This uses no "" for field names (which we already support by default,
2795   // omits `,`, `:` before `{` and a couple of other features.
2796   flatbuffers::Parser parser;
2797   parser.opts.protobuf_ascii_alike = true;
2798   TEST_EQ(
2799       parser.Parse("table S { B:int; } table T { A:[int]; C:S; } root_type T;"),
2800       true);
2801   TEST_EQ(parser.Parse("{ A [1 2] C { B:2 }}"), true);
2802   // Similarly, in text output, it should omit these.
2803   std::string text;
2804   auto ok = flatbuffers::GenerateText(
2805       parser, parser.builder_.GetBufferPointer(), &text);
2806   TEST_EQ(ok, true);
2807   TEST_EQ_STR(text.c_str(),
2808               "{\n  A [\n    1\n    2\n  ]\n  C {\n    B: 2\n  }\n}\n");
2809 }
2810
2811 void FlexBuffersTest() {
2812   flexbuffers::Builder slb(512,
2813                            flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
2814
2815   // Write the equivalent of:
2816   // { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ],
2817   // foo: 100, bool: true, mymap: { foo: "Fred" } }
2818   // clang-format off
2819   #ifndef FLATBUFFERS_CPP98_STL
2820     // It's possible to do this without std::function support as well.
2821     slb.Map([&]() {
2822        slb.Vector("vec", [&]() {
2823         slb += -100;  // Equivalent to slb.Add(-100) or slb.Int(-100);
2824         slb += "Fred";
2825         slb.IndirectFloat(4.0f);
2826         auto i_f = slb.LastValue();
2827         uint8_t blob[] = { 77 };
2828         slb.Blob(blob, 1);
2829         slb += false;
2830         slb.ReuseValue(i_f);
2831       });
2832       int ints[] = { 1, 2, 3 };
2833       slb.Vector("bar", ints, 3);
2834       slb.FixedTypedVector("bar3", ints, 3);
2835       bool bools[] = {true, false, true, false};
2836       slb.Vector("bools", bools, 4);
2837       slb.Bool("bool", true);
2838       slb.Double("foo", 100);
2839       slb.Map("mymap", [&]() {
2840         slb.String("foo", "Fred");  // Testing key and string reuse.
2841       });
2842     });
2843     slb.Finish();
2844   #else
2845     // It's possible to do this without std::function support as well.
2846     slb.Map([](flexbuffers::Builder& slb2) {
2847        slb2.Vector("vec", [](flexbuffers::Builder& slb3) {
2848         slb3 += -100;  // Equivalent to slb.Add(-100) or slb.Int(-100);
2849         slb3 += "Fred";
2850         slb3.IndirectFloat(4.0f);
2851         auto i_f = slb3.LastValue();
2852         uint8_t blob[] = { 77 };
2853         slb3.Blob(blob, 1);
2854         slb3 += false;
2855         slb3.ReuseValue(i_f);
2856       }, slb2);
2857       int ints[] = { 1, 2, 3 };
2858       slb2.Vector("bar", ints, 3);
2859       slb2.FixedTypedVector("bar3", ints, 3);
2860       slb2.Bool("bool", true);
2861       slb2.Double("foo", 100);
2862       slb2.Map("mymap", [](flexbuffers::Builder& slb3) {
2863         slb3.String("foo", "Fred");  // Testing key and string reuse.
2864       }, slb2);
2865     }, slb);
2866     slb.Finish();
2867   #endif  // FLATBUFFERS_CPP98_STL
2868
2869   #ifdef FLATBUFFERS_TEST_VERBOSE
2870     for (size_t i = 0; i < slb.GetBuffer().size(); i++)
2871       printf("%d ", flatbuffers::vector_data(slb.GetBuffer())[i]);
2872     printf("\n");
2873   #endif
2874   // clang-format on
2875
2876   auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap();
2877   TEST_EQ(map.size(), 7);
2878   auto vec = map["vec"].AsVector();
2879   TEST_EQ(vec.size(), 6);
2880   TEST_EQ(vec[0].AsInt64(), -100);
2881   TEST_EQ_STR(vec[1].AsString().c_str(), "Fred");
2882   TEST_EQ(vec[1].AsInt64(), 0);  // Number parsing failed.
2883   TEST_EQ(vec[2].AsDouble(), 4.0);
2884   TEST_EQ(vec[2].AsString().IsTheEmptyString(), true);  // Wrong Type.
2885   TEST_EQ_STR(vec[2].AsString().c_str(), "");     // This still works though.
2886   TEST_EQ_STR(vec[2].ToString().c_str(), "4.0");  // Or have it converted.
2887   // Few tests for templated version of As.
2888   TEST_EQ(vec[0].As<int64_t>(), -100);
2889   TEST_EQ_STR(vec[1].As<std::string>().c_str(), "Fred");
2890   TEST_EQ(vec[1].As<int64_t>(), 0);  // Number parsing failed.
2891   TEST_EQ(vec[2].As<double>(), 4.0);
2892   // Test that the blob can be accessed.
2893   TEST_EQ(vec[3].IsBlob(), true);
2894   auto blob = vec[3].AsBlob();
2895   TEST_EQ(blob.size(), 1);
2896   TEST_EQ(blob.data()[0], 77);
2897   TEST_EQ(vec[4].IsBool(), true);   // Check if type is a bool
2898   TEST_EQ(vec[4].AsBool(), false);  // Check if value is false
2899   TEST_EQ(vec[5].AsDouble(), 4.0);  // This is shared with vec[2] !
2900   auto tvec = map["bar"].AsTypedVector();
2901   TEST_EQ(tvec.size(), 3);
2902   TEST_EQ(tvec[2].AsInt8(), 3);
2903   auto tvec3 = map["bar3"].AsFixedTypedVector();
2904   TEST_EQ(tvec3.size(), 3);
2905   TEST_EQ(tvec3[2].AsInt8(), 3);
2906   TEST_EQ(map["bool"].AsBool(), true);
2907   auto tvecb = map["bools"].AsTypedVector();
2908   TEST_EQ(tvecb.ElementType(), flexbuffers::FBT_BOOL);
2909   TEST_EQ(map["foo"].AsUInt8(), 100);
2910   TEST_EQ(map["unknown"].IsNull(), true);
2911   auto mymap = map["mymap"].AsMap();
2912   // These should be equal by pointer equality, since key and value are shared.
2913   TEST_EQ(mymap.Keys()[0].AsKey(), map.Keys()[4].AsKey());
2914   TEST_EQ(mymap.Values()[0].AsString().c_str(), vec[1].AsString().c_str());
2915   // We can mutate values in the buffer.
2916   TEST_EQ(vec[0].MutateInt(-99), true);
2917   TEST_EQ(vec[0].AsInt64(), -99);
2918   TEST_EQ(vec[1].MutateString("John"), true);  // Size must match.
2919   TEST_EQ_STR(vec[1].AsString().c_str(), "John");
2920   TEST_EQ(vec[1].MutateString("Alfred"), false);  // Too long.
2921   TEST_EQ(vec[2].MutateFloat(2.0f), true);
2922   TEST_EQ(vec[2].AsFloat(), 2.0f);
2923   TEST_EQ(vec[2].MutateFloat(3.14159), false);  // Double does not fit in float.
2924   TEST_EQ(vec[4].AsBool(), false);              // Is false before change
2925   TEST_EQ(vec[4].MutateBool(true), true);       // Can change a bool
2926   TEST_EQ(vec[4].AsBool(), true);               // Changed bool is now true
2927
2928   // Parse from JSON:
2929   flatbuffers::Parser parser;
2930   slb.Clear();
2931   auto jsontest = "{ a: [ 123, 456.0 ], b: \"hello\", c: true, d: false }";
2932   TEST_EQ(parser.ParseFlexBuffer(jsontest, nullptr, &slb), true);
2933   auto jroot = flexbuffers::GetRoot(slb.GetBuffer());
2934   auto jmap = jroot.AsMap();
2935   auto jvec = jmap["a"].AsVector();
2936   TEST_EQ(jvec[0].AsInt64(), 123);
2937   TEST_EQ(jvec[1].AsDouble(), 456.0);
2938   TEST_EQ_STR(jmap["b"].AsString().c_str(), "hello");
2939   TEST_EQ(jmap["c"].IsBool(), true);   // Parsed correctly to a bool
2940   TEST_EQ(jmap["c"].AsBool(), true);   // Parsed correctly to true
2941   TEST_EQ(jmap["d"].IsBool(), true);   // Parsed correctly to a bool
2942   TEST_EQ(jmap["d"].AsBool(), false);  // Parsed correctly to false
2943   // And from FlexBuffer back to JSON:
2944   auto jsonback = jroot.ToString();
2945   TEST_EQ_STR(jsontest, jsonback.c_str());
2946
2947   slb.Clear();
2948   slb.Vector([&]() {
2949     for (int i = 0; i < 130; ++i) slb.Add(static_cast<uint8_t>(255));
2950     slb.Vector([&]() {
2951       for (int i = 0; i < 130; ++i) slb.Add(static_cast<uint8_t>(255));
2952       slb.Vector([] {});
2953     });
2954   });
2955   slb.Finish();
2956   TEST_EQ(slb.GetSize(), 664);
2957 }
2958
2959 void FlexBuffersDeprecatedTest() {
2960   // FlexBuffers as originally designed had a flaw involving the
2961   // FBT_VECTOR_STRING datatype, and this test documents/tests the fix for it.
2962   // Discussion: https://github.com/google/flatbuffers/issues/5627
2963   flexbuffers::Builder slb;
2964   // FBT_VECTOR_* are "typed vectors" where all elements are of the same type.
2965   // Problem is, when storing FBT_STRING elements, it relies on that type to
2966   // get the bit-width for the size field of the string, which in this case
2967   // isn't present, and instead defaults to 8-bit. This means that any strings
2968   // stored inside such a vector, when accessed thru the old API that returns
2969   // a String reference, will appear to be truncated if the string stored is
2970   // actually >=256 bytes.
2971   std::string test_data(300, 'A');
2972   auto start = slb.StartVector();
2973   // This one will have a 16-bit size field.
2974   slb.String(test_data);
2975   // This one will have an 8-bit size field.
2976   slb.String("hello");
2977   // We're asking this to be serialized as a typed vector (true), but not
2978   // fixed size (false). The type will be FBT_VECTOR_STRING with a bit-width
2979   // of whatever the offsets in the vector need, the bit-widths of the strings
2980   // are not stored(!) <- the actual design flaw.
2981   // Note that even in the fixed code, we continue to serialize the elements of
2982   // FBT_VECTOR_STRING as FBT_STRING, since there may be old code out there
2983   // reading new data that we want to continue to function.
2984   // Thus, FBT_VECTOR_STRING, while deprecated, will always be represented the
2985   // same way, the fix lies on the reading side.
2986   slb.EndVector(start, true, false);
2987   slb.Finish();
2988   // So now lets read this data back.
2989   // For existing data, since we have no way of knowing what the actual
2990   // bit-width of the size field of the string is, we are going to ignore this
2991   // field, and instead treat these strings as FBT_KEY (null-terminated), so we
2992   // can deal with strings of arbitrary length. This of course truncates strings
2993   // with embedded nulls, but we think that that is preferrable over truncating
2994   // strings >= 256 bytes.
2995   auto vec = flexbuffers::GetRoot(slb.GetBuffer()).AsTypedVector();
2996   // Even though this was serialized as FBT_VECTOR_STRING, it is read as
2997   // FBT_VECTOR_KEY:
2998   TEST_EQ(vec.ElementType(), flexbuffers::FBT_KEY);
2999   // Access the long string. Previously, this would return a string of size 1,
3000   // since it would read the high-byte of the 16-bit length.
3001   // This should now correctly test the full 300 bytes, using AsKey():
3002   TEST_EQ_STR(vec[0].AsKey(), test_data.c_str());
3003   // Old code that called AsString will continue to work, as the String
3004   // accessor objects now use a cached size that can come from a key as well.
3005   TEST_EQ_STR(vec[0].AsString().c_str(), test_data.c_str());
3006   // Short strings work as before:
3007   TEST_EQ_STR(vec[1].AsKey(), "hello");
3008   TEST_EQ_STR(vec[1].AsString().c_str(), "hello");
3009   // So, while existing code and data mostly "just work" with the fixes applied
3010   // to AsTypedVector and AsString, what do you do going forward?
3011   // Code accessing existing data doesn't necessarily need to change, though
3012   // you could consider using AsKey instead of AsString for a) documenting
3013   // that you are accessing keys, or b) a speedup if you don't actually use
3014   // the string size.
3015   // For new data, or data that doesn't need to be backwards compatible,
3016   // instead serialize as FBT_VECTOR (call EndVector with typed = false, then
3017   // read elements with AsString), or, for maximum compactness, use
3018   // FBT_VECTOR_KEY (call slb.Key above instead, read with AsKey or AsString).
3019 }
3020
3021 void TypeAliasesTest() {
3022   flatbuffers::FlatBufferBuilder builder;
3023
3024   builder.Finish(CreateTypeAliases(
3025       builder, flatbuffers::numeric_limits<int8_t>::min(),
3026       flatbuffers::numeric_limits<uint8_t>::max(),
3027       flatbuffers::numeric_limits<int16_t>::min(),
3028       flatbuffers::numeric_limits<uint16_t>::max(),
3029       flatbuffers::numeric_limits<int32_t>::min(),
3030       flatbuffers::numeric_limits<uint32_t>::max(),
3031       flatbuffers::numeric_limits<int64_t>::min(),
3032       flatbuffers::numeric_limits<uint64_t>::max(), 2.3f, 2.3));
3033
3034   auto p = builder.GetBufferPointer();
3035   auto ta = flatbuffers::GetRoot<TypeAliases>(p);
3036
3037   TEST_EQ(ta->i8(), flatbuffers::numeric_limits<int8_t>::min());
3038   TEST_EQ(ta->u8(), flatbuffers::numeric_limits<uint8_t>::max());
3039   TEST_EQ(ta->i16(), flatbuffers::numeric_limits<int16_t>::min());
3040   TEST_EQ(ta->u16(), flatbuffers::numeric_limits<uint16_t>::max());
3041   TEST_EQ(ta->i32(), flatbuffers::numeric_limits<int32_t>::min());
3042   TEST_EQ(ta->u32(), flatbuffers::numeric_limits<uint32_t>::max());
3043   TEST_EQ(ta->i64(), flatbuffers::numeric_limits<int64_t>::min());
3044   TEST_EQ(ta->u64(), flatbuffers::numeric_limits<uint64_t>::max());
3045   TEST_EQ(ta->f32(), 2.3f);
3046   TEST_EQ(ta->f64(), 2.3);
3047   using namespace flatbuffers;  // is_same
3048   static_assert(is_same<decltype(ta->i8()), int8_t>::value, "invalid type");
3049   static_assert(is_same<decltype(ta->i16()), int16_t>::value, "invalid type");
3050   static_assert(is_same<decltype(ta->i32()), int32_t>::value, "invalid type");
3051   static_assert(is_same<decltype(ta->i64()), int64_t>::value, "invalid type");
3052   static_assert(is_same<decltype(ta->u8()), uint8_t>::value, "invalid type");
3053   static_assert(is_same<decltype(ta->u16()), uint16_t>::value, "invalid type");
3054   static_assert(is_same<decltype(ta->u32()), uint32_t>::value, "invalid type");
3055   static_assert(is_same<decltype(ta->u64()), uint64_t>::value, "invalid type");
3056   static_assert(is_same<decltype(ta->f32()), float>::value, "invalid type");
3057   static_assert(is_same<decltype(ta->f64()), double>::value, "invalid type");
3058 }
3059
3060 void EndianSwapTest() {
3061   TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
3062   TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
3063           0x78563412);
3064   TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
3065           0xEFCDAB9078563412);
3066   TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
3067 }
3068
3069 void UninitializedVectorTest() {
3070   flatbuffers::FlatBufferBuilder builder;
3071
3072   Test *buf = nullptr;
3073   auto vector_offset =
3074       builder.CreateUninitializedVectorOfStructs<Test>(2, &buf);
3075   TEST_NOTNULL(buf);
3076   buf[0] = Test(10, 20);
3077   buf[1] = Test(30, 40);
3078
3079   auto required_name = builder.CreateString("myMonster");
3080   auto monster_builder = MonsterBuilder(builder);
3081   monster_builder.add_name(
3082       required_name);  // required field mandated for monster.
3083   monster_builder.add_test4(vector_offset);
3084   builder.Finish(monster_builder.Finish());
3085
3086   auto p = builder.GetBufferPointer();
3087   auto uvt = flatbuffers::GetRoot<Monster>(p);
3088   TEST_NOTNULL(uvt);
3089   auto vec = uvt->test4();
3090   TEST_NOTNULL(vec);
3091   auto test_0 = vec->Get(0);
3092   auto test_1 = vec->Get(1);
3093   TEST_EQ(test_0->a(), 10);
3094   TEST_EQ(test_0->b(), 20);
3095   TEST_EQ(test_1->a(), 30);
3096   TEST_EQ(test_1->b(), 40);
3097 }
3098
3099 void EqualOperatorTest() {
3100   MonsterT a;
3101   MonsterT b;
3102   TEST_EQ(b == a, true);
3103   TEST_EQ(b != a, false);
3104
3105   b.mana = 33;
3106   TEST_EQ(b == a, false);
3107   TEST_EQ(b != a, true);
3108   b.mana = 150;
3109   TEST_EQ(b == a, true);
3110   TEST_EQ(b != a, false);
3111
3112   b.inventory.push_back(3);
3113   TEST_EQ(b == a, false);
3114   TEST_EQ(b != a, true);
3115   b.inventory.clear();
3116   TEST_EQ(b == a, true);
3117   TEST_EQ(b != a, false);
3118
3119   b.test.type = Any_Monster;
3120   TEST_EQ(b == a, false);
3121   TEST_EQ(b != a, true);
3122 }
3123
3124 // For testing any binaries, e.g. from fuzzing.
3125 void LoadVerifyBinaryTest() {
3126   std::string binary;
3127   if (flatbuffers::LoadFile(
3128           (test_data_path + "fuzzer/your-filename-here").c_str(), true,
3129           &binary)) {
3130     flatbuffers::Verifier verifier(
3131         reinterpret_cast<const uint8_t *>(binary.data()), binary.size());
3132     TEST_EQ(VerifyMonsterBuffer(verifier), true);
3133   }
3134 }
3135
3136 void CreateSharedStringTest() {
3137   flatbuffers::FlatBufferBuilder builder;
3138   const auto one1 = builder.CreateSharedString("one");
3139   const auto two = builder.CreateSharedString("two");
3140   const auto one2 = builder.CreateSharedString("one");
3141   TEST_EQ(one1.o, one2.o);
3142   const auto onetwo = builder.CreateSharedString("onetwo");
3143   TEST_EQ(onetwo.o != one1.o, true);
3144   TEST_EQ(onetwo.o != two.o, true);
3145
3146   // Support for embedded nulls
3147   const char chars_b[] = { 'a', '\0', 'b' };
3148   const char chars_c[] = { 'a', '\0', 'c' };
3149   const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b));
3150   const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c));
3151   const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b));
3152   TEST_EQ(null_b1.o != null_c.o, true);  // Issue#5058 repro
3153   TEST_EQ(null_b1.o, null_b2.o);
3154
3155   // Put the strings into an array for round trip verification.
3156   const flatbuffers::Offset<flatbuffers::String> array[7] = {
3157     one1, two, one2, onetwo, null_b1, null_c, null_b2
3158   };
3159   const auto vector_offset =
3160       builder.CreateVector(array, flatbuffers::uoffset_t(7));
3161   MonsterBuilder monster_builder(builder);
3162   monster_builder.add_name(two);
3163   monster_builder.add_testarrayofstring(vector_offset);
3164   builder.Finish(monster_builder.Finish());
3165
3166   // Read the Monster back.
3167   const auto *monster =
3168       flatbuffers::GetRoot<Monster>(builder.GetBufferPointer());
3169   TEST_EQ_STR(monster->name()->c_str(), "two");
3170   const auto *testarrayofstring = monster->testarrayofstring();
3171   TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7));
3172   const auto &a = *testarrayofstring;
3173   TEST_EQ_STR(a[0]->c_str(), "one");
3174   TEST_EQ_STR(a[1]->c_str(), "two");
3175   TEST_EQ_STR(a[2]->c_str(), "one");
3176   TEST_EQ_STR(a[3]->c_str(), "onetwo");
3177   TEST_EQ(a[4]->str(), (std::string(chars_b, sizeof(chars_b))));
3178   TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c))));
3179   TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b))));
3180
3181   // Make sure String::operator< works, too, since it is related to
3182   // StringOffsetCompare.
3183   TEST_EQ((*a[0]) < (*a[1]), true);
3184   TEST_EQ((*a[1]) < (*a[0]), false);
3185   TEST_EQ((*a[1]) < (*a[2]), false);
3186   TEST_EQ((*a[2]) < (*a[1]), true);
3187   TEST_EQ((*a[4]) < (*a[3]), true);
3188   TEST_EQ((*a[5]) < (*a[4]), false);
3189   TEST_EQ((*a[5]) < (*a[4]), false);
3190   TEST_EQ((*a[6]) < (*a[5]), true);
3191 }
3192
3193 void FixedLengthArrayTest() {
3194   // VS10 does not support typed enums, exclude from tests
3195 #if !defined(_MSC_VER) || _MSC_VER >= 1700
3196   // Generate an ArrayTable containing one ArrayStruct.
3197   flatbuffers::FlatBufferBuilder fbb;
3198   MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
3199   TEST_NOTNULL(nStruct0.mutable_a());
3200   nStruct0.mutable_a()->Mutate(0, 1);
3201   nStruct0.mutable_a()->Mutate(1, 2);
3202   TEST_NOTNULL(nStruct0.mutable_c());
3203   nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
3204   nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
3205   TEST_NOTNULL(nStruct0.mutable_d());
3206   nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
3207   nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
3208   MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
3209   TEST_NOTNULL(nStruct1.mutable_a());
3210   nStruct1.mutable_a()->Mutate(0, 3);
3211   nStruct1.mutable_a()->Mutate(1, 4);
3212   TEST_NOTNULL(nStruct1.mutable_c());
3213   nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
3214   nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
3215   TEST_NOTNULL(nStruct1.mutable_d());
3216   nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
3217   nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
3218   MyGame::Example::ArrayStruct aStruct(2, 12, 1);
3219   TEST_NOTNULL(aStruct.b());
3220   TEST_NOTNULL(aStruct.mutable_b());
3221   TEST_NOTNULL(aStruct.mutable_d());
3222   TEST_NOTNULL(aStruct.mutable_f());
3223   for (int i = 0; i < aStruct.b()->size(); i++)
3224     aStruct.mutable_b()->Mutate(i, i + 1);
3225   aStruct.mutable_d()->Mutate(0, nStruct0);
3226   aStruct.mutable_d()->Mutate(1, nStruct1);
3227   auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
3228   MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
3229
3230   // Verify correctness of the ArrayTable.
3231   flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
3232   MyGame::Example::VerifyArrayTableBuffer(verifier);
3233   auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
3234   auto mArStruct = p->mutable_a();
3235   TEST_NOTNULL(mArStruct);
3236   TEST_NOTNULL(mArStruct->b());
3237   TEST_NOTNULL(mArStruct->d());
3238   TEST_NOTNULL(mArStruct->f());
3239   TEST_NOTNULL(mArStruct->mutable_b());
3240   TEST_NOTNULL(mArStruct->mutable_d());
3241   TEST_NOTNULL(mArStruct->mutable_f());
3242   mArStruct->mutable_b()->Mutate(14, -14);
3243   TEST_EQ(mArStruct->a(), 2);
3244   TEST_EQ(mArStruct->b()->size(), 15);
3245   TEST_EQ(mArStruct->b()->Get(aStruct.b()->size() - 1), -14);
3246   TEST_EQ(mArStruct->c(), 12);
3247   TEST_NOTNULL(mArStruct->d()->Get(0));
3248   TEST_NOTNULL(mArStruct->d()->Get(0)->a());
3249   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(0), 1);
3250   TEST_EQ(mArStruct->d()->Get(0)->a()->Get(1), 2);
3251   TEST_NOTNULL(mArStruct->d()->Get(1));
3252   TEST_NOTNULL(mArStruct->d()->Get(1)->a());
3253   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(0), 3);
3254   TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 4);
3255   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
3256   TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
3257   mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
3258   TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1));
3259   TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b());
3260   TEST_NOTNULL(mArStruct->d()->Get(0)->c());
3261   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0));
3262   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1));
3263   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
3264           mArStruct->d()->Get(0)->d()->Get(0));
3265   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
3266           mArStruct->d()->Get(0)->d()->Get(1));
3267   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b());
3268   TEST_NOTNULL(mArStruct->d()->Get(1)->c());
3269   TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0));
3270   TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1));
3271   TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
3272           mArStruct->d()->Get(1)->d()->Get(0));
3273   TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
3274           mArStruct->d()->Get(1)->d()->Get(1));
3275   for (int i = 0; i < mArStruct->b()->size() - 1; i++)
3276     TEST_EQ(mArStruct->b()->Get(i), i + 1);
3277   // Check alignment
3278   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->d()) % 8);
3279   TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->f()) % 8);
3280
3281   // Check if default constructor set all memory zero
3282   const size_t arr_size = sizeof(MyGame::Example::ArrayStruct);
3283   char non_zero_memory[arr_size];
3284   // set memory chunk of size ArrayStruct to 1's
3285   std::memset(static_cast<void *>(non_zero_memory), 1, arr_size);
3286   // after placement-new it should be all 0's
3287 #if defined (_MSC_VER) && defined (_DEBUG)
3288   #undef new
3289 #endif
3290   MyGame::Example::ArrayStruct *ap = new (non_zero_memory) MyGame::Example::ArrayStruct;
3291 #if defined (_MSC_VER) && defined (_DEBUG)
3292   #define new DEBUG_NEW
3293 #endif
3294   (void)ap;
3295   for (size_t i = 0; i < arr_size; ++i) {
3296     TEST_EQ(non_zero_memory[i], 0);
3297   }
3298 #endif
3299 }
3300
3301 void NativeTypeTest() {
3302   const int N = 3;
3303
3304   Geometry::ApplicationDataT src_data;
3305   src_data.vectors.reserve(N);
3306
3307   for (int i = 0; i < N; ++i) {
3308     src_data.vectors.push_back(
3309         Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f));
3310   }
3311
3312   flatbuffers::FlatBufferBuilder fbb;
3313   fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data));
3314
3315   auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer());
3316
3317   for (int i = 0; i < N; ++i) {
3318     Native::Vector3D &v = dstDataT->vectors[i];
3319     TEST_EQ(v.x, 10 * i + 0.1f);
3320     TEST_EQ(v.y, 10 * i + 0.2f);
3321     TEST_EQ(v.z, 10 * i + 0.3f);
3322   }
3323 }
3324
3325 void FixedLengthArrayJsonTest(bool binary) {
3326   // VS10 does not support typed enums, exclude from tests
3327 #if !defined(_MSC_VER) || _MSC_VER >= 1700
3328   // load FlatBuffer schema (.fbs) and JSON from disk
3329   std::string schemafile;
3330   std::string jsonfile;
3331   TEST_EQ(
3332       flatbuffers::LoadFile(
3333           (test_data_path + "arrays_test." + (binary ? "bfbs" : "fbs")).c_str(),
3334           binary, &schemafile),
3335       true);
3336   TEST_EQ(flatbuffers::LoadFile((test_data_path + "arrays_test.golden").c_str(),
3337                                 false, &jsonfile),
3338           true);
3339
3340   // parse schema first, so we can use it to parse the data after
3341   flatbuffers::Parser parserOrg, parserGen;
3342   if (binary) {
3343     flatbuffers::Verifier verifier(
3344         reinterpret_cast<const uint8_t *>(schemafile.c_str()),
3345         schemafile.size());
3346     TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
3347     TEST_EQ(parserOrg.Deserialize((const uint8_t *)schemafile.c_str(),
3348                                   schemafile.size()),
3349             true);
3350     TEST_EQ(parserGen.Deserialize((const uint8_t *)schemafile.c_str(),
3351                                   schemafile.size()),
3352             true);
3353   } else {
3354     TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
3355     TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
3356   }
3357   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
3358
3359   // First, verify it, just in case:
3360   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
3361                                     parserOrg.builder_.GetSize());
3362   TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
3363
3364   // Export to JSON
3365   std::string jsonGen;
3366   TEST_EQ(
3367       GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
3368       true);
3369
3370   // Import from JSON
3371   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
3372
3373   // Verify buffer from generated JSON
3374   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
3375                                     parserGen.builder_.GetSize());
3376   TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
3377
3378   // Compare generated buffer to original
3379   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
3380   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
3381                       parserGen.builder_.GetBufferPointer(),
3382                       parserOrg.builder_.GetSize()),
3383           0);
3384 #else
3385   (void)binary;
3386 #endif
3387 }
3388
3389 void TestEmbeddedBinarySchema() {
3390   // load JSON from disk
3391   std::string jsonfile;
3392   TEST_EQ(flatbuffers::LoadFile(
3393               (test_data_path + "monsterdata_test.golden").c_str(), false,
3394               &jsonfile),
3395           true);
3396
3397   // parse schema first, so we can use it to parse the data after
3398   flatbuffers::Parser parserOrg, parserGen;
3399   flatbuffers::Verifier verifier(MyGame::Example::MonsterBinarySchema::data(),
3400                                  MyGame::Example::MonsterBinarySchema::size());
3401   TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
3402   TEST_EQ(parserOrg.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
3403                                 MyGame::Example::MonsterBinarySchema::size()),
3404           true);
3405   TEST_EQ(parserGen.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
3406                                 MyGame::Example::MonsterBinarySchema::size()),
3407           true);
3408   TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
3409
3410   // First, verify it, just in case:
3411   flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
3412                                     parserOrg.builder_.GetSize());
3413   TEST_EQ(VerifyMonsterBuffer(verifierOrg), true);
3414
3415   // Export to JSON
3416   std::string jsonGen;
3417   TEST_EQ(
3418       GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
3419       true);
3420
3421   // Import from JSON
3422   TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
3423
3424   // Verify buffer from generated JSON
3425   flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
3426                                     parserGen.builder_.GetSize());
3427   TEST_EQ(VerifyMonsterBuffer(verifierGen), true);
3428
3429   // Compare generated buffer to original
3430   TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
3431   TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
3432                       parserGen.builder_.GetBufferPointer(),
3433                       parserOrg.builder_.GetSize()),
3434           0);
3435 }
3436
3437 void OptionalScalarsTest() {
3438   // Simple schemas and a "has optional scalar" sentinal.
3439   std::vector<std::string> schemas;
3440   schemas.push_back("table Monster { mana : int; }");
3441   schemas.push_back("table Monster { mana : int = 42; }");
3442   schemas.push_back("table Monster { mana : int =  null; }");
3443   schemas.push_back("table Monster { mana : long; }");
3444   schemas.push_back("table Monster { mana : long = 42; }");
3445   schemas.push_back("table Monster { mana : long = null; }");
3446   schemas.push_back("table Monster { mana : float; }");
3447   schemas.push_back("table Monster { mana : float = 42; }");
3448   schemas.push_back("table Monster { mana : float = null; }");
3449   schemas.push_back("table Monster { mana : double; }");
3450   schemas.push_back("table Monster { mana : double = 42; }");
3451   schemas.push_back("table Monster { mana : double = null; }");
3452   schemas.push_back("table Monster { mana : bool; }");
3453   schemas.push_back("table Monster { mana : bool = 42; }");
3454   schemas.push_back("table Monster { mana : bool = null; }");
3455
3456   // Check the FieldDef is correctly set.
3457   for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
3458     const bool has_null = schema->find("null") != std::string::npos;
3459     flatbuffers::Parser parser;
3460     TEST_ASSERT(parser.Parse(schema->c_str()));
3461     const auto *mana = parser.structs_.Lookup("Monster")->fields.Lookup("mana");
3462     TEST_EQ(mana->optional, has_null);
3463   }
3464
3465   // Test if optional scalars are allowed for each language.
3466   const int kNumLanguages = 17;
3467   const auto supported = (flatbuffers::IDLOptions::kRust |
3468                           flatbuffers::IDLOptions::kSwift |
3469                           flatbuffers::IDLOptions::kLobster);
3470   for (int lang=0; lang<kNumLanguages; lang++) {
3471     flatbuffers::IDLOptions opts;
3472     opts.lang_to_generate |= 1 << lang;
3473     if (opts.lang_to_generate & supported) continue;
3474     for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
3475       const bool has_null = schema->find("null") != std::string::npos;
3476       flatbuffers::Parser parser(opts);
3477       // Its not supported in any language yet so has_null means error.
3478       TEST_EQ(parser.Parse(schema->c_str()), !has_null);
3479     }
3480   }
3481 }
3482
3483 void ParseFlexbuffersFromJsonWithNullTest() {
3484   // Test nulls are handled appropriately through flexbuffers to exercise other
3485   // code paths of ParseSingleValue in the optional scalars change.
3486   // TODO(cneo): Json -> Flatbuffers test once some language can generate code
3487   // with optional scalars.
3488   {
3489     char json[] = "{\"opt_field\": 123 }";
3490     flatbuffers::Parser parser;
3491     flexbuffers::Builder flexbuild;
3492     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3493     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3494     TEST_EQ(root.AsMap()["opt_field"].AsInt64(), 123);
3495   }
3496   {
3497     char json[] = "{\"opt_field\": 123.4 }";
3498     flatbuffers::Parser parser;
3499     flexbuffers::Builder flexbuild;
3500     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3501     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3502     TEST_EQ(root.AsMap()["opt_field"].AsDouble(), 123.4);
3503   }
3504   {
3505     char json[] = "{\"opt_field\": null }";
3506     flatbuffers::Parser parser;
3507     flexbuffers::Builder flexbuild;
3508     parser.ParseFlexBuffer(json, nullptr, &flexbuild);
3509     auto root = flexbuffers::GetRoot(flexbuild.GetBuffer());
3510     TEST_ASSERT(!root.AsMap().IsTheEmptyMap());
3511     TEST_ASSERT(root.AsMap()["opt_field"].IsNull());
3512     TEST_EQ(root.ToString(), std::string("{ opt_field: null }"));
3513   }
3514 }
3515
3516 int FlatBufferTests() {
3517   // clang-format off
3518
3519   // Run our various test suites:
3520
3521   std::string rawbuf;
3522   auto flatbuf1 = CreateFlatBufferTest(rawbuf);
3523   #if !defined(FLATBUFFERS_CPP98_STL)
3524     auto flatbuf = std::move(flatbuf1);  // Test move assignment.
3525   #else
3526     auto &flatbuf = flatbuf1;
3527   #endif // !defined(FLATBUFFERS_CPP98_STL)
3528
3529   TriviallyCopyableTest();
3530
3531   AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()),
3532                        rawbuf.length());
3533   AccessFlatBufferTest(flatbuf.data(), flatbuf.size());
3534
3535   MutateFlatBuffersTest(flatbuf.data(), flatbuf.size());
3536
3537   ObjectFlatBuffersTest(flatbuf.data());
3538
3539   MiniReflectFlatBuffersTest(flatbuf.data());
3540
3541   SizePrefixedTest();
3542
3543   #ifndef FLATBUFFERS_NO_FILE_TESTS
3544     #ifdef FLATBUFFERS_TEST_PATH_PREFIX
3545       test_data_path = FLATBUFFERS_STRING(FLATBUFFERS_TEST_PATH_PREFIX) +
3546                        test_data_path;
3547     #endif
3548     ParseAndGenerateTextTest(false);
3549     ParseAndGenerateTextTest(true);
3550     FixedLengthArrayJsonTest(false);
3551     FixedLengthArrayJsonTest(true);
3552     ReflectionTest(flatbuf.data(), flatbuf.size());
3553     ParseProtoTest();
3554     ParseProtoTestWithSuffix();
3555     ParseProtoTestWithIncludes();
3556     EvolutionTest();
3557     UnionDeprecationTest();
3558     UnionVectorTest();
3559     LoadVerifyBinaryTest();
3560     GenerateTableTextTest();
3561     TestEmbeddedBinarySchema();
3562   #endif
3563   // clang-format on
3564
3565   FuzzTest1();
3566   FuzzTest2();
3567
3568   ErrorTest();
3569   ValueTest();
3570   EnumValueTest();
3571   EnumStringsTest();
3572   EnumNamesTest();
3573   EnumOutOfRangeTest();
3574   IntegerOutOfRangeTest();
3575   IntegerBoundaryTest();
3576   UnicodeTest();
3577   UnicodeTestAllowNonUTF8();
3578   UnicodeTestGenerateTextFailsOnNonUTF8();
3579   UnicodeSurrogatesTest();
3580   UnicodeInvalidSurrogatesTest();
3581   InvalidUTF8Test();
3582   UnknownFieldsTest();
3583   ParseUnionTest();
3584   InvalidNestedFlatbufferTest();
3585   ConformTest();
3586   ParseProtoBufAsciiTest();
3587   TypeAliasesTest();
3588   EndianSwapTest();
3589   CreateSharedStringTest();
3590   JsonDefaultTest();
3591   JsonEnumsTest();
3592   FlexBuffersTest();
3593   FlexBuffersDeprecatedTest();
3594   UninitializedVectorTest();
3595   EqualOperatorTest();
3596   NumericUtilsTest();
3597   IsAsciiUtilsTest();
3598   ValidFloatTest();
3599   InvalidFloatTest();
3600   TestMonsterExtraFloats();
3601   FixedLengthArrayTest();
3602   NativeTypeTest();
3603   OptionalScalarsTest();
3604   ParseFlexbuffersFromJsonWithNullTest();
3605   return 0;
3606 }
3607
3608 int main(int /*argc*/, const char * /*argv*/[]) {
3609   InitTestEngine();
3610
3611   std::string req_locale;
3612   if (flatbuffers::ReadEnvironmentVariable("FLATBUFFERS_TEST_LOCALE",
3613                                            &req_locale)) {
3614     TEST_OUTPUT_LINE("The environment variable FLATBUFFERS_TEST_LOCALE=%s",
3615                      req_locale.c_str());
3616     req_locale = flatbuffers::RemoveStringQuotes(req_locale);
3617     std::string the_locale;
3618     TEST_ASSERT_FUNC(
3619         flatbuffers::SetGlobalTestLocale(req_locale.c_str(), &the_locale));
3620     TEST_OUTPUT_LINE("The global C-locale changed: %s", the_locale.c_str());
3621   }
3622
3623   FlatBufferTests();
3624   FlatBufferBuilderTest();
3625
3626   if (!testing_fails) {
3627     TEST_OUTPUT_LINE("ALL TESTS PASSED");
3628   } else {
3629     TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
3630   }
3631   return CloseTestEngine();
3632 }