Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor test.cpp #7487

Merged
merged 18 commits into from Aug 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions CMakeLists.txt
Expand Up @@ -87,6 +87,14 @@ if(MSVC OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
set(MSVC_LIKE ON)
endif()

if(DEFINED FLATBUFFERS_COMPILATION_TIMINGS)
message("Recording Compilation Timings to ${FLATBUFFERS_COMPILATION_TIMINGS}")
file(REMOVE ${FLATBUFFERS_COMPILATION_TIMINGS})
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "time -f 'Wall: %E User: %U Sys: %S | %C' -q -a -o ${FLATBUFFERS_COMPILATION_TIMINGS}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_CUSTOM "time -f 'Wall: %E User: %U Sys: %S | %C' -q -a -o ${FLATBUFFERS_COMPILATION_TIMINGS}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "time -f 'Wall: %E User: %U Sys: %S | %C' -q -a -o ${FLATBUFFERS_COMPILATION_TIMINGS}")
endif()

if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
message(WARNING
"Cannot build tests without building the compiler. Tests will be disabled.")
Expand Down Expand Up @@ -205,11 +213,21 @@ set(FlatHash_SRCS
set(FlatBuffers_Tests_SRCS
${FlatBuffers_Library_SRCS}
src/idl_gen_fbs.cpp
tests/evolution_test.cpp
tests/flexbuffers_test.cpp
tests/fuzz_test.cpp
tests/json_test.cpp
tests/monster_test.cpp
tests/optional_scalars_test.cpp
tests/parser_test.cpp
tests/proto_test.cpp
tests/reflection_test.cpp
tests/test.cpp
tests/test_assert.h
tests/test_assert.cpp
tests/test_builder.h
tests/test_builder.cpp
tests/util_test.cpp
tests/native_type_test_impl.h
tests/native_type_test_impl.cpp
include/flatbuffers/code_generators.h
Expand Down
21 changes: 21 additions & 0 deletions tests/BUILD.bazel
Expand Up @@ -9,20 +9,41 @@ cc_test(
name = "flatbuffers_test",
testonly = 1,
srcs = [
"evolution_test.cpp",
"evolution_test.h",
"evolution_test/evolution_v1_generated.h",
"evolution_test/evolution_v2_generated.h",
"flexbuffers_test.cpp",
"flexbuffers_test.h",
"fuzz_test.cpp",
"fuzz_test.h",
"is_quiet_nan.h",
"json_test.cpp",
"json_test.h",
"monster_test.cpp",
"monster_test.h",
"monster_test_bfbs_generated.h",
"namespace_test/namespace_test1_generated.h",
"namespace_test/namespace_test2_generated.h",
"native_type_test_impl.cpp",
"native_type_test_impl.h",
"optional_scalars_generated.h",
"optional_scalars_test.cpp",
"optional_scalars_test.h",
"parser_test.cpp",
"parser_test.h",
"proto_test.cpp",
"proto_test.h",
"reflection_test.cpp",
"reflection_test.h",
"test.cpp",
"test_assert.cpp",
"test_assert.h",
"test_builder.cpp",
"test_builder.h",
"union_vector/union_vector_generated.h",
"util_test.cpp",
"util_test.h",
],
copts = [
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
Expand Down
139 changes: 139 additions & 0 deletions tests/evolution_test.cpp
@@ -0,0 +1,139 @@
#include "evolution_test.h"

#include "evolution_test/evolution_v1_generated.h"
#include "evolution_test/evolution_v2_generated.h"
#include "flatbuffers/idl.h"
#include "test_assert.h"

namespace flatbuffers {
namespace tests {

void EvolutionTest(const std::string &tests_data_path) {
// VS10 does not support typed enums, exclude from tests
#if !defined(_MSC_VER) || _MSC_VER >= 1700
const int NUM_VERSIONS = 2;
std::string schemas[NUM_VERSIONS];
std::string jsonfiles[NUM_VERSIONS];
std::vector<uint8_t> binaries[NUM_VERSIONS];

flatbuffers::IDLOptions idl_opts;
idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
flatbuffers::Parser parser(idl_opts);

// Load all the schema versions and their associated data.
for (int i = 0; i < NUM_VERSIONS; ++i) {
std::string schema = tests_data_path + "evolution_test/evolution_v" +
flatbuffers::NumToString(i + 1) + ".fbs";
TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
std::string json = tests_data_path + "evolution_test/evolution_v" +
flatbuffers::NumToString(i + 1) + ".json";
TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));

TEST_ASSERT(parser.Parse(schemas[i].c_str()));
TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));

auto bufLen = parser.builder_.GetSize();
auto buf = parser.builder_.GetBufferPointer();
binaries[i].reserve(bufLen);
std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
}

// Assert that all the verifiers for the different schema versions properly
// verify any version data.
for (int i = 0; i < NUM_VERSIONS; ++i) {
flatbuffers::Verifier verifier(&binaries[i].front(), binaries[i].size());
TEST_ASSERT(Evolution::V1::VerifyRootBuffer(verifier));
TEST_ASSERT(Evolution::V2::VerifyRootBuffer(verifier));
}

// Test backwards compatibility by reading old data with an evolved schema.
auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front());
// field 'k' is new in version 2, so it should be null.
TEST_ASSERT(nullptr == root_v1_viewed_from_v2->k());
// field 'l' is new in version 2 with a default of 56.
TEST_EQ(root_v1_viewed_from_v2->l(), 56);
// field 'c' of 'TableA' is new in version 2, so it should be null.
TEST_ASSERT(nullptr == root_v1_viewed_from_v2->e()->c());
// 'TableC' was added to field 'c' union in version 2, so it should be null.
TEST_ASSERT(nullptr == root_v1_viewed_from_v2->c_as_TableC());
// The field 'c' union should be of type 'TableB' regardless of schema version
TEST_ASSERT(root_v1_viewed_from_v2->c_type() == Evolution::V2::Union::TableB);
// The field 'f' was renamed to 'ff' in version 2, it should still be
// readable.
TEST_EQ(root_v1_viewed_from_v2->ff()->a(), 16);

// Test forwards compatibility by reading new data with an old schema.
auto root_v2_viewed_from_v1 = Evolution::V1::GetRoot(&binaries[1].front());
// The field 'c' union in version 2 is a new table (index = 3) and should
// still be accessible, but not interpretable.
TEST_EQ(static_cast<uint8_t>(root_v2_viewed_from_v1->c_type()), 3);
TEST_NOTNULL(root_v2_viewed_from_v1->c());
// The field 'd' enum in verison 2 has new members and should still be
// accessible, but not interpretable.
TEST_EQ(static_cast<int8_t>(root_v2_viewed_from_v1->d()), 3);
// The field 'a' in version 2 is deprecated and should return the default
// value (0) instead of the value stored in the in the buffer (42).
TEST_EQ(root_v2_viewed_from_v1->a(), 0);
// The field 'ff' was originally named 'f' in version 1, it should still be
// readable.
TEST_EQ(root_v2_viewed_from_v1->f()->a(), 35);
#endif
}

void ConformTest() {
flatbuffers::Parser parser;
TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);

auto test_conform = [](flatbuffers::Parser &parser1, const char *test,
const char *expected_err) {
flatbuffers::Parser parser2;
TEST_EQ(parser2.Parse(test), true);
auto err = parser2.ConformTo(parser1);
TEST_NOTNULL(strstr(err.c_str(), expected_err));
};

test_conform(parser, "table T { A:byte; }", "types differ for field");
test_conform(parser, "table T { B:int; A:int; }", "offsets differ for field");
test_conform(parser, "table T { A:int = 1; }", "defaults differ for field");
test_conform(parser, "table T { B:float; }",
"field renamed to different type");
test_conform(parser, "enum E:byte { B, A }", "values differ for enum");
}

void UnionDeprecationTest(const std::string& tests_data_path) {
const int NUM_VERSIONS = 2;
std::string schemas[NUM_VERSIONS];
std::string jsonfiles[NUM_VERSIONS];
std::vector<uint8_t> binaries[NUM_VERSIONS];

flatbuffers::IDLOptions idl_opts;
idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
flatbuffers::Parser parser(idl_opts);

// Load all the schema versions and their associated data.
for (int i = 0; i < NUM_VERSIONS; ++i) {
std::string schema = tests_data_path + "evolution_test/evolution_v" +
flatbuffers::NumToString(i + 1) + ".fbs";
TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
std::string json = tests_data_path + "evolution_test/evolution_v" +
flatbuffers::NumToString(i + 1) + ".json";
TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));

TEST_ASSERT(parser.Parse(schemas[i].c_str()));
TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));

auto bufLen = parser.builder_.GetSize();
auto buf = parser.builder_.GetBufferPointer();
binaries[i].reserve(bufLen);
std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
}

auto v2 = parser.LookupStruct("Evolution.V2.Root");
TEST_NOTNULL(v2);
auto j_type_field = v2->fields.Lookup("j_type");
TEST_NOTNULL(j_type_field);
TEST_ASSERT(j_type_field->deprecated);
}

} // namespace tests
} // namespace flatbuffers
16 changes: 16 additions & 0 deletions tests/evolution_test.h
@@ -0,0 +1,16 @@
#ifndef TESTS_EVOLUTION_TEST_H
#define TESTS_EVOLUTION_TEST_H

#include <string>

namespace flatbuffers {
namespace tests {

void EvolutionTest(const std::string &tests_data_path);
void ConformTest();
void UnionDeprecationTest(const std::string &tests_data_path);

} // namespace tests
} // namespace flatbuffers

#endif