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