blob: 65198a67a45b27bc54dde0c2511a68cf353c541d [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>
James Kuszmaul3b15b0c2022-11-08 14:03:16 -080019#include <limits>
Austin Schuh2dd86a92022-09-14 21:19:23 -070020#include <memory>
James Kuszmaul8e62b022022-03-22 09:33:25 -070021#include <string>
Austin Schuh272c6132020-11-14 16:37:52 -080022
Austin Schuh2dd86a92022-09-14 21:19:23 -070023#include "evolution_test.h"
James Kuszmaul3b15b0c2022-11-08 14:03:16 -080024#include "alignment_test.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070025#include "flatbuffers/flatbuffers.h"
26#include "flatbuffers/idl.h"
27#include "flatbuffers/minireflect.h"
28#include "flatbuffers/registry.h"
29#include "flatbuffers/util.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070030#include "fuzz_test.h"
31#include "json_test.h"
32#include "monster_test.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070033#include "monster_test_generated.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070034#include "optional_scalars_test.h"
35#include "native_inline_table_test_generated.h"
36#include "parser_test.h"
37#include "proto_test.h"
38#include "reflection_test.h"
James Kuszmaul8e62b022022-03-22 09:33:25 -070039#include "union_vector/union_vector_generated.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070040#if !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuh272c6132020-11-14 16:37:52 -080041# include "arrays_test_generated.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070042#endif
43
Austin Schuh2dd86a92022-09-14 21:19:23 -070044#include "flexbuffers_test.h"
45#include "is_quiet_nan.h"
Austin Schuh272c6132020-11-14 16:37:52 -080046#include "monster_test_bfbs_generated.h" // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed
James Kuszmaul8e62b022022-03-22 09:33:25 -070047#include "native_type_test_generated.h"
48#include "test_assert.h"
Austin Schuh2dd86a92022-09-14 21:19:23 -070049#include "util_test.h"
50
51void FlatBufferBuilderTest();
52
53namespace flatbuffers {
54namespace tests {
55namespace {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070056
57// clang-format off
58// Check that char* and uint8_t* are interoperable types.
59// The reinterpret_cast<> between the pointers are used to simplify data loading.
60static_assert(flatbuffers::is_same<uint8_t, char>::value ||
61 flatbuffers::is_same<uint8_t, unsigned char>::value,
62 "unexpected uint8_t type");
63
64#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
65 // Ensure IEEE-754 support if tests of floats with NaN/Inf will run.
66 static_assert(std::numeric_limits<float>::is_iec559 &&
67 std::numeric_limits<double>::is_iec559,
68 "IEC-559 (IEEE-754) standard required");
69#endif
70// clang-format on
71
Austin Schuhe89fa2d2019-08-14 20:24:23 -070072using namespace MyGame::Example;
73
Austin Schuhe89fa2d2019-08-14 20:24:23 -070074void TriviallyCopyableTest() {
James Kuszmaul8e62b022022-03-22 09:33:25 -070075// clang-format off
Austin Schuh2dd86a92022-09-14 21:19:23 -070076 #if __GNUG__ && __GNUC__ < 5 && \
77 !(defined(__clang__) && __clang_major__ >= 16)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070078 TEST_EQ(__has_trivial_copy(Vec3), true);
79 #else
80 #if __cplusplus >= 201103L
81 TEST_EQ(std::is_trivially_copyable<Vec3>::value, true);
82 #endif
83 #endif
84 // clang-format on
85}
86
James Kuszmaul3b15b0c2022-11-08 14:03:16 -080087// Guard against -Wunused-function on platforms without file tests.
88#ifndef FLATBUFFERS_NO_FILE_TESTS
Austin Schuh2dd86a92022-09-14 21:19:23 -070089void GenerateTableTextTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070090 std::string schemafile;
91 std::string jsonfile;
92 bool ok =
Austin Schuh2dd86a92022-09-14 21:19:23 -070093 flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -070094 false, &schemafile) &&
Austin Schuh2dd86a92022-09-14 21:19:23 -070095 flatbuffers::LoadFile((tests_data_path + "monsterdata_test.json").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -070096 false, &jsonfile);
97 TEST_EQ(ok, true);
98 auto include_test_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -070099 flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
100 const char *include_directories[] = { tests_data_path.c_str(),
Austin Schuh272c6132020-11-14 16:37:52 -0800101 include_test_path.c_str(), nullptr };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700102 flatbuffers::IDLOptions opt;
103 opt.indent_step = -1;
104 flatbuffers::Parser parser(opt);
105 ok = parser.Parse(schemafile.c_str(), include_directories) &&
106 parser.Parse(jsonfile.c_str(), include_directories);
107 TEST_EQ(ok, true);
108 // Test root table
109 const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
James Kuszmaul8e62b022022-03-22 09:33:25 -0700110 const auto abilities = monster->testarrayofsortedstruct();
111 TEST_EQ(abilities->size(), 3);
112 TEST_EQ(abilities->Get(0)->id(), 0);
113 TEST_EQ(abilities->Get(0)->distance(), 45);
114 TEST_EQ(abilities->Get(1)->id(), 1);
115 TEST_EQ(abilities->Get(1)->distance(), 21);
116 TEST_EQ(abilities->Get(2)->id(), 5);
117 TEST_EQ(abilities->Get(2)->distance(), 12);
118
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700119 std::string jsongen;
120 auto result = GenerateTextFromTable(parser, monster, "MyGame.Example.Monster",
121 &jsongen);
122 TEST_EQ(result, true);
123 // Test sub table
124 const Vec3 *pos = monster->pos();
125 jsongen.clear();
126 result = GenerateTextFromTable(parser, pos, "MyGame.Example.Vec3", &jsongen);
127 TEST_EQ(result, true);
128 TEST_EQ_STR(
129 jsongen.c_str(),
130 "{x: 1.0,y: 2.0,z: 3.0,test1: 3.0,test2: \"Green\",test3: {a: 5,b: 6}}");
131 const Test &test3 = pos->test3();
132 jsongen.clear();
133 result =
134 GenerateTextFromTable(parser, &test3, "MyGame.Example.Test", &jsongen);
135 TEST_EQ(result, true);
136 TEST_EQ_STR(jsongen.c_str(), "{a: 5,b: 6}");
137 const Test *test4 = monster->test4()->Get(0);
138 jsongen.clear();
139 result =
140 GenerateTextFromTable(parser, test4, "MyGame.Example.Test", &jsongen);
141 TEST_EQ(result, true);
142 TEST_EQ_STR(jsongen.c_str(), "{a: 10,b: 20}");
143}
144
Austin Schuh2dd86a92022-09-14 21:19:23 -0700145void MultiFileNameClashTest(const std::string &tests_data_path) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700146 const auto name_clash_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -0700147 flatbuffers::ConCatPathFileName(tests_data_path, "name_clash_test");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700148 const char *include_directories[] = { name_clash_path.c_str() };
149
150 // Load valid 2 file Flatbuffer schema
151 const auto valid_path =
152 flatbuffers::ConCatPathFileName(name_clash_path, "valid_test1.fbs");
153 std::string valid_schema;
154 TEST_ASSERT(flatbuffers::LoadFile(valid_path.c_str(), false, &valid_schema));
155 // Clashing table and union names in different namespaces must be parsable
156 TEST_ASSERT(
157 flatbuffers::Parser().Parse(valid_schema.c_str(), include_directories));
158
159 flatbuffers::Parser p;
160 TEST_ASSERT(p.Parse(valid_schema.c_str(), include_directories));
161
162 // Load invalid 2 file Flatbuffer schema
163 const auto invalid_path =
164 flatbuffers::ConCatPathFileName(name_clash_path, "invalid_test1.fbs");
165 std::string invalid_schema;
166 TEST_ASSERT(
167 flatbuffers::LoadFile(invalid_path.c_str(), false, &invalid_schema));
168 // Clashing table and union names in same namespace must fail to parse
169 TEST_EQ(
170 flatbuffers::Parser().Parse(invalid_schema.c_str(), include_directories),
171 false);
172}
173
Austin Schuh2dd86a92022-09-14 21:19:23 -0700174void InvalidNestedFlatbufferTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700175 // First, load and parse FlatBuffer schema (.fbs)
176 std::string schemafile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700177 TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700178 false, &schemafile),
179 true);
180 auto include_test_path =
Austin Schuh2dd86a92022-09-14 21:19:23 -0700181 flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
182 const char *include_directories[] = { tests_data_path.c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700183 include_test_path.c_str(), nullptr };
184 flatbuffers::Parser parser1;
185 TEST_EQ(parser1.Parse(schemafile.c_str(), include_directories), true);
186
187 // "color" inside nested flatbuffer contains invalid enum value
188 TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: "
189 "\"Leela\", color: \"nonexistent\"}}"),
190 false);
Austin Schuh272c6132020-11-14 16:37:52 -0800191}
192
Austin Schuh2dd86a92022-09-14 21:19:23 -0700193void UnionVectorTest(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700194 // load FlatBuffer fbs schema and json.
195 std::string schemafile, jsonfile;
196 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700197 (tests_data_path + "union_vector/union_vector.fbs").c_str(),
198 false, &schemafile),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700199 true);
200 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700201 (tests_data_path + "union_vector/union_vector.json").c_str(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700202 false, &jsonfile),
203 true);
204
205 // parse schema.
206 flatbuffers::IDLOptions idl_opts;
207 idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
208 flatbuffers::Parser parser(idl_opts);
209 TEST_EQ(parser.Parse(schemafile.c_str()), true);
210
211 flatbuffers::FlatBufferBuilder fbb;
212
213 // union types.
214 std::vector<uint8_t> types;
215 types.push_back(static_cast<uint8_t>(Character_Belle));
216 types.push_back(static_cast<uint8_t>(Character_MuLan));
217 types.push_back(static_cast<uint8_t>(Character_BookFan));
218 types.push_back(static_cast<uint8_t>(Character_Other));
219 types.push_back(static_cast<uint8_t>(Character_Unused));
220
221 // union values.
222 std::vector<flatbuffers::Offset<void>> characters;
223 characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
224 characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
225 characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
226 characters.push_back(fbb.CreateString("Other").Union());
227 characters.push_back(fbb.CreateString("Unused").Union());
228
229 // create Movie.
230 const auto movie_offset =
231 CreateMovie(fbb, Character_Rapunzel,
232 fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
233 fbb.CreateVector(types), fbb.CreateVector(characters));
234 FinishMovieBuffer(fbb, movie_offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700235
Austin Schuh272c6132020-11-14 16:37:52 -0800236 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700237 TEST_EQ(VerifyMovieBuffer(verifier), true);
238
Austin Schuh272c6132020-11-14 16:37:52 -0800239 auto flat_movie = GetMovie(fbb.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700240
241 auto TestMovie = [](const Movie *movie) {
242 TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
243
244 auto cts = movie->characters_type();
245 TEST_EQ(movie->characters_type()->size(), 5);
246 TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
247 TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
248 TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
249 TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
250 TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
251
252 auto rapunzel = movie->main_character_as_Rapunzel();
253 TEST_NOTNULL(rapunzel);
254 TEST_EQ(rapunzel->hair_length(), 6);
255
256 auto cs = movie->characters();
257 TEST_EQ(cs->size(), 5);
258 auto belle = cs->GetAs<BookReader>(0);
259 TEST_EQ(belle->books_read(), 7);
260 auto mu_lan = cs->GetAs<Attacker>(1);
261 TEST_EQ(mu_lan->sword_attack_damage(), 5);
262 auto book_fan = cs->GetAs<BookReader>(2);
263 TEST_EQ(book_fan->books_read(), 2);
264 auto other = cs->GetAsString(3);
265 TEST_EQ_STR(other->c_str(), "Other");
266 auto unused = cs->GetAsString(4);
267 TEST_EQ_STR(unused->c_str(), "Unused");
268 };
269
270 TestMovie(flat_movie);
271
272 // Also test the JSON we loaded above.
273 TEST_EQ(parser.Parse(jsonfile.c_str()), true);
274 auto jbuf = parser.builder_.GetBufferPointer();
275 flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
276 TEST_EQ(VerifyMovieBuffer(jverifier), true);
277 TestMovie(GetMovie(jbuf));
278
279 auto movie_object = flat_movie->UnPack();
280 TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
281 TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
282 TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
283 TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
284 TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
285 TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
286
287 fbb.Clear();
288 fbb.Finish(Movie::Pack(fbb, movie_object));
289
290 delete movie_object;
291
292 auto repacked_movie = GetMovie(fbb.GetBufferPointer());
293
294 TestMovie(repacked_movie);
295
Austin Schuh272c6132020-11-14 16:37:52 -0800296 // Generate text using mini-reflection.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700297 auto s =
298 flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
299 TEST_EQ_STR(
300 s.c_str(),
301 "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
302 "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
303 "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
304 "{ books_read: 2 }, \"Other\", \"Unused\" ] }");
305
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700306 flatbuffers::ToStringVisitor visitor("\n", true, " ");
307 IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor);
Austin Schuh272c6132020-11-14 16:37:52 -0800308 TEST_EQ_STR(visitor.s.c_str(),
309 "{\n"
310 " \"main_character_type\": \"Rapunzel\",\n"
311 " \"main_character\": {\n"
312 " \"hair_length\": 6\n"
313 " },\n"
314 " \"characters_type\": [\n"
315 " \"Belle\",\n"
316 " \"MuLan\",\n"
317 " \"BookFan\",\n"
318 " \"Other\",\n"
319 " \"Unused\"\n"
320 " ],\n"
321 " \"characters\": [\n"
322 " {\n"
323 " \"books_read\": 7\n"
324 " },\n"
325 " {\n"
326 " \"sword_attack_damage\": 5\n"
327 " },\n"
328 " {\n"
329 " \"books_read\": 2\n"
330 " },\n"
331 " \"Other\",\n"
332 " \"Unused\"\n"
333 " ]\n"
334 "}");
335
336 // Generate text using parsed schema.
337 std::string jsongen;
338 auto result = GenerateText(parser, fbb.GetBufferPointer(), &jsongen);
339 TEST_EQ(result, true);
340 TEST_EQ_STR(jsongen.c_str(),
341 "{\n"
342 " main_character_type: \"Rapunzel\",\n"
343 " main_character: {\n"
344 " hair_length: 6\n"
345 " },\n"
346 " characters_type: [\n"
347 " \"Belle\",\n"
348 " \"MuLan\",\n"
349 " \"BookFan\",\n"
350 " \"Other\",\n"
351 " \"Unused\"\n"
352 " ],\n"
353 " characters: [\n"
354 " {\n"
355 " books_read: 7\n"
356 " },\n"
357 " {\n"
358 " sword_attack_damage: 5\n"
359 " },\n"
360 " {\n"
361 " books_read: 2\n"
362 " },\n"
363 " \"Other\",\n"
364 " \"Unused\"\n"
365 " ]\n"
366 "}\n");
367
368 // Simple test with reflection.
369 parser.Serialize();
370 auto schema = reflection::GetSchema(parser.builder_.GetBufferPointer());
371 auto ok = flatbuffers::Verify(*schema, *schema->root_table(),
372 fbb.GetBufferPointer(), fbb.GetSize());
373 TEST_EQ(ok, true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700374
375 flatbuffers::Parser parser2(idl_opts);
376 TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
377 "union Any { Bool }"
378 "table Root { a:Any; }"
Austin Schuh272c6132020-11-14 16:37:52 -0800379 "root_type Root;"),
380 true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700381 TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
382}
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800383#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700384
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700385void EndianSwapTest() {
386 TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
387 TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
388 0x78563412);
389 TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
390 0xEFCDAB9078563412);
391 TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
392}
393
394void UninitializedVectorTest() {
395 flatbuffers::FlatBufferBuilder builder;
396
397 Test *buf = nullptr;
Austin Schuh272c6132020-11-14 16:37:52 -0800398 auto vector_offset =
399 builder.CreateUninitializedVectorOfStructs<Test>(2, &buf);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700400 TEST_NOTNULL(buf);
401 buf[0] = Test(10, 20);
402 buf[1] = Test(30, 40);
403
404 auto required_name = builder.CreateString("myMonster");
405 auto monster_builder = MonsterBuilder(builder);
Austin Schuh272c6132020-11-14 16:37:52 -0800406 monster_builder.add_name(
407 required_name); // required field mandated for monster.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700408 monster_builder.add_test4(vector_offset);
409 builder.Finish(monster_builder.Finish());
410
411 auto p = builder.GetBufferPointer();
412 auto uvt = flatbuffers::GetRoot<Monster>(p);
413 TEST_NOTNULL(uvt);
414 auto vec = uvt->test4();
415 TEST_NOTNULL(vec);
416 auto test_0 = vec->Get(0);
417 auto test_1 = vec->Get(1);
418 TEST_EQ(test_0->a(), 10);
419 TEST_EQ(test_0->b(), 20);
420 TEST_EQ(test_1->a(), 30);
421 TEST_EQ(test_1->b(), 40);
422}
423
424void EqualOperatorTest() {
425 MonsterT a;
426 MonsterT b;
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800427 // We have to reset the fields that are NaN to zero to allow the equality
428 // to evaluate to true.
429 TEST_EQ(std::isnan(a.nan_default), true);
430 TEST_EQ(std::isnan(b.nan_default), true);
431 a.nan_default = 0;
432 b.nan_default = 0;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700433 TEST_EQ(b == a, true);
434 TEST_EQ(b != a, false);
435
436 b.mana = 33;
437 TEST_EQ(b == a, false);
438 TEST_EQ(b != a, true);
439 b.mana = 150;
440 TEST_EQ(b == a, true);
441 TEST_EQ(b != a, false);
442
443 b.inventory.push_back(3);
444 TEST_EQ(b == a, false);
445 TEST_EQ(b != a, true);
446 b.inventory.clear();
447 TEST_EQ(b == a, true);
448 TEST_EQ(b != a, false);
449
James Kuszmaul8e62b022022-03-22 09:33:25 -0700450 a.enemy.reset(new MonsterT());
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800451 a.enemy->nan_default = 0;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700452 TEST_EQ(b != a, true);
453 a.enemy->mana = 33;
454 TEST_EQ(b == a, false);
455 TEST_EQ(b != a, true);
456
457 b.enemy.reset(new MonsterT());
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800458 b.enemy->nan_default = 0;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700459 TEST_EQ(b == a, false);
460 TEST_EQ(b != a, true);
461 b.enemy->mana = 33;
462 TEST_EQ(b == a, true);
463 TEST_EQ(b != a, false);
464
465 a.enemy.reset(nullptr);
466 TEST_EQ(b == a, false);
467 TEST_EQ(b != a, true);
468 b.enemy->mana = 150;
469 TEST_EQ(b == a, false);
470 TEST_EQ(b != a, true);
471 a.enemy.reset(new MonsterT());
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800472 a.enemy->nan_default = 0;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700473 TEST_EQ(b == a, true);
474 TEST_EQ(b != a, false);
475
476 b.enemy.reset(nullptr);
477
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700478 b.test.type = Any_Monster;
479 TEST_EQ(b == a, false);
480 TEST_EQ(b != a, true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700481
Austin Schuh2dd86a92022-09-14 21:19:23 -0700482 // Test that vector of tables are compared by value and not by reference.
483 {
484 // Two tables are equal by default.
485 MonsterT a, b;
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800486 a.nan_default = 0;
487 b.nan_default = 0;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700488 TEST_EQ(a == b, true);
489
490 // Adding only a table to one of the monster vectors should make it not
491 // equal (due to size mistmatch).
492 a.testarrayoftables.push_back(
493 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800494 a.testarrayoftables.back()->nan_default = 0;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700495 TEST_EQ(a == b, false);
496
497 // Adding an equalivant table to the other monster vector should make it
498 // equal again.
499 b.testarrayoftables.push_back(
500 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800501 b.testarrayoftables.back()->nan_default = 0;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700502 TEST_EQ(a == b, true);
503
504 // Create two new monsters that are different.
505 auto c = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
506 auto d = flatbuffers::unique_ptr<MonsterT>(new MonsterT);
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800507 c->nan_default = 0;
508 d->nan_default = 0;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700509 c->hp = 1;
510 d->hp = 2;
511 TEST_EQ(c == d, false);
512
513 // Adding them to the original monsters should also make them different.
514 a.testarrayoftables.push_back(std::move(c));
515 b.testarrayoftables.push_back(std::move(d));
516 TEST_EQ(a == b, false);
517
518 // Remove the mismatching monsters to get back to equality
519 a.testarrayoftables.pop_back();
520 b.testarrayoftables.pop_back();
521 TEST_EQ(a == b, true);
522
523 // Check that nullptr are OK.
524 a.testarrayoftables.push_back(nullptr);
525 b.testarrayoftables.push_back(
526 flatbuffers::unique_ptr<MonsterT>(new MonsterT));
527 TEST_EQ(a == b, false);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700528 }
529}
530
531void CreateSharedStringTest() {
532 flatbuffers::FlatBufferBuilder builder;
533 const auto one1 = builder.CreateSharedString("one");
534 const auto two = builder.CreateSharedString("two");
535 const auto one2 = builder.CreateSharedString("one");
536 TEST_EQ(one1.o, one2.o);
537 const auto onetwo = builder.CreateSharedString("onetwo");
538 TEST_EQ(onetwo.o != one1.o, true);
539 TEST_EQ(onetwo.o != two.o, true);
540
541 // Support for embedded nulls
Austin Schuh272c6132020-11-14 16:37:52 -0800542 const char chars_b[] = { 'a', '\0', 'b' };
543 const char chars_c[] = { 'a', '\0', 'c' };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700544 const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b));
545 const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c));
546 const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b));
Austin Schuh272c6132020-11-14 16:37:52 -0800547 TEST_EQ(null_b1.o != null_c.o, true); // Issue#5058 repro
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700548 TEST_EQ(null_b1.o, null_b2.o);
549
550 // Put the strings into an array for round trip verification.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700551 std::array<flatbuffers::Offset<flatbuffers::String>, 7> array = {
Austin Schuh272c6132020-11-14 16:37:52 -0800552 one1, two, one2, onetwo, null_b1, null_c, null_b2
553 };
554 const auto vector_offset =
James Kuszmaul8e62b022022-03-22 09:33:25 -0700555 builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(array);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700556 MonsterBuilder monster_builder(builder);
557 monster_builder.add_name(two);
558 monster_builder.add_testarrayofstring(vector_offset);
559 builder.Finish(monster_builder.Finish());
560
561 // Read the Monster back.
Austin Schuh272c6132020-11-14 16:37:52 -0800562 const auto *monster =
563 flatbuffers::GetRoot<Monster>(builder.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700564 TEST_EQ_STR(monster->name()->c_str(), "two");
565 const auto *testarrayofstring = monster->testarrayofstring();
566 TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7));
567 const auto &a = *testarrayofstring;
568 TEST_EQ_STR(a[0]->c_str(), "one");
569 TEST_EQ_STR(a[1]->c_str(), "two");
570 TEST_EQ_STR(a[2]->c_str(), "one");
571 TEST_EQ_STR(a[3]->c_str(), "onetwo");
572 TEST_EQ(a[4]->str(), (std::string(chars_b, sizeof(chars_b))));
573 TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c))));
574 TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b))));
575
Austin Schuh272c6132020-11-14 16:37:52 -0800576 // Make sure String::operator< works, too, since it is related to
577 // StringOffsetCompare.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700578 TEST_EQ((*a[0]) < (*a[1]), true);
579 TEST_EQ((*a[1]) < (*a[0]), false);
580 TEST_EQ((*a[1]) < (*a[2]), false);
581 TEST_EQ((*a[2]) < (*a[1]), true);
582 TEST_EQ((*a[4]) < (*a[3]), true);
583 TEST_EQ((*a[5]) < (*a[4]), false);
584 TEST_EQ((*a[5]) < (*a[4]), false);
585 TEST_EQ((*a[6]) < (*a[5]), true);
586}
587
Austin Schuh2dd86a92022-09-14 21:19:23 -0700588#if !defined(FLATBUFFERS_USE_STD_SPAN) && !defined(FLATBUFFERS_SPAN_MINIMAL)
Austin Schuh272c6132020-11-14 16:37:52 -0800589void FlatbuffersSpanTest() {
590 // Compile-time checking of non-const [] to const [] conversions.
Austin Schuh2dd86a92022-09-14 21:19:23 -0700591 using flatbuffers::internal::is_span_convertible;
592 (void)is_span_convertible<int, 1, int, 1>::type(123);
593 (void)is_span_convertible<const int, 1, int, 1>::type(123);
594 (void)is_span_convertible<const int64_t, 1, int64_t, 1>::type(123);
595 (void)is_span_convertible<const uint64_t, 1, uint64_t, 1>::type(123);
596 (void)is_span_convertible<const int, 1, const int, 1>::type(123);
597 (void)is_span_convertible<const int64_t, 1, const int64_t, 1>::type(123);
598 (void)is_span_convertible<const uint64_t, 1, const uint64_t, 1>::type(123);
Austin Schuh272c6132020-11-14 16:37:52 -0800599
600 using flatbuffers::span;
601 span<char, 0> c1;
602 TEST_EQ(c1.size(), 0);
603 span<char, flatbuffers::dynamic_extent> c2;
604 TEST_EQ(c2.size(), 0);
605 span<char> c3;
606 TEST_EQ(c3.size(), 0);
607 TEST_ASSERT(c1.empty() && c2.empty() && c3.empty());
608
609 int i_data7[7] = { 0, 1, 2, 3, 4, 5, 6 };
610 span<int, 7> i1(&i_data7[0], 7);
611 span<int> i2(i1); // make dynamic from static
612 TEST_EQ(i1.size(), 7);
613 TEST_EQ(i1.empty(), false);
614 TEST_EQ(i1.size(), i2.size());
615 TEST_EQ(i1.data(), i_data7);
616 TEST_EQ(i1[2], 2);
617 // Make const span from a non-const one.
618 span<const int, 7> i3(i1);
619 // Construct from a C-array.
620 span<int, 7> i4(i_data7);
621 span<const int, 7> i5(i_data7);
622 span<int> i6(i_data7);
623 span<const int> i7(i_data7);
624 TEST_EQ(i7.size(), 7);
625 // Check construction from a const array.
626 const int i_cdata5[5] = { 4, 3, 2, 1, 0 };
627 span<const int, 5> i8(i_cdata5);
628 span<const int> i9(i_cdata5);
629 TEST_EQ(i9.size(), 5);
630 // Construction from a (ptr, size) pair.
631 span<int, 7> i10(i_data7, 7);
632 span<int> i11(i_data7, 7);
633 TEST_EQ(i11.size(), 7);
634 span<const int, 5> i12(i_cdata5, 5);
635 span<const int> i13(i_cdata5, 5);
636 TEST_EQ(i13.size(), 5);
637 // Construction from std::array.
638 std::array<int, 6> i_arr6 = { { 0, 1, 2, 3, 4, 5 } };
639 span<int, 6> i14(i_arr6);
640 span<const int, 6> i15(i_arr6);
641 span<int> i16(i_arr6);
642 span<const int> i17(i_arr6);
643 TEST_EQ(i17.size(), 6);
644 const std::array<int, 8> i_carr8 = { { 0, 1, 2, 3, 4, 5, 6, 7 } };
645 span<const int, 8> i18(i_carr8);
646 span<const int> i19(i_carr8);
647 TEST_EQ(i18.size(), 8);
648 TEST_EQ(i19.size(), 8);
649 TEST_EQ(i19[7], 7);
650 // Check compatibility with flatbuffers::Array.
651 int fbs_int3_underlaying[3] = { 0 };
652 int fbs_int3_data[3] = { 1, 2, 3 };
653 auto &fbs_int3 = flatbuffers::CastToArray(fbs_int3_underlaying);
654 fbs_int3.CopyFromSpan(fbs_int3_data);
655 TEST_EQ(fbs_int3.Get(1), 2);
656 const int fbs_cint3_data[3] = { 2, 3, 4 };
657 fbs_int3.CopyFromSpan(fbs_cint3_data);
658 TEST_EQ(fbs_int3.Get(1), 3);
659 // Check with Array<Enum, N>
660 enum class Dummy : uint16_t { Zero = 0, One, Two };
661 Dummy fbs_dummy3_underlaying[3] = {};
662 Dummy fbs_dummy3_data[3] = { Dummy::One, Dummy::Two, Dummy::Two };
663 auto &fbs_dummy3 = flatbuffers::CastToArray(fbs_dummy3_underlaying);
664 fbs_dummy3.CopyFromSpan(fbs_dummy3_data);
665 TEST_EQ(fbs_dummy3.Get(1), Dummy::Two);
666}
667#else
668void FlatbuffersSpanTest() {}
669#endif
670
James Kuszmaul8e62b022022-03-22 09:33:25 -0700671// VS10 does not support typed enums, exclude from tests
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700672#if !defined(_MSC_VER) || _MSC_VER >= 1700
James Kuszmaul8e62b022022-03-22 09:33:25 -0700673void FixedLengthArrayTest() {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700674 // Generate an ArrayTable containing one ArrayStruct.
675 flatbuffers::FlatBufferBuilder fbb;
676 MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
677 TEST_NOTNULL(nStruct0.mutable_a());
678 nStruct0.mutable_a()->Mutate(0, 1);
679 nStruct0.mutable_a()->Mutate(1, 2);
680 TEST_NOTNULL(nStruct0.mutable_c());
681 nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
682 nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
Austin Schuh272c6132020-11-14 16:37:52 -0800683 TEST_NOTNULL(nStruct0.mutable_d());
684 nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
685 nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700686 MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
687 TEST_NOTNULL(nStruct1.mutable_a());
688 nStruct1.mutable_a()->Mutate(0, 3);
689 nStruct1.mutable_a()->Mutate(1, 4);
690 TEST_NOTNULL(nStruct1.mutable_c());
691 nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
692 nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
Austin Schuh272c6132020-11-14 16:37:52 -0800693 TEST_NOTNULL(nStruct1.mutable_d());
694 nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
695 nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
696 MyGame::Example::ArrayStruct aStruct(2, 12, 1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700697 TEST_NOTNULL(aStruct.b());
698 TEST_NOTNULL(aStruct.mutable_b());
699 TEST_NOTNULL(aStruct.mutable_d());
Austin Schuh272c6132020-11-14 16:37:52 -0800700 TEST_NOTNULL(aStruct.mutable_f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700701 for (int i = 0; i < aStruct.b()->size(); i++)
702 aStruct.mutable_b()->Mutate(i, i + 1);
703 aStruct.mutable_d()->Mutate(0, nStruct0);
704 aStruct.mutable_d()->Mutate(1, nStruct1);
705 auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
Austin Schuh272c6132020-11-14 16:37:52 -0800706 MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700707 // Verify correctness of the ArrayTable.
708 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
James Kuszmaul8e62b022022-03-22 09:33:25 -0700709 TEST_ASSERT(MyGame::Example::VerifyArrayTableBuffer(verifier));
710 // Do test.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700711 auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
712 auto mArStruct = p->mutable_a();
713 TEST_NOTNULL(mArStruct);
714 TEST_NOTNULL(mArStruct->b());
715 TEST_NOTNULL(mArStruct->d());
Austin Schuh272c6132020-11-14 16:37:52 -0800716 TEST_NOTNULL(mArStruct->f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700717 TEST_NOTNULL(mArStruct->mutable_b());
718 TEST_NOTNULL(mArStruct->mutable_d());
Austin Schuh272c6132020-11-14 16:37:52 -0800719 TEST_NOTNULL(mArStruct->mutable_f());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700720 TEST_EQ(mArStruct->a(), 2);
721 TEST_EQ(mArStruct->b()->size(), 15);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700722 mArStruct->mutable_b()->Mutate(14, -14);
723 TEST_EQ(mArStruct->b()->Get(14), -14);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700724 TEST_EQ(mArStruct->c(), 12);
Austin Schuh272c6132020-11-14 16:37:52 -0800725 TEST_NOTNULL(mArStruct->d()->Get(0));
726 TEST_NOTNULL(mArStruct->d()->Get(0)->a());
727 TEST_EQ(mArStruct->d()->Get(0)->a()->Get(0), 1);
728 TEST_EQ(mArStruct->d()->Get(0)->a()->Get(1), 2);
729 TEST_NOTNULL(mArStruct->d()->Get(1));
730 TEST_NOTNULL(mArStruct->d()->Get(1)->a());
731 TEST_EQ(mArStruct->d()->Get(1)->a()->Get(0), 3);
732 TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 4);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700733 TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
734 TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
735 mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
Austin Schuh272c6132020-11-14 16:37:52 -0800736 TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1));
737 TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b());
738 TEST_NOTNULL(mArStruct->d()->Get(0)->c());
739 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0));
740 TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1));
741 TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
742 mArStruct->d()->Get(0)->d()->Get(0));
743 TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
744 mArStruct->d()->Get(0)->d()->Get(1));
745 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b());
746 TEST_NOTNULL(mArStruct->d()->Get(1)->c());
747 TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0));
748 TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1));
749 TEST_EQ(flatbuffers::numeric_limits<int64_t>::min(),
750 mArStruct->d()->Get(1)->d()->Get(0));
751 TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(),
752 mArStruct->d()->Get(1)->d()->Get(1));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700753 for (int i = 0; i < mArStruct->b()->size() - 1; i++)
754 TEST_EQ(mArStruct->b()->Get(i), i + 1);
Austin Schuh272c6132020-11-14 16:37:52 -0800755 // Check alignment
756 TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->d()) % 8);
757 TEST_EQ(0, reinterpret_cast<uintptr_t>(mArStruct->f()) % 8);
758
759 // Check if default constructor set all memory zero
760 const size_t arr_size = sizeof(MyGame::Example::ArrayStruct);
761 char non_zero_memory[arr_size];
762 // set memory chunk of size ArrayStruct to 1's
763 std::memset(static_cast<void *>(non_zero_memory), 1, arr_size);
764 // after placement-new it should be all 0's
James Kuszmaul8e62b022022-03-22 09:33:25 -0700765# if defined(_MSC_VER) && defined(_DEBUG)
766# undef new
767# endif
768 MyGame::Example::ArrayStruct *ap =
769 new (non_zero_memory) MyGame::Example::ArrayStruct;
770# if defined(_MSC_VER) && defined(_DEBUG)
771# define new DEBUG_NEW
772# endif
Austin Schuh272c6132020-11-14 16:37:52 -0800773 (void)ap;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700774 for (size_t i = 0; i < arr_size; ++i) { TEST_EQ(non_zero_memory[i], 0); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700775}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700776#else
777void FixedLengthArrayTest() {}
778#endif // !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700779
James Kuszmaul8e62b022022-03-22 09:33:25 -0700780#if !defined(FLATBUFFERS_SPAN_MINIMAL) && \
781 (!defined(_MSC_VER) || _MSC_VER >= 1700)
Austin Schuh272c6132020-11-14 16:37:52 -0800782void FixedLengthArrayConstructorTest() {
783 const int32_t nested_a[2] = { 1, 2 };
784 MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A,
785 MyGame::Example::TestEnum::B };
786 const int64_t int64_2[2] = { -2, -1 };
787
788 std::array<MyGame::Example::NestedStruct, 2> init_d = {
789 { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B,
790 nested_c, int64_2),
791 MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::A,
792 nested_c,
793 std::array<int64_t, 2>{ { 12, 13 } }) }
794 };
795
796 MyGame::Example::ArrayStruct arr_struct(
797 8.125,
798 std::array<int32_t, 0xF>{
799 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
800 -17, init_d, 10, int64_2);
801 TEST_EQ(arr_struct.a(), 8.125);
802 TEST_EQ(arr_struct.b()->Get(2), 3);
803 TEST_EQ(arr_struct.c(), -17);
804
805 TEST_NOTNULL(arr_struct.d());
806 const auto &arr_d_0 = *arr_struct.d()->Get(0);
807 TEST_EQ(arr_d_0.a()->Get(0), 1);
808 TEST_EQ(arr_d_0.a()->Get(1), 2);
809 TEST_EQ(arr_d_0.b(), MyGame::Example::TestEnum::B);
810 TEST_EQ(arr_d_0.c()->Get(0), MyGame::Example::TestEnum::A);
811 TEST_EQ(arr_d_0.c()->Get(1), MyGame::Example::TestEnum::B);
812 TEST_EQ(arr_d_0.d()->Get(0), -2);
813 TEST_EQ(arr_d_0.d()->Get(1), -1);
814 const auto &arr_d_1 = *arr_struct.d()->Get(1);
815 TEST_EQ(arr_d_1.a()->Get(0), 1);
816 TEST_EQ(arr_d_1.a()->Get(1), 2);
817 TEST_EQ(arr_d_1.b(), MyGame::Example::TestEnum::A);
818 TEST_EQ(arr_d_1.c()->Get(0), MyGame::Example::TestEnum::A);
819 TEST_EQ(arr_d_1.c()->Get(1), MyGame::Example::TestEnum::B);
820 TEST_EQ(arr_d_1.d()->Get(0), 12);
821 TEST_EQ(arr_d_1.d()->Get(1), 13);
822
823 TEST_EQ(arr_struct.e(), 10);
824 TEST_EQ(arr_struct.f()->Get(0), -2);
825 TEST_EQ(arr_struct.f()->Get(1), -1);
826}
827#else
James Kuszmaul8e62b022022-03-22 09:33:25 -0700828void FixedLengthArrayConstructorTest() {}
Austin Schuh272c6132020-11-14 16:37:52 -0800829#endif
830
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700831void NativeTypeTest() {
832 const int N = 3;
833
834 Geometry::ApplicationDataT src_data;
835 src_data.vectors.reserve(N);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700836 src_data.vectors_alt.reserve(N);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700837
838 for (int i = 0; i < N; ++i) {
Austin Schuh272c6132020-11-14 16:37:52 -0800839 src_data.vectors.push_back(
840 Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700841 src_data.vectors_alt.push_back(
842 Native::Vector3D(20 * i + 0.1f, 20 * i + 0.2f, 20 * i + 0.3f));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700843 }
844
845 flatbuffers::FlatBufferBuilder fbb;
846 fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data));
847
Austin Schuh272c6132020-11-14 16:37:52 -0800848 auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700849
850 for (int i = 0; i < N; ++i) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700851 const Native::Vector3D &v = dstDataT->vectors[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700852 TEST_EQ(v.x, 10 * i + 0.1f);
853 TEST_EQ(v.y, 10 * i + 0.2f);
854 TEST_EQ(v.z, 10 * i + 0.3f);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700855
856 const Native::Vector3D &v2 = dstDataT->vectors_alt[i];
857 TEST_EQ(v2.x, 20 * i + 0.1f);
858 TEST_EQ(v2.y, 20 * i + 0.2f);
859 TEST_EQ(v2.z, 20 * i + 0.3f);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700860 }
861}
862
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800863// Guard against -Wunused-function on platforms without file tests.
864#ifndef FLATBUFFERS_NO_FILE_TESTS
James Kuszmaul8e62b022022-03-22 09:33:25 -0700865// VS10 does not support typed enums, exclude from tests
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700866#if !defined(_MSC_VER) || _MSC_VER >= 1700
Austin Schuh2dd86a92022-09-14 21:19:23 -0700867void FixedLengthArrayJsonTest(const std::string &tests_data_path, bool binary) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700868 // load FlatBuffer schema (.fbs) and JSON from disk
869 std::string schemafile;
870 std::string jsonfile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700871 TEST_EQ(flatbuffers::LoadFile(
872 (tests_data_path + "arrays_test." + (binary ? "bfbs" : "fbs"))
873 .c_str(),
874 binary, &schemafile),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700875 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700876 TEST_EQ(
877 flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
878 false, &jsonfile),
879 true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700880
881 // parse schema first, so we can use it to parse the data after
882 flatbuffers::Parser parserOrg, parserGen;
883 if (binary) {
884 flatbuffers::Verifier verifier(
885 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
886 schemafile.size());
887 TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700888 TEST_EQ(parserOrg.Deserialize(
889 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
890 schemafile.size()),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700891 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700892 TEST_EQ(parserGen.Deserialize(
893 reinterpret_cast<const uint8_t *>(schemafile.c_str()),
894 schemafile.size()),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700895 true);
896 } else {
897 TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
898 TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
899 }
900 TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
901
902 // First, verify it, just in case:
903 flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
904 parserOrg.builder_.GetSize());
905 TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
906
907 // Export to JSON
908 std::string jsonGen;
909 TEST_EQ(
910 GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
911 true);
912
913 // Import from JSON
914 TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
915
916 // Verify buffer from generated JSON
917 flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
918 parserGen.builder_.GetSize());
919 TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
920
921 // Compare generated buffer to original
922 TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
923 TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
924 parserGen.builder_.GetBufferPointer(),
925 parserOrg.builder_.GetSize()),
926 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700927}
928
Austin Schuh2dd86a92022-09-14 21:19:23 -0700929void FixedLengthArraySpanTest(const std::string &tests_data_path) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700930 // load FlatBuffer schema (.fbs) and JSON from disk
931 std::string schemafile;
932 std::string jsonfile;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700933 TEST_EQ(flatbuffers::LoadFile((tests_data_path + "arrays_test.fbs").c_str(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700934 false, &schemafile),
935 true);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700936 TEST_EQ(
937 flatbuffers::LoadFile((tests_data_path + "arrays_test.golden").c_str(),
938 false, &jsonfile),
939 true);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700940
941 // parse schema first, so we can use it to parse the data after
942 flatbuffers::Parser parser;
943 TEST_EQ(parser.Parse(schemafile.c_str()), true);
944 TEST_EQ(parser.Parse(jsonfile.c_str()), true);
945 auto &fbb = parser.builder_;
946 auto verifier = flatbuffers::Verifier(fbb.GetBufferPointer(), fbb.GetSize());
947 TEST_EQ(true, VerifyArrayTableBuffer(verifier));
948
949 auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
950 TEST_NOTNULL(p);
951 auto table_struct = p->mutable_a();
952 TEST_NOTNULL(table_struct);
953 TEST_EQ(2, table_struct->d()->size());
954 TEST_NOTNULL(table_struct->d());
955 TEST_NOTNULL(table_struct->mutable_d());
956 // test array of structs
957 auto const_d = flatbuffers::make_span(*table_struct->d());
958 auto mutable_d = flatbuffers::make_span(*table_struct->mutable_d());
959 TEST_EQ(2, const_d.size());
960 TEST_EQ(2, mutable_d.size());
961 TEST_ASSERT(const_d[0] == mutable_d[0]);
962 TEST_ASSERT(const_d[1] == mutable_d[1]);
963 mutable_d[0] = const_d[0]; // mutate
964 // test scalars
965 auto &const_nested = const_d[0];
966 auto &mutable_nested = mutable_d[0];
967 static_assert(sizeof(MyGame::Example::TestEnum) == sizeof(uint8_t),
968 "TestEnum's underlaying type must by byte");
969 TEST_NOTNULL(const_nested.d());
970 TEST_NOTNULL(mutable_nested.d());
971 {
972 flatbuffers::span<const MyGame::Example::TestEnum, 2> const_d_c =
973 flatbuffers::make_span(*const_nested.c());
974 auto mutable_d_c = flatbuffers::make_span(*mutable_nested.mutable_c());
975 TEST_EQ(2, const_d_c.size());
976 TEST_EQ(2, mutable_d_c.size());
977 TEST_EQ(MyGame::Example::TestEnum::C, const_d_c[0]);
978 TEST_EQ(MyGame::Example::TestEnum::B, const_d_c[1]);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700979 TEST_ASSERT(mutable_d_c.end() == std::copy(const_d_c.begin(),
980 const_d_c.end(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700981 mutable_d_c.begin()));
982 TEST_ASSERT(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700983 std::equal(const_d_c.begin(), const_d_c.end(), mutable_d_c.begin()));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700984 }
985 // test little endian array of int32
986# if FLATBUFFERS_LITTLEENDIAN
987 {
988 flatbuffers::span<const int32_t, 2> const_d_a =
989 flatbuffers::make_span(*const_nested.a());
990 auto mutable_d_a = flatbuffers::make_span(*mutable_nested.mutable_a());
991 TEST_EQ(2, const_d_a.size());
992 TEST_EQ(2, mutable_d_a.size());
993 TEST_EQ(-1, const_d_a[0]);
994 TEST_EQ(2, const_d_a[1]);
Austin Schuh2dd86a92022-09-14 21:19:23 -0700995 TEST_ASSERT(mutable_d_a.end() == std::copy(const_d_a.begin(),
996 const_d_a.end(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700997 mutable_d_a.begin()));
998 TEST_ASSERT(
Austin Schuh2dd86a92022-09-14 21:19:23 -0700999 std::equal(const_d_a.begin(), const_d_a.end(), mutable_d_a.begin()));
James Kuszmaul8e62b022022-03-22 09:33:25 -07001000 }
1001# endif
1002}
1003#else
1004void FixedLengthArrayJsonTest(bool /*binary*/) {}
1005void FixedLengthArraySpanTest() {}
1006#endif
1007
Austin Schuh2dd86a92022-09-14 21:19:23 -07001008void TestEmbeddedBinarySchema(const std::string &tests_data_path) {
Austin Schuh272c6132020-11-14 16:37:52 -08001009 // load JSON from disk
1010 std::string jsonfile;
1011 TEST_EQ(flatbuffers::LoadFile(
Austin Schuh2dd86a92022-09-14 21:19:23 -07001012 (tests_data_path + "monsterdata_test.golden").c_str(), false,
Austin Schuh272c6132020-11-14 16:37:52 -08001013 &jsonfile),
1014 true);
1015
1016 // parse schema first, so we can use it to parse the data after
1017 flatbuffers::Parser parserOrg, parserGen;
1018 flatbuffers::Verifier verifier(MyGame::Example::MonsterBinarySchema::data(),
1019 MyGame::Example::MonsterBinarySchema::size());
1020 TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
1021 TEST_EQ(parserOrg.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1022 MyGame::Example::MonsterBinarySchema::size()),
1023 true);
1024 TEST_EQ(parserGen.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
1025 MyGame::Example::MonsterBinarySchema::size()),
1026 true);
1027 TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
1028
1029 // First, verify it, just in case:
1030 flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
1031 parserOrg.builder_.GetSize());
1032 TEST_EQ(VerifyMonsterBuffer(verifierOrg), true);
1033
1034 // Export to JSON
1035 std::string jsonGen;
1036 TEST_EQ(
1037 GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
1038 true);
1039
1040 // Import from JSON
1041 TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
1042
1043 // Verify buffer from generated JSON
1044 flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
1045 parserGen.builder_.GetSize());
1046 TEST_EQ(VerifyMonsterBuffer(verifierGen), true);
1047
1048 // Compare generated buffer to original
1049 TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
1050 TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
1051 parserGen.builder_.GetBufferPointer(),
1052 parserOrg.builder_.GetSize()),
1053 0);
1054}
James Kuszmaul3b15b0c2022-11-08 14:03:16 -08001055#endif
Austin Schuh272c6132020-11-14 16:37:52 -08001056
Austin Schuh2dd86a92022-09-14 21:19:23 -07001057void NestedVerifierTest() {
1058 // Create a nested monster.
1059 flatbuffers::FlatBufferBuilder nested_builder;
1060 FinishMonsterBuffer(
1061 nested_builder,
1062 CreateMonster(nested_builder, nullptr, 0, 0,
1063 nested_builder.CreateString("NestedMonster")));
James Kuszmaul8e62b022022-03-22 09:33:25 -07001064
Austin Schuh2dd86a92022-09-14 21:19:23 -07001065 // Verify the nested monster
1066 flatbuffers::Verifier verifier(nested_builder.GetBufferPointer(),
1067 nested_builder.GetSize());
1068 TEST_EQ(true, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001069
Austin Schuh272c6132020-11-14 16:37:52 -08001070 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001071 // Create the outer monster.
1072 flatbuffers::FlatBufferBuilder builder;
1073
1074 // Add the nested monster as a vector of bytes.
1075 auto nested_monster_bytes = builder.CreateVector(
1076 nested_builder.GetBufferPointer(), nested_builder.GetSize());
1077
1078 auto name = builder.CreateString("OuterMonster");
1079
1080 MonsterBuilder mon_builder(builder);
1081 mon_builder.add_name(name);
1082 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1083 FinishMonsterBuffer(builder, mon_builder.Finish());
1084
1085 // Verify the root monster, which includes verifing the nested monster
1086 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1087 builder.GetSize());
1088 TEST_EQ(true, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001089 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001090
Austin Schuh272c6132020-11-14 16:37:52 -08001091 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001092 // Create the outer monster.
1093 flatbuffers::FlatBufferBuilder builder;
1094
1095 // Purposely invalidate the nested flatbuffer setting its length to 1, an
1096 // invalid length.
1097 uint8_t invalid_nested_buffer[1];
1098 auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 1);
1099
1100 auto name = builder.CreateString("OuterMonster");
1101
1102 MonsterBuilder mon_builder(builder);
1103 mon_builder.add_name(name);
1104 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1105 FinishMonsterBuffer(builder, mon_builder.Finish());
1106
1107 // Verify the root monster fails, since the included nested monster fails.
1108 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1109 builder.GetSize());
1110 TEST_EQ(false, VerifyMonsterBuffer(verifier));
1111
1112 // Verify the root monster succeeds, since we've disabled checking nested
1113 // flatbuffers
1114 flatbuffers::Verifier::Options options;
1115 options.check_nested_flatbuffers = false;
1116 flatbuffers::Verifier no_check_nested(builder.GetBufferPointer(),
1117 builder.GetSize(), options);
1118 TEST_EQ(true, VerifyMonsterBuffer(no_check_nested));
Austin Schuh272c6132020-11-14 16:37:52 -08001119 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001120
Austin Schuh272c6132020-11-14 16:37:52 -08001121 {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001122 // Create the outer monster.
1123 flatbuffers::FlatBufferBuilder builder;
1124
1125 // Purposely invalidate the nested flatbuffer setting its length to 0, an
1126 // invalid length.
1127 uint8_t *invalid_nested_buffer = nullptr;
1128 auto nested_monster_bytes = builder.CreateVector(invalid_nested_buffer, 0);
1129
1130 auto name = builder.CreateString("OuterMonster");
1131
1132 MonsterBuilder mon_builder(builder);
1133 mon_builder.add_name(name);
1134 mon_builder.add_testnestedflatbuffer(nested_monster_bytes);
1135 FinishMonsterBuffer(builder, mon_builder.Finish());
1136
1137 // Verify the root monster fails, since the included nested monster fails.
1138 flatbuffers::Verifier verifier(builder.GetBufferPointer(),
1139 builder.GetSize());
1140 TEST_EQ(false, VerifyMonsterBuffer(verifier));
Austin Schuh272c6132020-11-14 16:37:52 -08001141 }
1142}
1143
James Kuszmaul8e62b022022-03-22 09:33:25 -07001144template<class T, class Container>
1145void TestIterators(const std::vector<T> &expected, const Container &tested) {
1146 TEST_ASSERT(tested.rbegin().base() == tested.end());
1147 TEST_ASSERT(tested.crbegin().base() == tested.cend());
1148 TEST_ASSERT(tested.rend().base() == tested.begin());
1149 TEST_ASSERT(tested.crend().base() == tested.cbegin());
1150
1151 size_t k = 0;
1152 for (auto it = tested.begin(); it != tested.end(); ++it, ++k) {
1153 const auto &e = expected.at(k);
1154 TEST_EQ(*it, e);
1155 }
1156 TEST_EQ(k, expected.size());
1157
1158 k = expected.size();
1159 for (auto it = tested.rbegin(); it != tested.rend(); ++it, --k) {
1160 const auto &e = expected.at(k - 1);
1161 TEST_EQ(*it, e);
1162 }
1163 TEST_EQ(k, 0);
1164}
1165
1166void FlatbuffersIteratorsTest() {
1167 {
1168 flatbuffers::FlatBufferBuilder fbb;
1169 const std::vector<unsigned char> inv_data = { 1, 2, 3 };
1170 {
1171 auto mon_name = fbb.CreateString("MyMonster"); // key, mandatory
1172 auto inv_vec = fbb.CreateVector(inv_data);
1173 auto empty_i64_vec =
1174 fbb.CreateVector(static_cast<const int64_t *>(nullptr), 0);
1175 MonsterBuilder mb(fbb);
1176 mb.add_name(mon_name);
1177 mb.add_inventory(inv_vec);
1178 mb.add_vector_of_longs(empty_i64_vec);
1179 FinishMonsterBuffer(fbb, mb.Finish());
1180 }
1181 const auto &mon = *flatbuffers::GetRoot<Monster>(fbb.GetBufferPointer());
1182
1183 TEST_EQ_STR("MyMonster", mon.name()->c_str());
1184 TEST_ASSERT(mon.inventory());
1185 TEST_ASSERT(mon.vector_of_longs());
1186 TestIterators(inv_data, *mon.inventory());
1187 TestIterators(std::vector<int64_t>(), *mon.vector_of_longs());
1188 }
1189
1190 {
1191 flatbuffers::FlatBufferBuilder fbb;
1192 MyGame::Example::ArrayStruct aStruct;
1193 MyGame::Example::FinishArrayTableBuffer(
1194 fbb, MyGame::Example::CreateArrayTable(fbb, &aStruct));
1195 const auto &array_table =
1196 *flatbuffers::GetRoot<ArrayTable>(fbb.GetBufferPointer());
1197 TEST_ASSERT(array_table.a());
1198 auto &int_15 = *array_table.a()->b();
1199 TestIterators(std::vector<int>(15, 0), int_15);
1200 }
1201}
James Kuszmaul8e62b022022-03-22 09:33:25 -07001202
Austin Schuh2dd86a92022-09-14 21:19:23 -07001203void PrivateAnnotationsLeaks() {
1204 // Simple schemas and a "has optional scalar" sentinal.
1205 std::vector<std::string> schemas;
1206 std::vector<std::string> failure_schemas;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001207
Austin Schuh2dd86a92022-09-14 21:19:23 -07001208 // (private) (table/struct)
1209 schemas.push_back(
1210 "table Monster (private) { mana: int; }"
1211 "struct ABC (private) { mana: int; }");
1212
1213 // (public) (table/struct)
1214 schemas.push_back(
1215 "table Monster { mana: int; }"
1216 "struct ABC { mana: int; }");
1217
1218 // (private) (union) containing (private) (table/struct)
1219 schemas.push_back(
1220 "table Monster (private) { mana: int; } "
1221 "struct ABC (private) { mana: int; } "
1222 "union Any (private) { Monster, ABC } ");
1223
1224 // (public) (union) containing (public) (table/struct)
1225 schemas.push_back(
1226 "table Monster { mana: int; }"
1227 "struct ABC { mana: int; }"
1228 "union Any { Monster, ABC }");
1229
1230 // (private) (table/struct/enum)
1231 schemas.push_back(
1232 "table Monster (private) { mana: int; }"
1233 "struct ABC (private) { mana: int; }"
1234 "enum Race:byte (private) { None = -1, Human = 0, }");
1235
1236 // (public) (table/struct/enum)
1237 schemas.push_back(
1238 "table Monster { mana: int; }"
1239 "struct ABC { mana: int; }"
1240 "enum Race:byte { None = -1, Human = 0, }");
1241
1242 // (private) (union) containing (private) (table/struct)
1243 schemas.push_back(
1244 "table Monster (private) { mana: int; }"
1245 "struct ABC (private) { mana: int; }"
1246 "enum Race:byte (private) { None = -1, Human = 0, }"
1247 "union Any (private) { Monster, ABC }");
1248
1249 // (public) (union) containing (public) (table/struct)
1250 schemas.push_back(
1251 "table Monster { mana: int; }"
1252 "struct ABC { mana: int; }"
1253 "enum Race:byte { None = -1, Human = 0, }"
1254 "union Any { Monster, ABC }");
1255
1256 // (private) (table), (public struct)
1257 schemas.push_back(
1258 "table Monster (private) { mana: int; }"
1259 "struct ABC { mana: int; }");
1260
1261 // (private) (table), (public) (struct/enum)
1262 schemas.push_back(
1263 "table Monster (private) { mana: int; }"
1264 "struct ABC { mana: int; }"
1265 "enum Race:byte { None = -1, Human = 0, }");
1266
1267 // (public) (struct) containing (public) (enum)
1268 schemas.push_back(
1269 "enum Race:byte { None = -1, Human = 0, }"
1270 "table Monster { mana: int; }"
1271 "struct ABC { mana: int; type: Race; }");
1272
1273 // (public) (union) containing (private) (table) & (public) (struct)
1274 failure_schemas.push_back(
1275 "table Monster (private) { mana: int; }"
1276 "struct ABC { mana: int; }"
1277 "union Any { Monster, ABC }");
1278
1279 // (public) (union) containing (private) (table/struct)
1280 failure_schemas.push_back(
1281 "table Monster (private) { mana: int; }"
1282 "struct ABC (private) { mana: int; }"
1283 "enum Race:byte { None = -1, Human = 0, }"
1284 "union Any { Monster, ABC }");
1285
1286 // (public) (table) containing (private) (struct)
1287 failure_schemas.push_back(
1288 "table Monster { mana: int; ab: ABC; }"
1289 "struct ABC (private) { mana: int; }");
1290
1291 // (public) (struct) containing (private) (enum)
1292 failure_schemas.push_back(
1293 "enum Race:byte (private) { None = -1, Human = 0, }"
1294 "table Monster { mana: int; }"
1295 "struct ABC { mana: int; type: Race; }");
1296
1297 flatbuffers::IDLOptions opts;
1298 opts.lang_to_generate = flatbuffers::IDLOptions::Language::kSwift;
1299 opts.no_leak_private_annotations = true;
1300
1301 for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1302 flatbuffers::Parser parser(opts);
1303 TEST_ASSERT(parser.Parse(schema->c_str()));
1304 }
1305
1306 for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1307 schema++) {
1308 flatbuffers::Parser parser(opts);
1309 TEST_EQ(false, parser.Parse(schema->c_str()));
1310 }
1311
1312 opts.no_leak_private_annotations = false;
1313
1314 for (auto schema = schemas.begin(); schema < schemas.end(); schema++) {
1315 flatbuffers::Parser parser(opts);
1316 TEST_ASSERT(parser.Parse(schema->c_str()));
1317 }
1318
1319 for (auto schema = failure_schemas.begin(); schema < failure_schemas.end();
1320 schema++) {
1321 flatbuffers::Parser parser(opts);
1322 TEST_ASSERT(parser.Parse(schema->c_str()));
1323 }
1324}
1325
1326void VectorSpanTest() {
1327 flatbuffers::FlatBufferBuilder builder;
1328
1329 auto mloc = CreateMonster(
1330 builder, nullptr, 0, 0, builder.CreateString("Monster"),
1331 builder.CreateVector<uint8_t>({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
1332
1333 FinishMonsterBuffer(builder, mloc);
1334
1335 auto monster = GetMonster(builder.GetBufferPointer());
1336 auto mutable_monster = GetMutableMonster(builder.GetBufferPointer());
1337
1338 { // using references
1339 TEST_NOTNULL(monster->inventory());
1340
1341 flatbuffers::span<const uint8_t> const_inventory =
1342 flatbuffers::make_span(*monster->inventory());
1343 TEST_EQ(const_inventory.size(), 10);
1344 TEST_EQ(const_inventory[0], 0);
1345 TEST_EQ(const_inventory[9], 9);
1346
1347 flatbuffers::span<uint8_t> mutable_inventory =
1348 flatbuffers::make_span(*mutable_monster->mutable_inventory());
1349 TEST_EQ(mutable_inventory.size(), 10);
1350 TEST_EQ(mutable_inventory[0], 0);
1351 TEST_EQ(mutable_inventory[9], 9);
1352
1353 mutable_inventory[0] = 42;
1354 TEST_EQ(mutable_inventory[0], 42);
1355
1356 mutable_inventory[0] = 0;
1357 TEST_EQ(mutable_inventory[0], 0);
1358 }
1359
1360 { // using pointers
1361 TEST_EQ(flatbuffers::VectorLength(monster->inventory()), 10);
1362
1363 flatbuffers::span<const uint8_t> const_inventory =
1364 flatbuffers::make_span(monster->inventory());
1365 TEST_EQ(const_inventory.size(), 10);
1366 TEST_EQ(const_inventory[0], 0);
1367 TEST_EQ(const_inventory[9], 9);
1368
1369 flatbuffers::span<uint8_t> mutable_inventory =
1370 flatbuffers::make_span(mutable_monster->mutable_inventory());
1371 TEST_EQ(mutable_inventory.size(), 10);
1372 TEST_EQ(mutable_inventory[0], 0);
1373 TEST_EQ(mutable_inventory[9], 9);
1374
1375 mutable_inventory[0] = 42;
1376 TEST_EQ(mutable_inventory[0], 42);
1377
1378 mutable_inventory[0] = 0;
1379 TEST_EQ(mutable_inventory[0], 0);
1380 }
1381
1382 {
1383 TEST_ASSERT(nullptr == monster->testnestedflatbuffer());
1384
1385 TEST_EQ(flatbuffers::VectorLength(monster->testnestedflatbuffer()), 0);
1386
1387 flatbuffers::span<const uint8_t> const_nested =
1388 flatbuffers::make_span(monster->testnestedflatbuffer());
1389 TEST_ASSERT(const_nested.empty());
1390
1391 flatbuffers::span<uint8_t> mutable_nested =
1392 flatbuffers::make_span(mutable_monster->mutable_testnestedflatbuffer());
1393 TEST_ASSERT(mutable_nested.empty());
1394 }
1395}
1396
1397void NativeInlineTableVectorTest() {
1398 TestNativeInlineTableT test;
1399 for (int i = 0; i < 10; ++i) {
1400 NativeInlineTableT t;
1401 t.a = i;
1402 test.t.push_back(t);
1403 }
1404
1405 flatbuffers::FlatBufferBuilder fbb;
1406 auto offset = TestNativeInlineTable::Pack(fbb, &test);
1407 fbb.Finish(offset);
1408
1409 auto *root =
1410 flatbuffers::GetRoot<TestNativeInlineTable>(fbb.GetBufferPointer());
1411 TestNativeInlineTableT unpacked;
1412 root->UnPackTo(&unpacked);
1413
1414 for (int i = 0; i < 10; ++i) {
1415 TEST_ASSERT(unpacked.t[i] == test.t[i]);
1416 }
1417
1418 TEST_ASSERT(unpacked.t == test.t);
1419}
1420
James Kuszmaul3b15b0c2022-11-08 14:03:16 -08001421void DoNotRequireEofTest(const std::string& tests_data_path) {
1422 std::string schemafile;
1423 bool ok = flatbuffers::LoadFile(
1424 (tests_data_path + "monster_test.fbs").c_str(), false, &schemafile);
1425 TEST_EQ(ok, true);
1426 auto include_test_path =
1427 flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
1428 const char *include_directories[] = { tests_data_path.c_str(),
1429 include_test_path.c_str(), nullptr };
1430 flatbuffers::IDLOptions opt;
1431 opt.require_json_eof = false;
1432 flatbuffers::Parser parser(opt);
1433 ok = parser.Parse(schemafile.c_str(), include_directories);
1434 TEST_EQ(ok, true);
1435
1436 const char *str = R"(This string contains two monsters, the first one is {
1437 "name": "Blob",
1438 "hp": 5
1439 }
1440 and the second one is {
1441 "name": "Imp",
1442 "hp": 10
1443 }
1444 )";
1445 const char *tableStart = std::strchr(str, '{');
1446 ok = parser.ParseJson(tableStart);
1447 TEST_EQ(ok, true);
1448
1449 const Monster *monster = GetMonster(parser.builder_.GetBufferPointer());
1450 TEST_EQ_STR(monster->name()->c_str(), "Blob");
1451 TEST_EQ(monster->hp(), 5);
1452
1453 tableStart += parser.BytesConsumed();
1454
1455 tableStart = std::strchr(tableStart + 1, '{');
1456 ok = parser.ParseJson(tableStart);
1457 TEST_EQ(ok, true);
1458
1459 monster = GetMonster(parser.builder_.GetBufferPointer());
1460 TEST_EQ_STR(monster->name()->c_str(), "Imp");
1461 TEST_EQ(monster->hp(), 10);
1462}
1463
Austin Schuh2dd86a92022-09-14 21:19:23 -07001464int FlatBufferTests(const std::string &tests_data_path) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001465 // Run our various test suites:
1466
1467 std::string rawbuf;
1468 auto flatbuf1 = CreateFlatBufferTest(rawbuf);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001469 auto flatbuf = std::move(flatbuf1); // Test move assignment.
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001470
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001471 AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()),
1472 rawbuf.length());
1473 AccessFlatBufferTest(flatbuf.data(), flatbuf.size());
1474
1475 MutateFlatBuffersTest(flatbuf.data(), flatbuf.size());
1476
1477 ObjectFlatBuffersTest(flatbuf.data());
Austin Schuh2dd86a92022-09-14 21:19:23 -07001478 UnPackTo(flatbuf.data());
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001479
1480 MiniReflectFlatBuffersTest(flatbuf.data());
Austin Schuh272c6132020-11-14 16:37:52 -08001481 MiniReflectFixedLengthArrayTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001482
1483 SizePrefixedTest();
1484
James Kuszmaul3b15b0c2022-11-08 14:03:16 -08001485 AlignmentTest();
1486
Austin Schuh2dd86a92022-09-14 21:19:23 -07001487#ifndef FLATBUFFERS_NO_FILE_TESTS
1488 ParseAndGenerateTextTest(tests_data_path, false);
1489 ParseAndGenerateTextTest(tests_data_path, true);
1490 FixedLengthArrayJsonTest(tests_data_path, false);
1491 FixedLengthArrayJsonTest(tests_data_path, true);
1492 ReflectionTest(tests_data_path, flatbuf.data(), flatbuf.size());
1493 ParseProtoTest(tests_data_path);
1494 ParseProtoTestWithSuffix(tests_data_path);
1495 ParseProtoTestWithIncludes(tests_data_path);
1496 EvolutionTest(tests_data_path);
1497 UnionDeprecationTest(tests_data_path);
1498 UnionVectorTest(tests_data_path);
1499 GenerateTableTextTest(tests_data_path);
1500 TestEmbeddedBinarySchema(tests_data_path);
1501 JsonOptionalTest(tests_data_path, false);
1502 JsonOptionalTest(tests_data_path, true);
1503 MultiFileNameClashTest(tests_data_path);
1504 InvalidNestedFlatbufferTest(tests_data_path);
1505 JsonDefaultTest(tests_data_path);
1506 JsonEnumsTest(tests_data_path);
1507 TestMonsterExtraFloats(tests_data_path);
1508 ParseIncorrectMonsterJsonTest(tests_data_path);
1509 FixedLengthArraySpanTest(tests_data_path);
James Kuszmaul3b15b0c2022-11-08 14:03:16 -08001510 DoNotRequireEofTest(tests_data_path);
Austin Schuh2dd86a92022-09-14 21:19:23 -07001511#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001512
James Kuszmaul8e62b022022-03-22 09:33:25 -07001513 UtilConvertCase();
1514
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001515 FuzzTest1();
1516 FuzzTest2();
1517
Austin Schuh2dd86a92022-09-14 21:19:23 -07001518 TriviallyCopyableTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001519 ErrorTest();
1520 ValueTest();
1521 EnumValueTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001522 NestedListTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001523 EnumStringsTest();
1524 EnumNamesTest();
1525 EnumOutOfRangeTest();
1526 IntegerOutOfRangeTest();
1527 IntegerBoundaryTest();
1528 UnicodeTest();
1529 UnicodeTestAllowNonUTF8();
1530 UnicodeTestGenerateTextFailsOnNonUTF8();
1531 UnicodeSurrogatesTest();
1532 UnicodeInvalidSurrogatesTest();
1533 InvalidUTF8Test();
1534 UnknownFieldsTest();
1535 ParseUnionTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001536 ValidSameNameDifferentNamespaceTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001537 ConformTest();
1538 ParseProtoBufAsciiTest();
1539 TypeAliasesTest();
1540 EndianSwapTest();
1541 CreateSharedStringTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001542 FlexBuffersTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001543 FlexBuffersReuseBugTest();
Austin Schuh272c6132020-11-14 16:37:52 -08001544 FlexBuffersDeprecatedTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001545 UninitializedVectorTest();
1546 EqualOperatorTest();
1547 NumericUtilsTest();
1548 IsAsciiUtilsTest();
1549 ValidFloatTest();
1550 InvalidFloatTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001551 FixedLengthArrayTest();
1552 NativeTypeTest();
Austin Schuh272c6132020-11-14 16:37:52 -08001553 OptionalScalarsTest();
1554 ParseFlexbuffersFromJsonWithNullTest();
1555 FlatbuffersSpanTest();
1556 FixedLengthArrayConstructorTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001557 FieldIdentifierTest();
1558 StringVectorDefaultsTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001559 FlexBuffersFloatingPointTest();
1560 FlatbuffersIteratorsTest();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001561 WarningsAsErrorsTest();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001562 NestedVerifierTest();
1563 PrivateAnnotationsLeaks();
1564 JsonUnsortedArrayTest();
1565 VectorSpanTest();
1566 NativeInlineTableVectorTest();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001567 return 0;
1568}
Austin Schuh2dd86a92022-09-14 21:19:23 -07001569} // namespace
1570} // namespace tests
1571} // namespace flatbuffers
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001572
James Kuszmaul8e62b022022-03-22 09:33:25 -07001573int main(int argc, const char *argv[]) {
Austin Schuh2dd86a92022-09-14 21:19:23 -07001574 std::string tests_data_path =
1575#ifdef BAZEL_TEST_DATA_PATH
1576 "../com_github_google_flatbuffers/tests/";
1577#else
1578 "tests/";
1579#endif
1580
James Kuszmaul8e62b022022-03-22 09:33:25 -07001581 for (int argi = 1; argi < argc; argi++) {
1582 std::string arg = argv[argi];
1583 if (arg == "--test_path") {
1584 if (++argi >= argc) {
1585 fprintf(stderr, "error: missing path following: %s\n", arg.c_str());
1586 exit(1);
1587 }
Austin Schuh2dd86a92022-09-14 21:19:23 -07001588 // Override default path if provided one.
1589 tests_data_path = argv[argi];
1590
James Kuszmaul8e62b022022-03-22 09:33:25 -07001591 } else {
1592 fprintf(stderr, "error: Unknown argument: %s\n", arg.c_str());
1593 exit(1);
1594 }
1595 }
1596
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001597 InitTestEngine();
1598
1599 std::string req_locale;
1600 if (flatbuffers::ReadEnvironmentVariable("FLATBUFFERS_TEST_LOCALE",
1601 &req_locale)) {
1602 TEST_OUTPUT_LINE("The environment variable FLATBUFFERS_TEST_LOCALE=%s",
1603 req_locale.c_str());
1604 req_locale = flatbuffers::RemoveStringQuotes(req_locale);
1605 std::string the_locale;
1606 TEST_ASSERT_FUNC(
1607 flatbuffers::SetGlobalTestLocale(req_locale.c_str(), &the_locale));
1608 TEST_OUTPUT_LINE("The global C-locale changed: %s", the_locale.c_str());
1609 }
1610
Austin Schuh2dd86a92022-09-14 21:19:23 -07001611#ifdef FLATBUFFERS_TEST_PATH_PREFIX
1612 tests_data_path =
1613 FLATBUFFERS_STRING(FLATBUFFERS_TEST_PATH_PREFIX) + tests_data_path;
1614#endif
1615
1616 flatbuffers::tests::FlatBufferTests(tests_data_path);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001617 FlatBufferBuilderTest();
1618
1619 if (!testing_fails) {
1620 TEST_OUTPUT_LINE("ALL TESTS PASSED");
1621 } else {
1622 TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
1623 }
1624 return CloseTestEngine();
1625}