blob: 7e05c08ff2213b553ac8870c6571af275c9a7f9b [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
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 */
Austin Schuh2dd86a92022-09-14 21:19:23 -070016#include <stdint.h>
17
Austin Schuhe89fa2d2019-08-14 20:24:23 -070018#include <cmath>
Austin Schuh2dd86a92022-09-14 21:19:23 -070019#include <memory>
James Kuszmaul8e62b022022-03-22 09:33:25 -070020#include <string>
Austin Schuh272c6132020-11-14 16:37:52 -080021
Austin Schuh2dd86a92022-09-14 21:19:23 -070022#include "evolution_test.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070023#include "flatbuffers/flatbuffers.h"
24#include "flatbuffers/idl.h"
25#include "flatbuffers/minireflect.h"
26#include "flatbuffers/registry.h"
27#include "flatbuffers/util.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070028#include "fuzz_test.h"
29#include "json_test.h"
30#include "monster_test.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070031#include "monster_test_generated.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070032#include "optional_scalars_test.h"
33#include "native_inline_table_test_generated.h"
34#include "parser_test.h"
35#include "proto_test.h"
36#include "reflection_test.h"
James Kuszmaul8e62b022022-03-22 09:33:25 -070037#include "union_vector/union_vector_generated.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070038#if !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuh272c6132020-11-14 16:37:52 -080039# include "arrays_test_generated.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070040#endif
41
Austin Schuh2dd86a92022-09-14 21:19:23 -070042#include "flexbuffers_test.h"
43#include "is_quiet_nan.h"
Austin Schuh272c6132020-11-14 16:37:52 -080044#include "monster_test_bfbs_generated.h" // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed
James Kuszmaul8e62b022022-03-22 09:33:25 -070045#include "native_type_test_generated.h"
46#include "test_assert.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070047#include "util_test.h"
48
49void FlatBufferBuilderTest();
50
51namespace flatbuffers {
52namespace tests {
53namespace {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070054
55// clang-format off
56// Check that char* and uint8_t* are interoperable types.
57// The reinterpret_cast<> between the pointers are used to simplify data loading.
58static_assert(flatbuffers::is_same<uint8_t, char>::value ||
59 flatbuffers::is_same<uint8_t, unsigned char>::value,
60 "unexpected uint8_t type");
61
62#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
63 // Ensure IEEE-754 support if tests of floats with NaN/Inf will run.
64 static_assert(std::numeric_limits<float>::is_iec559 &&
65 std::numeric_limits<double>::is_iec559,
66 "IEC-559 (IEEE-754) standard required");
67#endif
68// clang-format on
69
Austin Schuhe89fa2d2019-08-14 20:24:23 -070070using namespace MyGame::Example;
71
Austin Schuhe89fa2d2019-08-14 20:24:23 -070072void TriviallyCopyableTest() {
James Kuszmaul8e62b022022-03-22 09:33:25 -070073// clang-format off
Austin Schuh2dd86a92022-09-14 21:19:23 -070074 #if __GNUG__ && __GNUC__ < 5 && \
75 !(defined(__clang__) && __clang_major__ >= 16)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070076 TEST_EQ(__has_trivial_copy(Vec3), true);
77 #else
78 #if __cplusplus >= 201103L
79 TEST_EQ(std::is_trivially_copyable<Vec3>::value, true);
80 #endif
81 #endif
82 // clang-format on
83}
84
Austin Schuh2dd86a92022-09-14 21:19:23 -070085void GenerateTableTextTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070086 std::string schemafile;
87 std::string jsonfile;
88 bool ok =
Austin Schuh2dd86a92022-09-14 21:19:23 -070089 flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -070090 false, &schemafile) &&
Austin Schuh2dd86a92022-09-14 21:19:23 -070091 flatbuffers::LoadFile((tests_data_path + "monsterdata_test.json").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -070092 false, &jsonfile);
93 TEST_EQ(ok, true);
94 auto include_test_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -070095 flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
96 const char *include_directories[] = { tests_data_path.c_str(),
Austin Schuh272c6132020-11-14 16:37:52 -080097 include_test_path.c_str(), nullptr };
Austin Schuhe89fa2d2019-08-14 20:24:23 -070098 flatbuffers::IDLOptions opt;
99 opt.indent_step = -1;
100 flatbuffers::Parser parser(opt);
101 ok = parser.Parse(schemafile.c_str(), include_directories) &&
102 parser.Parse(jsonfile.c_str(), include_directories);
103 TEST_EQ(ok, true);
104 // Test root table
105 const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
James Kuszmaul8e62b022022-03-22 09:33:25 -0700106 const auto abilities = monster->testarrayofsortedstruct();
107 TEST_EQ(abilities->size(), 3);
108 TEST_EQ(abilities->Get(0)->id(), 0);
109 TEST_EQ(abilities->Get(0)->distance(), 45);
110 TEST_EQ(abilities->Get(1)->id(), 1);
111 TEST_EQ(abilities->Get(1)->distance(), 21);
112 TEST_EQ(abilities->Get(2)->id(), 5);
113 TEST_EQ(abilities->Get(2)->distance(), 12);
114
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700115 std::string jsongen;
116 auto result = GenerateTextFromTable(parser, monster, "MyGame.Example.Monster",
117 &jsongen);
118 TEST_EQ(result, true);
119 // Test sub table
120 const Vec3 *pos = monster->pos();
121 jsongen.clear();
122 result = GenerateTextFromTable(parser, pos, "MyGame.Example.Vec3", &jsongen);
123 TEST_EQ(result, true);
124 TEST_EQ_STR(
125 jsongen.c_str(),
126 "{x: 1.0,y: 2.0,z: 3.0,test1: 3.0,test2: \"Green\",test3: {a: 5,b: 6}}");
127 const Test &test3 = pos->test3();
128 jsongen.clear();
129 result =
130 GenerateTextFromTable(parser, &test3, "MyGame.Example.Test", &jsongen);
131 TEST_EQ(result, true);
132 TEST_EQ_STR(jsongen.c_str(), "{a: 5,b: 6}");
133 const Test *test4 = monster->test4()->Get(0);
134 jsongen.clear();
135 result =
136 GenerateTextFromTable(parser, test4, "MyGame.Example.Test", &jsongen);
137 TEST_EQ(result, true);
138 TEST_EQ_STR(jsongen.c_str(), "{a: 10,b: 20}");
139}
140
Austin Schuh2dd86a92022-09-14 21:19:23 -0700141void MultiFileNameClashTest(const std::string &tests_data_path) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700142 const auto name_clash_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -0700143 flatbuffers::ConCatPathFileName(tests_data_path, "name_clash_test");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700144 const char *include_directories[] = { name_clash_path.c_str() };
145
146 // Load valid 2 file Flatbuffer schema
147 const auto valid_path =
148 flatbuffers::ConCatPathFileName(name_clash_path, "valid_test1.fbs");
149 std::string valid_schema;
150 TEST_ASSERT(flatbuffers::LoadFile(valid_path.c_str(), false, &valid_schema));
151 // Clashing table and union names in different namespaces must be parsable
152 TEST_ASSERT(
153 flatbuffers::Parser().Parse(valid_schema.c_str(), include_directories));
154
155 flatbuffers::Parser p;
156 TEST_ASSERT(p.Parse(valid_schema.c_str(), include_directories));
157
158 // Load invalid 2 file Flatbuffer schema
159 const auto invalid_path =
160 flatbuffers::ConCatPathFileName(name_clash_path, "invalid_test1.fbs");
161 std::string invalid_schema;
162 TEST_ASSERT(
163 flatbuffers::LoadFile(invalid_path.c_str(), false, &invalid_schema));
164 // Clashing table and union names in same namespace must fail to parse
165 TEST_EQ(
166 flatbuffers::Parser().Parse(invalid_schema.c_str(), include_directories),
167 false);
168}
169
Austin Schuh2dd86a92022-09-14 21:19:23 -0700170void InvalidNestedFlatbufferTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700171 // First, load and parse FlatBuffer schema (.fbs)
172 std::string schemafile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700173 TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700174 false, &schemafile),
175 true);
176 auto include_test_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -0700177 flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
178 const char *include_directories[] = { tests_data_path.c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700179 include_test_path.c_str(), nullptr };
180 flatbuffers::Parser parser1;
181 TEST_EQ(parser1.Parse(schemafile.c_str(), include_directories), true);
182
183 // "color" inside nested flatbuffer contains invalid enum value
184 TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: "
185 "\"Leela\", color: \"nonexistent\"}}"),
186 false);
Austin Schuh272c6132020-11-14 16:37:52 -0800187}
188
Austin Schuh2dd86a92022-09-14 21:19:23 -0700189void UnionVectorTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700190 // load FlatBuffer fbs schema and json.
191 std::string schemafile, jsonfile;
192 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700193 (tests_data_path + "union_vector/union_vector.fbs").c_str(),
194 false, &schemafile),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700195 true);
196 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700197 (tests_data_path + "union_vector/union_vector.json").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700198 false, &jsonfile),
199 true);
200
201 // parse schema.
202 flatbuffers::IDLOptions idl_opts;
203 idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
204 flatbuffers::Parser parser(idl_opts);
205 TEST_EQ(parser.Parse(schemafile.c_str()), true);
206
207 flatbuffers::FlatBufferBuilder fbb;
208
209 // union types.
210 std::vector<uint8_t> types;
211 types.push_back(static_cast<uint8_t>(Character_Belle));
212 types.push_back(static_cast<uint8_t>(Character_MuLan));
213 types.push_back(static_cast<uint8_t>(Character_BookFan));
214 types.push_back(static_cast<uint8_t>(Character_Other));
215 types.push_back(static_cast<uint8_t>(Character_Unused));
216
217 // union values.
218 std::vector<flatbuffers::Offset<void>> characters;
219 characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
220 characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
221 characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
222 characters.push_back(fbb.CreateString("Other").Union());
223 characters.push_back(fbb.CreateString("Unused").Union());
224
225 // create Movie.
226 const auto movie_offset =
227 CreateMovie(fbb, Character_Rapunzel,
228 fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
229 fbb.CreateVector(types), fbb.CreateVector(characters));
230 FinishMovieBuffer(fbb, movie_offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700231
Austin Schuh272c6132020-11-14 16:37:52 -0800232 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700233 TEST_EQ(VerifyMovieBuffer(verifier), true);
234
Austin Schuh272c6132020-11-14 16:37:52 -0800235 auto flat_movie = GetMovie(fbb.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700236
237 auto TestMovie = [](const Movie *movie) {
238 TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
239
240 auto cts = movie->characters_type();
241 TEST_EQ(movie->characters_type()->size(), 5);
242 TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
243 TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
244 TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
245 TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
246 TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
247
248 auto rapunzel = movie->main_character_as_Rapunzel();
249 TEST_NOTNULL(rapunzel);
250 TEST_EQ(rapunzel->hair_length(), 6);
251
252 auto cs = movie->characters();
253 TEST_EQ(cs->size(), 5);
254 auto belle = cs->GetAs<BookReader>(0);
255 TEST_EQ(belle->books_read(), 7);
256 auto mu_lan = cs->GetAs<Attacker>(1);
257 TEST_EQ(mu_lan->sword_attack_damage(), 5);
258 auto book_fan = cs->GetAs<BookReader>(2);
259 TEST_EQ(book_fan->books_read(), 2);
260 auto other = cs->GetAsString(3);
261 TEST_EQ_STR(other->c_str(), "Other");
262 auto unused = cs->GetAsString(4);
263 TEST_EQ_STR(unused->c_str(), "Unused");
264 };
265
266 TestMovie(flat_movie);
267
268 // Also test the JSON we loaded above.
269 TEST_EQ(parser.Parse(jsonfile.c_str()), true);
270 auto jbuf = parser.builder_.GetBufferPointer();
271 flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
272 TEST_EQ(VerifyMovieBuffer(jverifier), true);
273 TestMovie(GetMovie(jbuf));
274
275 auto movie_object = flat_movie->UnPack();
276 TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
277 TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
278 TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
279 TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
280 TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
281 TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
282
283 fbb.Clear();
284 fbb.Finish(Movie::Pack(fbb, movie_object));
285
286 delete movie_object;
287
288 auto repacked_movie = GetMovie(fbb.GetBufferPointer());
289
290 TestMovie(repacked_movie);
291
Austin Schuh272c6132020-11-14 16:37:52 -0800292 // Generate text using mini-reflection.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700293 auto s =
294 flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
295 TEST_EQ_STR(
296 s.c_str(),
297 "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
298 "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
299 "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
300 "{ books_read: 2 }, \"Other\", \"Unused\" ] }");
301
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700302 flatbuffers::ToStringVisitor visitor("\n", true, " ");
303 IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor);
Austin Schuh272c6132020-11-14 16:37:52 -0800304 TEST_EQ_STR(visitor.s.c_str(),
305 "{\n"
306 " \"main_character_type\": \"Rapunzel\",\n"
307 " \"main_character\": {\n"
308 " \"hair_length\": 6\n"
309 " },\n"
310 " \"characters_type\": [\n"
311 " \"Belle\",\n"
312 " \"MuLan\",\n"
313 " \"BookFan\",\n"
314 " \"Other\",\n"
315 " \"Unused\"\n"
316 " ],\n"
317 " \"characters\": [\n"
318 " {\n"
319 " \"books_read\": 7\n"
320 " },\n"
321 " {\n"
322 " \"sword_attack_damage\": 5\n"
323 " },\n"
324 " {\n"
325 " \"books_read\": 2\n"
326 " },\n"
327 " \"Other\",\n"
328 " \"Unused\"\n"
329 " ]\n"
330 "}");
331
332 // Generate text using parsed schema.
333 std::string jsongen;
334 auto result = GenerateText(parser, fbb.GetBufferPointer(), &jsongen);
335 TEST_EQ(result, true);
336 TEST_EQ_STR(jsongen.c_str(),
337 "{\n"
338 " main_character_type: \"Rapunzel\",\n"
339 " main_character: {\n"
340 " hair_length: 6\n"
341 " },\n"
342 " characters_type: [\n"
343 " \"Belle\",\n"
344 " \"MuLan\",\n"
345 " \"BookFan\",\n"
346 " \"Other\",\n"
347 " \"Unused\"\n"
348 " ],\n"
349 " characters: [\n"
350 " {\n"
351 " books_read: 7\n"
352 " },\n"
353 " {\n"
354 " sword_attack_damage: 5\n"
355 " },\n"
356 " {\n"
357 " books_read: 2\n"
358 " },\n"
359 " \"Other\",\n"
360 " \"Unused\"\n"
361 " ]\n"
362 "}\n");
363
364 // Simple test with reflection.
365 parser.Serialize();
366 auto schema = reflection::GetSchema(parser.builder_.GetBufferPointer());
367 auto ok = flatbuffers::Verify(*schema, *schema->root_table(),
368 fbb.GetBufferPointer(), fbb.GetSize());
369 TEST_EQ(ok, true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700370
371 flatbuffers::Parser parser2(idl_opts);
372 TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
373 "union Any { Bool }"
374 "table Root { a:Any; }"
Austin Schuh272c6132020-11-14 16:37:52 -0800375 "root_type Root;"),
376 true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700377 TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
378}
379
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700380void EndianSwapTest() {
381 TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
382 TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
383 0x78563412);
384 TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
385 0xEFCDAB9078563412);
386 TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
387}
388
389void UninitializedVectorTest() {
390 flatbuffers::FlatBufferBuilder builder;
391
392 Test *buf = nullptr;
Austin Schuh272c6132020-11-14 16:37:52 -0800393 auto vector_offset =
394 builder.CreateUninitializedVectorOfStructs<Test>(2, &buf);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700395 TEST_NOTNULL(buf);
396 buf[0] = Test(10, 20);
397 buf[1] = Test(30, 40);
398
399 auto required_name = builder.CreateString("myMonster");
400 auto monster_builder = MonsterBuilder(builder);
Austin Schuh272c6132020-11-14 16:37:52 -0800401 monster_builder.add_name(
402 required_name); // required field mandated for monster.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700403 monster_builder.add_test4(vector_offset);
404 builder.Finish(monster_builder.Finish());
405
406 auto p = builder.GetBufferPointer();
407 auto uvt = flatbuffers::GetRoot<Monster>(p);
408 TEST_NOTNULL(uvt);
409 auto vec = uvt->test4();
410 TEST_NOTNULL(vec);
411 auto test_0 = vec->Get(0);
412 auto test_1 = vec->Get(1);
413 TEST_EQ(test_0->a(), 10);
414 TEST_EQ(test_0->b(), 20);
415 TEST_EQ(test_1->a(), 30);
416 TEST_EQ(test_1->b(), 40);
417}
418
419void EqualOperatorTest() {
420 MonsterT a;
421 MonsterT b;
422 TEST_EQ(b == a, true);
423 TEST_EQ(b != a, false);
424
425 b.mana = 33;
426 TEST_EQ(b == a, false);
427 TEST_EQ(b != a, true);
428 b.mana = 150;
429 TEST_EQ(b == a, true);
430 TEST_EQ(b != a, false);
431
432 b.inventory.push_back(3);
433 TEST_EQ(b == a, false);
434 TEST_EQ(b != a, true);
435 b.inventory.clear();
436 TEST_EQ(b == a, true);
437 TEST_EQ(b != a, false);
438
James Kuszmaul8e62b022022-03-22 09:33:25 -0700439 a.enemy.reset(new MonsterT());
440 TEST_EQ(b != a, true);
441 a.enemy->mana = 33;
442 TEST_EQ(b == a, false);
443 TEST_EQ(b != a, true);
444
445 b.enemy.reset(new MonsterT());
446 TEST_EQ(b == a, false);
447 TEST_EQ(b != a, true);
448 b.enemy->mana = 33;
449 TEST_EQ(b == a, true);
450 TEST_EQ(b != a, false);
451
452 a.enemy.reset(nullptr);
453 TEST_EQ(b == a, false);
454 TEST_EQ(b != a, true);
455 b.enemy->mana = 150;
456 TEST_EQ(b == a, false);
457 TEST_EQ(b != a, true);
458 a.enemy.reset(new MonsterT());
459 TEST_EQ(b == a, true);
460 TEST_EQ(b != a, false);
461
462 b.enemy.reset(nullptr);
463
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700464 b.test.type = Any_Monster;
465 TEST_EQ(b == a, false);
466 TEST_EQ(b != a, true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700467
Austin Schuh2dd86a92022-09-14 21:19:23 -0700468 // Test that vector of tables are compared by value and not by reference.
469 {
470 // Two tables are equal by default.
471 MonsterT a, b;
472 TEST_EQ(a == b, true);
473
474 // Adding only a table to one of the monster vectors should make it not
475 // equal (due to size mistmatch).
476 a.testarrayoftables.push_back(
477 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
478 TEST_EQ(a == b, false);
479
480 // Adding an equalivant table to the other monster vector should make it
481 // equal again.
482 b.testarrayoftables.push_back(
483 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
484 TEST_EQ(a == b, true);
485
486 // Create two new monsters that are different.
487 auto c = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
488 auto d = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
489 c->hp = 1;
490 d->hp = 2;
491 TEST_EQ(c == d, false);
492
493 // Adding them to the original monsters should also make them different.
494 a.testarrayoftables.push_back(std::move(c));
495 b.testarrayoftables.push_back(std::move(d));
496 TEST_EQ(a == b, false);
497
498 // Remove the mismatching monsters to get back to equality
499 a.testarrayoftables.pop_back();
500 b.testarrayoftables.pop_back();
501 TEST_EQ(a == b, true);
502
503 // Check that nullptr are OK.
504 a.testarrayoftables.push_back(nullptr);
505 b.testarrayoftables.push_back(
506 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
507 TEST_EQ(a == b, false);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700508 }
509}
510
511void CreateSharedStringTest() {
512 flatbuffers::FlatBufferBuilder builder;
513 const auto one1 = builder.CreateSharedString("one");
514 const auto two = builder.CreateSharedString("two");
515 const auto one2 = builder.CreateSharedString("one");
516 TEST_EQ(one1.o, one2.o);
517 const auto onetwo = builder.CreateSharedString("onetwo");
518 TEST_EQ(onetwo.o != one1.o, true);
519 TEST_EQ(onetwo.o != two.o, true);
520
521 // Support for embedded nulls
Austin Schuh272c6132020-11-14 16:37:52 -0800522 const char chars_b[] = { 'a', '\0', 'b' };
523 const char chars_c[] = { 'a', '\0', 'c' };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700524 const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b));
525 const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c));
526 const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b));
Austin Schuh272c6132020-11-14 16:37:52 -0800527 TEST_EQ(null_b1.o != null_c.o, true); // Issue#5058 repro
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700528 TEST_EQ(null_b1.o, null_b2.o);
529
530 // Put the strings into an array for round trip verification.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700531 std::array<flatbuffers::Offset<flatbuffers::String>, 7> array = {
Austin Schuh272c6132020-11-14 16:37:52 -0800532 one1, two, one2, onetwo, null_b1, null_c, null_b2
533 };
534 const auto vector_offset =
James Kuszmaul8e62b022022-03-22 09:33:25 -0700535 builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(array);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700536 MonsterBuilder monster_builder(builder);
537 monster_builder.add_name(two);
538 monster_builder.add_testarrayofstring(vector_offset);
539 builder.Finish(monster_builder.Finish());
540
541 // Read the Monster back.
Austin Schuh272c6132020-11-14 16:37:52 -0800542 const auto *monster =
543 flatbuffers::GetRoot<Monster>(builder.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700544 TEST_EQ_STR(monster->name()->c_str(), "two");
545 const auto *testarrayofstring = monster->testarrayofstring();
546 TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7));
547 const auto &a = *testarrayofstring;
548 TEST_EQ_STR(a[0]->c_str(), "one");
549 TEST_EQ_STR(a[1]->c_str(), "two");
550 TEST_EQ_STR(a[2]->c_str(), "one");
551 TEST_EQ_STR(a[3]->c_str(), "onetwo");
552 TEST_EQ(a[4]->str(), (std::string(chars_b, sizeof(chars_b))));
553 TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c))));
554 TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b))));
555
Austin Schuh272c6132020-11-14 16:37:52 -0800556 // Make sure String::operator< works, too, since it is related to
557 // StringOffsetCompare.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700558 TEST_EQ((*a[0]) < (*a[1]), true);
559 TEST_EQ((*a[1]) < (*a[0]), false);
560 TEST_EQ((*a[1]) < (*a[2]), false);
561 TEST_EQ((*a[2]) < (*a[1]), true);
562 TEST_EQ((*a[4]) < (*a[3]), true);
563 TEST_EQ((*a[5]) < (*a[4]), false);
564 TEST_EQ((*a[5]) < (*a[4]), false);
565 TEST_EQ((*a[6]) < (*a[5]), true);
566}
567
Austin Schuh2dd86a92022-09-14 21:19:23 -0700568#if !defined(FLATBUFFERS_USE_STD_SPAN) && !defined(FLATBUFFERS_SPAN_MINIMAL)
Austin Schuh272c6132020-11-14 16:37:52 -0800569void FlatbuffersSpanTest() {
570 // Compile-time checking of non-const [] to const [] conversions.
Austin Schuh2dd86a92022-09-14 21:19:23 -0700571 using flatbuffers::internal::is_span_convertible;
572 (void)is_span_convertible<int, 1, int, 1>::type(123);
573 (void)is_span_convertible<const int, 1, int, 1>::type(123);
574 (void)is_span_convertible<const int64_t, 1, int64_t, 1>::type(123);
575 (void)is_span_convertible<const uint64_t, 1, uint64_t, 1>::type(123);
576 (void)is_span_convertible<const int, 1, const int, 1>::type(123);
577 (void)is_span_convertible<const int64_t, 1, const int64_t, 1>::type(123);
578 (void)is_span_convertible<const uint64_t, 1, const uint64_t, 1>::type(123);
Austin Schuh272c6132020-11-14 16:37:52 -0800579
580 using flatbuffers::span;
581 span<char, 0> c1;
582 TEST_EQ(c1.size(), 0);
583 span<char, flatbuffers::dynamic_extent> c2;
584 TEST_EQ(c2.size(), 0);
585 span<char> c3;
586 TEST_EQ(c3.size(), 0);
587 TEST_ASSERT(c1.empty() && c2.empty() && c3.empty());
588
589 int i_data7[7] = { 0, 1, 2, 3, 4, 5, 6 };
590 span<int, 7> i1(&i_data7[0], 7);
591 span<int> i2(i1); // make dynamic from static
592 TEST_EQ(i1.size(), 7);
593 TEST_EQ(i1.empty(), false);
594 TEST_EQ(i1.size(), i2.size());
595 TEST_EQ(i1.data(), i_data7);
596 TEST_EQ(i1[2], 2);
597 // Make const span from a non-const one.
598 span<const int, 7> i3(i1);
599 // Construct from a C-array.
600 span<int, 7> i4(i_data7);
601 span<const int, 7> i5(i_data7);
602 span<int> i6(i_data7);
603 span<const int> i7(i_data7);
604 TEST_EQ(i7.size(), 7);
605 // Check construction from a const array.
606 const int i_cdata5[5] = { 4, 3, 2, 1, 0 };
607 span<const int, 5> i8(i_cdata5);
608 span<const int> i9(i_cdata5);
609 TEST_EQ(i9.size(), 5);
610 // Construction from a (ptr, size) pair.
611 span<int, 7> i10(i_data7, 7);
612 span<int> i11(i_data7, 7);
613 TEST_EQ(i11.size(), 7);
614 span<const int, 5> i12(i_cdata5, 5);
615 span<const int> i13(i_cdata5, 5);
616 TEST_EQ(i13.size(), 5);
617 // Construction from std::array.
618 std::array<int, 6> i_arr6 = { { 0, 1, 2, 3, 4, 5 } };
619 span<int, 6> i14(i_arr6);
620 span<const int, 6> i15(i_arr6);
621 span<int> i16(i_arr6);
622 span<const int> i17(i_arr6);
623 TEST_EQ(i17.size(), 6);
624 const std::array<int, 8> i_carr8 = { { 0, 1, 2, 3, 4, 5, 6, 7 } };
625 span<const int, 8> i18(i_carr8);
626 span<const int> i19(i_carr8);
627 TEST_EQ(i18.size(), 8);
628 TEST_EQ(i19.size(), 8);
629 TEST_EQ(i19[7], 7);
630 // Check compatibility with flatbuffers::Array.
631 int fbs_int3_underlaying[3] = { 0 };
632 int fbs_int3_data[3] = { 1, 2, 3 };
633 auto &fbs_int3 = flatbuffers::CastToArray(fbs_int3_underlaying);
634 fbs_int3.CopyFromSpan(fbs_int3_data);
635 TEST_EQ(fbs_int3.Get(1), 2);
636 const int fbs_cint3_data[3] = { 2, 3, 4 };
637 fbs_int3.CopyFromSpan(fbs_cint3_data);
638 TEST_EQ(fbs_int3.Get(1), 3);
639 // Check with Array<Enum, N>
640 enum class Dummy : uint16_t { Zero = 0, One, Two };
641 Dummy fbs_dummy3_underlaying[3] = {};
642 Dummy fbs_dummy3_data[3] = { Dummy::One, Dummy::Two, Dummy::Two };
643 auto &fbs_dummy3 = flatbuffers::CastToArray(fbs_dummy3_underlaying);
644 fbs_dummy3.CopyFromSpan(fbs_dummy3_data);
645 TEST_EQ(fbs_dummy3.Get(1), Dummy::Two);
646}
647#else
648void FlatbuffersSpanTest() {}
649#endif
650
James Kuszmaul8e62b022022-03-22 09:33:25 -0700651// VS10 does not support typed enums, exclude from tests
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700652#if !defined(_MSC_VER) || _MSC_VER >= 1700
James Kuszmaul8e62b022022-03-22 09:33:25 -0700653void FixedLengthArrayTest() {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700654 // Generate an ArrayTable containing one ArrayStruct.
655 flatbuffers::FlatBufferBuilder fbb;
656 MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
657 TEST_NOTNULL(nStruct0.mutable_a());
658 nStruct0.mutable_a()->Mutate(0, 1);
659 nStruct0.mutable_a()->Mutate(1, 2);
660 TEST_NOTNULL(nStruct0.mutable_c());
661 nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
662 nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
Austin Schuh272c6132020-11-14 16:37:52 -0800663 TEST_NOTNULL(nStruct0.mutable_d());
664 nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
665 nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700666 MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
667 TEST_NOTNULL(nStruct1.mutable_a());
668 nStruct1.mutable_a()->Mutate(0, 3);
669 nStruct1.mutable_a()->Mutate(1, 4);
670 TEST_NOTNULL(nStruct1.mutable_c());
671 nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
672 nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
Austin Schuh272c6132020-11-14 16:37:52 -0800673 TEST_NOTNULL(nStruct1.mutable_d());
674 nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
675 nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
676 MyGame::Example::ArrayStruct aStruct(2, 12, 1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700677 TEST_NOTNULL(aStruct.b());
678 TEST_NOTNULL(aStruct.mutable_b());
679 TEST_NOTNULL(aStruct.mutable_d());
Austin Schuh272c6132020-11-14 16:37:52 -0800680 TEST_NOTNULL(aStruct.mutable_f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700681 for (int i = 0; i < aStruct.b()->size(); i++)
682 aStruct.mutable_b()->Mutate(i, i + 1);
683 aStruct.mutable_d()->Mutate(0, nStruct0);
684 aStruct.mutable_d()->Mutate(1, nStruct1);
685 auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
Austin Schuh272c6132020-11-14 16:37:52 -0800686 MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700687 // Verify correctness of the ArrayTable.
688 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
James Kuszmaul8e62b022022-03-22 09:33:25 -0700689 TEST_ASSERT(MyGame::Example::VerifyArrayTableBuffer(verifier));
690 // Do test.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700691 auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
692 auto mArStruct = p->mutable_a();
693 TEST_NOTNULL(mArStruct);
694 TEST_NOTNULL(mArStruct->b());
695 TEST_NOTNULL(mArStruct->d());
Austin Schuh272c6132020-11-14 16:37:52 -0800696 TEST_NOTNULL(mArStruct->f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700697 TEST_NOTNULL(mArStruct->mutable_b());
698 TEST_NOTNULL(mArStruct->mutable_d());
Austin Schuh272c6132020-11-14 16:37:52 -0800699 TEST_NOTNULL(mArStruct->mutable_f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700700 TEST_EQ(mArStruct->a(), 2);
701 TEST_EQ(mArStruct->b()->size(), 15);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700702 mArStruct->mutable_b()->Mutate(14, -14);
703 TEST_EQ(mArStruct->b()->Get(14), -14);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700704 TEST_EQ(mArStruct->c(), 12);
Austin Schuh272c6132020-11-14 16:37:52 -0800705 TEST_NOTNULL(mArStruct->d()->Get(0));
706 TEST_NOTNULL(mArStruct->d()->Get(0)->a());
707 TEST_EQ(mArStruct->d()->Get(0)->a()->Get(0), 1);
708 TEST_EQ(mArStruct->d()->Get(0)->a()->Get(1), 2);
709 TEST_NOTNULL(mArStruct->d()->Get(1));
710 TEST_NOTNULL(mArStruct->d()->Get(1)->a());
711 TEST_EQ(mArStruct->d()->Get(1)->a()->Get(0), 3);
712 TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 4);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700713 TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
714 TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
715 mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
Austin Schuh272c6132020-11-14 16:37:52 -0800716 TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1));
717 TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b());
718 TEST_NOTNULL(mArStruct->d()->Get(0)->c());
719 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0));
720 TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1));
721 TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
722 mArStruct->d()->Get(0)->d()->Get(0));
723 TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
724 mArStruct->d()->Get(0)->d()->Get(1));
725 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b());
726 TEST_NOTNULL(mArStruct->d()->Get(1)->c());
727 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0));
728 TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1));
729 TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
730 mArStruct->d()->Get(1)->d()->Get(0));
731 TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
732 mArStruct->d()->Get(1)->d()->Get(1));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700733 for (int i = 0; i < mArStruct->b()->size() - 1; i++)
734 TEST_EQ(mArStruct->b()->Get(i), i + 1);
Austin Schuh272c6132020-11-14 16:37:52 -0800735 // Check alignment
736 TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->d()) % 8);
737 TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->f()) % 8);
738
739 // Check if default constructor set all memory zero
740 const size_t arr_size = sizeof(MyGame::Example::ArrayStruct);
741 char non_zero_memory[arr_size];
742 // set memory chunk of size ArrayStruct to 1's
743 std::memset(static_cast<void *>(non_zero_memory), 1, arr_size);
744 // after placement-new it should be all 0's
James Kuszmaul8e62b022022-03-22 09:33:25 -0700745# if defined(_MSC_VER) && defined(_DEBUG)
746# undef new
747# endif
748 MyGame::Example::ArrayStruct *ap =
749 new (non_zero_memory) MyGame::Example::ArrayStruct;
750# if defined(_MSC_VER) && defined(_DEBUG)
751# define new DEBUG_NEW
752# endif
Austin Schuh272c6132020-11-14 16:37:52 -0800753 (void)ap;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700754 for (size_t i = 0; i < arr_size; ++i) { TEST_EQ(non_zero_memory[i], 0); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700755}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700756#else
757void FixedLengthArrayTest() {}
758#endif // !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700759
James Kuszmaul8e62b022022-03-22 09:33:25 -0700760#if !defined(FLATBUFFERS_SPAN_MINIMAL) && \
761 (!defined(_MSC_VER) || _MSC_VER >= 1700)
Austin Schuh272c6132020-11-14 16:37:52 -0800762void FixedLengthArrayConstructorTest() {
763 const int32_t nested_a[2] = { 1, 2 };
764 MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A,
765 MyGame::Example::TestEnum::B };
766 const int64_t int64_2[2] = { -2, -1 };
767
768 std::array<MyGame::Example::NestedStruct, 2> init_d = {
769 { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
770 nested_c, int64_2),
771 MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::A,
772 nested_c,
773 std::array<int64_t, 2>{ { 12, 13 } }) }
774 };
775
776 MyGame::Example::ArrayStruct arr_struct(
777 8.125,
778 std::array<int32_t, 0xF>{
779 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
780 -17, init_d, 10, int64_2);
781 TEST_EQ(arr_struct.a(), 8.125);
782 TEST_EQ(arr_struct.b()->Get(2), 3);
783 TEST_EQ(arr_struct.c(), -17);
784
785 TEST_NOTNULL(arr_struct.d());
786 const auto &arr_d_0 = *arr_struct.d()->Get(0);
787 TEST_EQ(arr_d_0.a()->Get(0), 1);
788 TEST_EQ(arr_d_0.a()->Get(1), 2);
789 TEST_EQ(arr_d_0.b(), MyGame::Example::TestEnum::B);
790 TEST_EQ(arr_d_0.c()->Get(0), MyGame::Example::TestEnum::A);
791 TEST_EQ(arr_d_0.c()->Get(1), MyGame::Example::TestEnum::B);
792 TEST_EQ(arr_d_0.d()->Get(0), -2);
793 TEST_EQ(arr_d_0.d()->Get(1), -1);
794 const auto &arr_d_1 = *arr_struct.d()->Get(1);
795 TEST_EQ(arr_d_1.a()->Get(0), 1);
796 TEST_EQ(arr_d_1.a()->Get(1), 2);
797 TEST_EQ(arr_d_1.b(), MyGame::Example::TestEnum::A);
798 TEST_EQ(arr_d_1.c()->Get(0), MyGame::Example::TestEnum::A);
799 TEST_EQ(arr_d_1.c()->Get(1), MyGame::Example::TestEnum::B);
800 TEST_EQ(arr_d_1.d()->Get(0), 12);
801 TEST_EQ(arr_d_1.d()->Get(1), 13);
802
803 TEST_EQ(arr_struct.e(), 10);
804 TEST_EQ(arr_struct.f()->Get(0), -2);
805 TEST_EQ(arr_struct.f()->Get(1), -1);
806}
807#else
James Kuszmaul8e62b022022-03-22 09:33:25 -0700808void FixedLengthArrayConstructorTest() {}
Austin Schuh272c6132020-11-14 16:37:52 -0800809#endif
810
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700811void NativeTypeTest() {
812 const int N = 3;
813
814 Geometry::ApplicationDataT src_data;
815 src_data.vectors.reserve(N);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700816 src_data.vectors_alt.reserve(N);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700817
818 for (int i = 0; i < N; ++i) {
Austin Schuh272c6132020-11-14 16:37:52 -0800819 src_data.vectors.push_back(
820 Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700821 src_data.vectors_alt.push_back(
822 Native::Vector3D(20 * i + 0.1f, 20 * i + 0.2f, 20 * i + 0.3f));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700823 }
824
825 flatbuffers::FlatBufferBuilder fbb;
826 fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data));
827
Austin Schuh272c6132020-11-14 16:37:52 -0800828 auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700829
830 for (int i = 0; i < N; ++i) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700831 const Native::Vector3D &v = dstDataT->vectors[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700832 TEST_EQ(v.x, 10 * i + 0.1f);
833 TEST_EQ(v.y, 10 * i + 0.2f);
834 TEST_EQ(v.z, 10 * i + 0.3f);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700835
836 const Native::Vector3D &v2 = dstDataT->vectors_alt[i];
837 TEST_EQ(v2.x, 20 * i + 0.1f);
838 TEST_EQ(v2.y, 20 * i + 0.2f);
839 TEST_EQ(v2.z, 20 * i + 0.3f);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700840 }
841}
842
James Kuszmaul8e62b022022-03-22 09:33:25 -0700843// VS10 does not support typed enums, exclude from tests
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700844#if !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuh2dd86a92022-09-14 21:19:23 -0700845void FixedLengthArrayJsonTest(const std::string &tests_data_path, bool binary) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700846 // load FlatBuffer schema (.fbs) and JSON from disk
847 std::string schemafile;
848 std::string jsonfile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700849 TEST_EQ(flatbuffers::LoadFile(
850 (tests_data_path + "arrays_test." + (binary ? "bfbs" : "fbs"))
851 .c_str(),
852 binary, &schemafile),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700853 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700854 TEST_EQ(
855 flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
856 false, &jsonfile),
857 true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700858
859 // parse schema first, so we can use it to parse the data after
860 flatbuffers::Parser parserOrg, parserGen;
861 if (binary) {
862 flatbuffers::Verifier verifier(
863 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
864 schemafile.size());
865 TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700866 TEST_EQ(parserOrg.Deserialize(
867 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
868 schemafile.size()),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700869 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700870 TEST_EQ(parserGen.Deserialize(
871 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
872 schemafile.size()),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700873 true);
874 } else {
875 TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
876 TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
877 }
878 TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
879
880 // First, verify it, just in case:
881 flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
882 parserOrg.builder_.GetSize());
883 TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
884
885 // Export to JSON
886 std::string jsonGen;
887 TEST_EQ(
888 GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
889 true);
890
891 // Import from JSON
892 TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
893
894 // Verify buffer from generated JSON
895 flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
896 parserGen.builder_.GetSize());
897 TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
898
899 // Compare generated buffer to original
900 TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
901 TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
902 parserGen.builder_.GetBufferPointer(),
903 parserOrg.builder_.GetSize()),
904 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700905}
906
Austin Schuh2dd86a92022-09-14 21:19:23 -0700907void FixedLengthArraySpanTest(const std::string &tests_data_path) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700908 // load FlatBuffer schema (.fbs) and JSON from disk
909 std::string schemafile;
910 std::string jsonfile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700911 TEST_EQ(flatbuffers::LoadFile((tests_data_path + "arrays_test.fbs").c_str(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700912 false, &schemafile),
913 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700914 TEST_EQ(
915 flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
916 false, &jsonfile),
917 true);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700918
919 // parse schema first, so we can use it to parse the data after
920 flatbuffers::Parser parser;
921 TEST_EQ(parser.Parse(schemafile.c_str()), true);
922 TEST_EQ(parser.Parse(jsonfile.c_str()), true);
923 auto &fbb = parser.builder_;
924 auto verifier = flatbuffers::Verifier(fbb.GetBufferPointer(), fbb.GetSize());
925 TEST_EQ(true, VerifyArrayTableBuffer(verifier));
926
927 auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
928 TEST_NOTNULL(p);
929 auto table_struct = p->mutable_a();
930 TEST_NOTNULL(table_struct);
931 TEST_EQ(2, table_struct->d()->size());
932 TEST_NOTNULL(table_struct->d());
933 TEST_NOTNULL(table_struct->mutable_d());
934 // test array of structs
935 auto const_d = flatbuffers::make_span(*table_struct->d());
936 auto mutable_d = flatbuffers::make_span(*table_struct->mutable_d());
937 TEST_EQ(2, const_d.size());
938 TEST_EQ(2, mutable_d.size());
939 TEST_ASSERT(const_d[0] == mutable_d[0]);
940 TEST_ASSERT(const_d[1] == mutable_d[1]);
941 mutable_d[0] = const_d[0]; // mutate
942 // test scalars
943 auto &const_nested = const_d[0];
944 auto &mutable_nested = mutable_d[0];
945 static_assert(sizeof(MyGame::Example::TestEnum) == sizeof(uint8_t),
946 "TestEnum's underlaying type must by byte");
947 TEST_NOTNULL(const_nested.d());
948 TEST_NOTNULL(mutable_nested.d());
949 {
950 flatbuffers::span<const MyGame::Example::TestEnum, 2> const_d_c =
951 flatbuffers::make_span(*const_nested.c());
952 auto mutable_d_c = flatbuffers::make_span(*mutable_nested.mutable_c());
953 TEST_EQ(2, const_d_c.size());
954 TEST_EQ(2, mutable_d_c.size());
955 TEST_EQ(MyGame::Example::TestEnum::C, const_d_c[0]);
956 TEST_EQ(MyGame::Example::TestEnum::B, const_d_c[1]);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700957 TEST_ASSERT(mutable_d_c.end() == std::copy(const_d_c.begin(),
958 const_d_c.end(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700959 mutable_d_c.begin()));
960 TEST_ASSERT(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700961 std::equal(const_d_c.begin(), const_d_c.end(), mutable_d_c.begin()));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700962 }
963 // test little endian array of int32
964# if FLATBUFFERS_LITTLEENDIAN
965 {
966 flatbuffers::span<const int32_t, 2> const_d_a =
967 flatbuffers::make_span(*const_nested.a());
968 auto mutable_d_a = flatbuffers::make_span(*mutable_nested.mutable_a());
969 TEST_EQ(2, const_d_a.size());
970 TEST_EQ(2, mutable_d_a.size());
971 TEST_EQ(-1, const_d_a[0]);
972 TEST_EQ(2, const_d_a[1]);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700973 TEST_ASSERT(mutable_d_a.end() == std::copy(const_d_a.begin(),
974 const_d_a.end(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700975 mutable_d_a.begin()));
976 TEST_ASSERT(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700977 std::equal(const_d_a.begin(), const_d_a.end(), mutable_d_a.begin()));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700978 }
979# endif
980}
981#else
982void FixedLengthArrayJsonTest(bool /*binary*/) {}
983void FixedLengthArraySpanTest() {}
984#endif
985
Austin Schuh2dd86a92022-09-14 21:19:23 -0700986void TestEmbeddedBinarySchema(const std::string &tests_data_path) {
Austin Schuh272c6132020-11-14 16:37:52 -0800987 // load JSON from disk
988 std::string jsonfile;
989 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700990 (tests_data_path + "monsterdata_test.golden").c_str(), false,
Austin Schuh272c6132020-11-14 16:37:52 -0800991 &jsonfile),
992 true);
993
994 // parse schema first, so we can use it to parse the data after
995 flatbuffers::Parser parserOrg, parserGen;
996 flatbuffers::Verifier verifier(MyGame::Example::MonsterBinarySchema::data(),
997 MyGame::Example::MonsterBinarySchema::size());
998 TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
999 TEST_EQ(parserOrg.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1000 MyGame::Example::MonsterBinarySchema::size()),
1001 true);
1002 TEST_EQ(parserGen.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1003 MyGame::Example::MonsterBinarySchema::size()),
1004 true);
1005 TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
1006
1007 // First, verify it, just in case:
1008 flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
1009 parserOrg.builder_.GetSize());
1010 TEST_EQ(VerifyMonsterBuffer(verifierOrg), true);
1011
1012 // Export to JSON
1013 std::string jsonGen;
1014 TEST_EQ(
1015 GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
1016 true);
1017
1018 // Import from JSON
1019 TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
1020
1021 // Verify buffer from generated JSON
1022 flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
1023 parserGen.builder_.GetSize());
1024 TEST_EQ(VerifyMonsterBuffer(verifierGen), true);
1025
1026 // Compare generated buffer to original
1027 TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
1028 TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
1029 parserGen.builder_.GetBufferPointer(),
1030 parserOrg.builder_.GetSize()),
1031 0);
1032}
1033
Austin Schuh2dd86a92022-09-14 21:19:23 -07001034void NestedVerifierTest() {
1035 // Create a nested monster.
1036 flatbuffers::FlatBufferBuilder nested_builder;
1037 FinishMonsterBuffer(
1038 nested_builder,
1039 CreateMonster(nested_builder, nullptr, 0, 0,
1040 nested_builder.CreateString("NestedMonster")));
James Kuszmaul8e62b022022-03-22 09:33:25 -07001041
Austin Schuh2dd86a92022-09-14 21:19:23 -07001042 // Verify the nested monster
1043 flatbuffers::Verifier verifier(nested_builder.GetBufferPointer(),
1044 nested_builder.GetSize());
1045 TEST_EQ(true, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001046
Austin Schuh272c6132020-11-14 16:37:52 -08001047 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001048 // Create the outer monster.
1049 flatbuffers::FlatBufferBuilder builder;
1050
1051 // Add the nested monster as a vector of bytes.
1052 auto nested_monster_bytes = builder.CreateVector(
1053 nested_builder.GetBufferPointer(), nested_builder.GetSize());
1054
1055 auto name = builder.CreateString("OuterMonster");
1056
1057 MonsterBuilder mon_builder(builder);
1058 mon_builder.add_name(name);
1059 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1060 FinishMonsterBuffer(builder, mon_builder.Finish());
1061
1062 // Verify the root monster, which includes verifing the nested monster
1063 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1064 builder.GetSize());
1065 TEST_EQ(true, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001066 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001067
Austin Schuh272c6132020-11-14 16:37:52 -08001068 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001069 // Create the outer monster.
1070 flatbuffers::FlatBufferBuilder builder;
1071
1072 // Purposely invalidate the nested flatbuffer setting its length to 1, an
1073 // invalid length.
1074 uint8_t invalid_nested_buffer[1];
1075 auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 1);
1076
1077 auto name = builder.CreateString("OuterMonster");
1078
1079 MonsterBuilder mon_builder(builder);
1080 mon_builder.add_name(name);
1081 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1082 FinishMonsterBuffer(builder, mon_builder.Finish());
1083
1084 // Verify the root monster fails, since the included nested monster fails.
1085 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1086 builder.GetSize());
1087 TEST_EQ(false, VerifyMonsterBuffer(verifier));
1088
1089 // Verify the root monster succeeds, since we've disabled checking nested
1090 // flatbuffers
1091 flatbuffers::Verifier::Options options;
1092 options.check_nested_flatbuffers = false;
1093 flatbuffers::Verifier no_check_nested(builder.GetBufferPointer(),
1094 builder.GetSize(), options);
1095 TEST_EQ(true, VerifyMonsterBuffer(no_check_nested));
Austin Schuh272c6132020-11-14 16:37:52 -08001096 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001097
Austin Schuh272c6132020-11-14 16:37:52 -08001098 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001099 // Create the outer monster.
1100 flatbuffers::FlatBufferBuilder builder;
1101
1102 // Purposely invalidate the nested flatbuffer setting its length to 0, an
1103 // invalid length.
1104 uint8_t *invalid_nested_buffer = nullptr;
1105 auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 0);
1106
1107 auto name = builder.CreateString("OuterMonster");
1108
1109 MonsterBuilder mon_builder(builder);
1110 mon_builder.add_name(name);
1111 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1112 FinishMonsterBuffer(builder, mon_builder.Finish());
1113
1114 // Verify the root monster fails, since the included nested monster fails.
1115 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1116 builder.GetSize());
1117 TEST_EQ(false, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001118 }
1119}
1120
James Kuszmaul8e62b022022-03-22 09:33:25 -07001121template<class T, class Container>
1122void TestIterators(const std::vector<T> &expected, const Container &tested) {
1123 TEST_ASSERT(tested.rbegin().base() == tested.end());
1124 TEST_ASSERT(tested.crbegin().base() == tested.cend());
1125 TEST_ASSERT(tested.rend().base() == tested.begin());
1126 TEST_ASSERT(tested.crend().base() == tested.cbegin());
1127
1128 size_t k = 0;
1129 for (auto it = tested.begin(); it != tested.end(); ++it, ++k) {
1130 const auto &e = expected.at(k);
1131 TEST_EQ(*it, e);
1132 }
1133 TEST_EQ(k, expected.size());
1134
1135 k = expected.size();
1136 for (auto it = tested.rbegin(); it != tested.rend(); ++it, --k) {
1137 const auto &e = expected.at(k - 1);
1138 TEST_EQ(*it, e);
1139 }
1140 TEST_EQ(k, 0);
1141}
1142
1143void FlatbuffersIteratorsTest() {
1144 {
1145 flatbuffers::FlatBufferBuilder fbb;
1146 const std::vector<unsigned char> inv_data = { 1, 2, 3 };
1147 {
1148 auto mon_name = fbb.CreateString("MyMonster"); // key, mandatory
1149 auto inv_vec = fbb.CreateVector(inv_data);
1150 auto empty_i64_vec =
1151 fbb.CreateVector(static_cast<const int64_t *>(nullptr), 0);
1152 MonsterBuilder mb(fbb);
1153 mb.add_name(mon_name);
1154 mb.add_inventory(inv_vec);
1155 mb.add_vector_of_longs(empty_i64_vec);
1156 FinishMonsterBuffer(fbb, mb.Finish());
1157 }
1158 const auto &mon = *flatbuffers::GetRoot<Monster>(fbb.GetBufferPointer());
1159
1160 TEST_EQ_STR("MyMonster", mon.name()->c_str());
1161 TEST_ASSERT(mon.inventory());
1162 TEST_ASSERT(mon.vector_of_longs());
1163 TestIterators(inv_data, *mon.inventory());
1164 TestIterators(std::vector<int64_t>(), *mon.vector_of_longs());
1165 }
1166
1167 {
1168 flatbuffers::FlatBufferBuilder fbb;
1169 MyGame::Example::ArrayStruct aStruct;
1170 MyGame::Example::FinishArrayTableBuffer(
1171 fbb, MyGame::Example::CreateArrayTable(fbb, &aStruct));
1172 const auto &array_table =
1173 *flatbuffers::GetRoot<ArrayTable>(fbb.GetBufferPointer());
1174 TEST_ASSERT(array_table.a());
1175 auto &int_15 = *array_table.a()->b();
1176 TestIterators(std::vector<int>(15, 0), int_15);
1177 }
1178}
James Kuszmaul8e62b022022-03-22 09:33:25 -07001179
Austin Schuh2dd86a92022-09-14 21:19:23 -07001180void PrivateAnnotationsLeaks() {
1181 // Simple schemas and a "has optional scalar" sentinal.
1182 std::vector<std::string> schemas;
1183 std::vector<std::string> failure_schemas;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001184
Austin Schuh2dd86a92022-09-14 21:19:23 -07001185 // (private) (table/struct)
1186 schemas.push_back(
1187 "table Monster (private) { mana: int; }"
1188 "struct ABC (private) { mana: int; }");
1189
1190 // (public) (table/struct)
1191 schemas.push_back(
1192 "table Monster { mana: int; }"
1193 "struct ABC { mana: int; }");
1194
1195 // (private) (union) containing (private) (table/struct)
1196 schemas.push_back(
1197 "table Monster (private) { mana: int; } "
1198 "struct ABC (private) { mana: int; } "
1199 "union Any (private) { Monster, ABC } ");
1200
1201 // (public) (union) containing (public) (table/struct)
1202 schemas.push_back(
1203 "table Monster { mana: int; }"
1204 "struct ABC { mana: int; }"
1205 "union Any { Monster, ABC }");
1206
1207 // (private) (table/struct/enum)
1208 schemas.push_back(
1209 "table Monster (private) { mana: int; }"
1210 "struct ABC (private) { mana: int; }"
1211 "enum Race:byte (private) { None = -1, Human = 0, }");
1212
1213 // (public) (table/struct/enum)
1214 schemas.push_back(
1215 "table Monster { mana: int; }"
1216 "struct ABC { mana: int; }"
1217 "enum Race:byte { None = -1, Human = 0, }");
1218
1219 // (private) (union) containing (private) (table/struct)
1220 schemas.push_back(
1221 "table Monster (private) { mana: int; }"
1222 "struct ABC (private) { mana: int; }"
1223 "enum Race:byte (private) { None = -1, Human = 0, }"
1224 "union Any (private) { Monster, ABC }");
1225
1226 // (public) (union) containing (public) (table/struct)
1227 schemas.push_back(
1228 "table Monster { mana: int; }"
1229 "struct ABC { mana: int; }"
1230 "enum Race:byte { None = -1, Human = 0, }"
1231 "union Any { Monster, ABC }");
1232
1233 // (private) (table), (public struct)
1234 schemas.push_back(
1235 "table Monster (private) { mana: int; }"
1236 "struct ABC { mana: int; }");
1237
1238 // (private) (table), (public) (struct/enum)
1239 schemas.push_back(
1240 "table Monster (private) { mana: int; }"
1241 "struct ABC { mana: int; }"
1242 "enum Race:byte { None = -1, Human = 0, }");
1243
1244 // (public) (struct) containing (public) (enum)
1245 schemas.push_back(
1246 "enum Race:byte { None = -1, Human = 0, }"
1247 "table Monster { mana: int; }"
1248 "struct ABC { mana: int; type: Race; }");
1249
1250 // (public) (union) containing (private) (table) & (public) (struct)
1251 failure_schemas.push_back(
1252 "table Monster (private) { mana: int; }"
1253 "struct ABC { mana: int; }"
1254 "union Any { Monster, ABC }");
1255
1256 // (public) (union) containing (private) (table/struct)
1257 failure_schemas.push_back(
1258 "table Monster (private) { mana: int; }"
1259 "struct ABC (private) { mana: int; }"
1260 "enum Race:byte { None = -1, Human = 0, }"
1261 "union Any { Monster, ABC }");
1262
1263 // (public) (table) containing (private) (struct)
1264 failure_schemas.push_back(
1265 "table Monster { mana: int; ab: ABC; }"
1266 "struct ABC (private) { mana: int; }");
1267
1268 // (public) (struct) containing (private) (enum)
1269 failure_schemas.push_back(
1270 "enum Race:byte (private) { None = -1, Human = 0, }"
1271 "table Monster { mana: int; }"
1272 "struct ABC { mana: int; type: Race; }");
1273
1274 flatbuffers::IDLOptions opts;
1275 opts.lang_to_generate = flatbuffers::IDLOptions::Language::kSwift;
1276 opts.no_leak_private_annotations = true;
1277
1278 for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1279 flatbuffers::Parser parser(opts);
1280 TEST_ASSERT(parser.Parse(schema->c_str()));
1281 }
1282
1283 for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1284 schema++) {
1285 flatbuffers::Parser parser(opts);
1286 TEST_EQ(false, parser.Parse(schema->c_str()));
1287 }
1288
1289 opts.no_leak_private_annotations = false;
1290
1291 for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1292 flatbuffers::Parser parser(opts);
1293 TEST_ASSERT(parser.Parse(schema->c_str()));
1294 }
1295
1296 for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1297 schema++) {
1298 flatbuffers::Parser parser(opts);
1299 TEST_ASSERT(parser.Parse(schema->c_str()));
1300 }
1301}
1302
1303void VectorSpanTest() {
1304 flatbuffers::FlatBufferBuilder builder;
1305
1306 auto mloc = CreateMonster(
1307 builder, nullptr, 0, 0, builder.CreateString("Monster"),
1308 builder.CreateVector<uint8_t>({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
1309
1310 FinishMonsterBuffer(builder, mloc);
1311
1312 auto monster = GetMonster(builder.GetBufferPointer());
1313 auto mutable_monster = GetMutableMonster(builder.GetBufferPointer());
1314
1315 { // using references
1316 TEST_NOTNULL(monster->inventory());
1317
1318 flatbuffers::span<const uint8_t> const_inventory =
1319 flatbuffers::make_span(*monster->inventory());
1320 TEST_EQ(const_inventory.size(), 10);
1321 TEST_EQ(const_inventory[0], 0);
1322 TEST_EQ(const_inventory[9], 9);
1323
1324 flatbuffers::span<uint8_t> mutable_inventory =
1325 flatbuffers::make_span(*mutable_monster->mutable_inventory());
1326 TEST_EQ(mutable_inventory.size(), 10);
1327 TEST_EQ(mutable_inventory[0], 0);
1328 TEST_EQ(mutable_inventory[9], 9);
1329
1330 mutable_inventory[0] = 42;
1331 TEST_EQ(mutable_inventory[0], 42);
1332
1333 mutable_inventory[0] = 0;
1334 TEST_EQ(mutable_inventory[0], 0);
1335 }
1336
1337 { // using pointers
1338 TEST_EQ(flatbuffers::VectorLength(monster->inventory()), 10);
1339
1340 flatbuffers::span<const uint8_t> const_inventory =
1341 flatbuffers::make_span(monster->inventory());
1342 TEST_EQ(const_inventory.size(), 10);
1343 TEST_EQ(const_inventory[0], 0);
1344 TEST_EQ(const_inventory[9], 9);
1345
1346 flatbuffers::span<uint8_t> mutable_inventory =
1347 flatbuffers::make_span(mutable_monster->mutable_inventory());
1348 TEST_EQ(mutable_inventory.size(), 10);
1349 TEST_EQ(mutable_inventory[0], 0);
1350 TEST_EQ(mutable_inventory[9], 9);
1351
1352 mutable_inventory[0] = 42;
1353 TEST_EQ(mutable_inventory[0], 42);
1354
1355 mutable_inventory[0] = 0;
1356 TEST_EQ(mutable_inventory[0], 0);
1357 }
1358
1359 {
1360 TEST_ASSERT(nullptr == monster->testnestedflatbuffer());
1361
1362 TEST_EQ(flatbuffers::VectorLength(monster->testnestedflatbuffer()), 0);
1363
1364 flatbuffers::span<const uint8_t> const_nested =
1365 flatbuffers::make_span(monster->testnestedflatbuffer());
1366 TEST_ASSERT(const_nested.empty());
1367
1368 flatbuffers::span<uint8_t> mutable_nested =
1369 flatbuffers::make_span(mutable_monster->mutable_testnestedflatbuffer());
1370 TEST_ASSERT(mutable_nested.empty());
1371 }
1372}
1373
1374void NativeInlineTableVectorTest() {
1375 TestNativeInlineTableT test;
1376 for (int i = 0; i < 10; ++i) {
1377 NativeInlineTableT t;
1378 t.a = i;
1379 test.t.push_back(t);
1380 }
1381
1382 flatbuffers::FlatBufferBuilder fbb;
1383 auto offset = TestNativeInlineTable::Pack(fbb, &test);
1384 fbb.Finish(offset);
1385
1386 auto *root =
1387 flatbuffers::GetRoot<TestNativeInlineTable>(fbb.GetBufferPointer());
1388 TestNativeInlineTableT unpacked;
1389 root->UnPackTo(&unpacked);
1390
1391 for (int i = 0; i < 10; ++i) {
1392 TEST_ASSERT(unpacked.t[i] == test.t[i]);
1393 }
1394
1395 TEST_ASSERT(unpacked.t == test.t);
1396}
1397
1398int FlatBufferTests(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001399 // Run our various test suites:
1400
1401 std::string rawbuf;
1402 auto flatbuf1 = CreateFlatBufferTest(rawbuf);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001403 auto flatbuf = std::move(flatbuf1); // Test move assignment.
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001404
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001405 AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()),
1406 rawbuf.length());
1407 AccessFlatBufferTest(flatbuf.data(), flatbuf.size());
1408
1409 MutateFlatBuffersTest(flatbuf.data(), flatbuf.size());
1410
1411 ObjectFlatBuffersTest(flatbuf.data());
Austin Schuh2dd86a92022-09-14 21:19:23 -07001412 UnPackTo(flatbuf.data());
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001413
1414 MiniReflectFlatBuffersTest(flatbuf.data());
Austin Schuh272c6132020-11-14 16:37:52 -08001415 MiniReflectFixedLengthArrayTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001416
1417 SizePrefixedTest();
1418
Austin Schuh2dd86a92022-09-14 21:19:23 -07001419#ifndef FLATBUFFERS_NO_FILE_TESTS
1420 ParseAndGenerateTextTest(tests_data_path, false);
1421 ParseAndGenerateTextTest(tests_data_path, true);
1422 FixedLengthArrayJsonTest(tests_data_path, false);
1423 FixedLengthArrayJsonTest(tests_data_path, true);
1424 ReflectionTest(tests_data_path, flatbuf.data(), flatbuf.size());
1425 ParseProtoTest(tests_data_path);
1426 ParseProtoTestWithSuffix(tests_data_path);
1427 ParseProtoTestWithIncludes(tests_data_path);
1428 EvolutionTest(tests_data_path);
1429 UnionDeprecationTest(tests_data_path);
1430 UnionVectorTest(tests_data_path);
1431 GenerateTableTextTest(tests_data_path);
1432 TestEmbeddedBinarySchema(tests_data_path);
1433 JsonOptionalTest(tests_data_path, false);
1434 JsonOptionalTest(tests_data_path, true);
1435 MultiFileNameClashTest(tests_data_path);
1436 InvalidNestedFlatbufferTest(tests_data_path);
1437 JsonDefaultTest(tests_data_path);
1438 JsonEnumsTest(tests_data_path);
1439 TestMonsterExtraFloats(tests_data_path);
1440 ParseIncorrectMonsterJsonTest(tests_data_path);
1441 FixedLengthArraySpanTest(tests_data_path);
1442#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001443
James Kuszmaul8e62b022022-03-22 09:33:25 -07001444 UtilConvertCase();
1445
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001446 FuzzTest1();
1447 FuzzTest2();
1448
Austin Schuh2dd86a92022-09-14 21:19:23 -07001449 TriviallyCopyableTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001450 ErrorTest();
1451 ValueTest();
1452 EnumValueTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001453 NestedListTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001454 EnumStringsTest();
1455 EnumNamesTest();
1456 EnumOutOfRangeTest();
1457 IntegerOutOfRangeTest();
1458 IntegerBoundaryTest();
1459 UnicodeTest();
1460 UnicodeTestAllowNonUTF8();
1461 UnicodeTestGenerateTextFailsOnNonUTF8();
1462 UnicodeSurrogatesTest();
1463 UnicodeInvalidSurrogatesTest();
1464 InvalidUTF8Test();
1465 UnknownFieldsTest();
1466 ParseUnionTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001467 ValidSameNameDifferentNamespaceTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001468 ConformTest();
1469 ParseProtoBufAsciiTest();
1470 TypeAliasesTest();
1471 EndianSwapTest();
1472 CreateSharedStringTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001473 FlexBuffersTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001474 FlexBuffersReuseBugTest();
Austin Schuh272c6132020-11-14 16:37:52 -08001475 FlexBuffersDeprecatedTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001476 UninitializedVectorTest();
1477 EqualOperatorTest();
1478 NumericUtilsTest();
1479 IsAsciiUtilsTest();
1480 ValidFloatTest();
1481 InvalidFloatTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001482 FixedLengthArrayTest();
1483 NativeTypeTest();
Austin Schuh272c6132020-11-14 16:37:52 -08001484 OptionalScalarsTest();
1485 ParseFlexbuffersFromJsonWithNullTest();
1486 FlatbuffersSpanTest();
1487 FixedLengthArrayConstructorTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001488 FieldIdentifierTest();
1489 StringVectorDefaultsTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001490 FlexBuffersFloatingPointTest();
1491 FlatbuffersIteratorsTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001492 WarningsAsErrorsTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001493 NestedVerifierTest();
1494 PrivateAnnotationsLeaks();
1495 JsonUnsortedArrayTest();
1496 VectorSpanTest();
1497 NativeInlineTableVectorTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001498 return 0;
1499}
Austin Schuh2dd86a92022-09-14 21:19:23 -07001500} // namespace
1501} // namespace tests
1502} // namespace flatbuffers
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001503
James Kuszmaul8e62b022022-03-22 09:33:25 -07001504int main(int argc, const char *argv[]) {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001505 std::string tests_data_path =
1506#ifdef BAZEL_TEST_DATA_PATH
1507 "../com_github_google_flatbuffers/tests/";
1508#else
1509 "tests/";
1510#endif
1511
James Kuszmaul8e62b022022-03-22 09:33:25 -07001512 for (int argi = 1; argi < argc; argi++) {
1513 std::string arg = argv[argi];
1514 if (arg == "--test_path") {
1515 if (++argi >= argc) {
1516 fprintf(stderr, "error: missing path following: %s\n", arg.c_str());
1517 exit(1);
1518 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001519 // Override default path if provided one.
1520 tests_data_path = argv[argi];
1521
James Kuszmaul8e62b022022-03-22 09:33:25 -07001522 } else {
1523 fprintf(stderr, "error: Unknown argument: %s\n", arg.c_str());
1524 exit(1);
1525 }
1526 }
1527
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001528 InitTestEngine();
1529
1530 std::string req_locale;
1531 if (flatbuffers::ReadEnvironmentVariable("FLATBUFFERS_TEST_LOCALE",
1532 &req_locale)) {
1533 TEST_OUTPUT_LINE("The environment variable FLATBUFFERS_TEST_LOCALE=%s",
1534 req_locale.c_str());
1535 req_locale = flatbuffers::RemoveStringQuotes(req_locale);
1536 std::string the_locale;
1537 TEST_ASSERT_FUNC(
1538 flatbuffers::SetGlobalTestLocale(req_locale.c_str(), &the_locale));
1539 TEST_OUTPUT_LINE("The global C-locale changed: %s", the_locale.c_str());
1540 }
1541
Austin Schuh2dd86a92022-09-14 21:19:23 -07001542#ifdef FLATBUFFERS_TEST_PATH_PREFIX
1543 tests_data_path =
1544 FLATBUFFERS_STRING(FLATBUFFERS_TEST_PATH_PREFIX) + tests_data_path;
1545#endif
1546
1547 flatbuffers::tests::FlatBufferTests(tests_data_path);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001548 FlatBufferBuilderTest();
1549
1550 if (!testing_fails) {
1551 TEST_OUTPUT_LINE("ALL TESTS PASSED");
1552 } else {
1553 TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
1554 }
1555 return CloseTestEngine();
1556}