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