[C++] Adds basic schema evolution tests (#5611)

* Added basic schema evolution tests

* Add BUILD targets for evolution tests. Added to test/generate_code scripts

* Use vector.front() instead of vector.data()

* Added --scoped-enums option for evolution test
This commit is contained in:
Derek Bailey
2019-11-14 15:44:18 -08:00
committed by Wouter van Oortmerssen
parent adbcbba5d1
commit dda095023d
10 changed files with 1261 additions and 0 deletions

View File

@@ -37,6 +37,8 @@
#include "monster_extra_generated.h"
#if !defined(_MSC_VER) || _MSC_VER >= 1700
# include "arrays_test_generated.h"
# include "evolution_test/evolution_v1_generated.h"
# include "evolution_test/evolution_v2_generated.h"
#endif
#include "native_type_test_generated.h"
@@ -2310,6 +2312,76 @@ void InvalidNestedFlatbufferTest() {
false);
}
void EvolutionTest() {
// 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::Verifier *verifiers[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 = test_data_path + "evolution_test/evolution_v" +
flatbuffers::NumToString(i + 1) + ".fbs";
TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
std::string json = test_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]));
verifiers[i] = new flatbuffers::Verifier(&binaries[i].front(), bufLen);
}
// Assert that all the verifiers for the different schema versions properly verify any version data.
for (int i = 0; i < NUM_VERSIONS; ++i) {
TEST_ASSERT(Evolution::V1::VerifyRootBuffer(*verifiers[i]));
TEST_ASSERT(Evolution::V2::VerifyRootBuffer(*verifiers[i]));
}
// Test backwards compatibility by reading old data with an evolved schema.
auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front());
// field 'j' is new in version 2, so it should be null.
TEST_EQ(root_v1_viewed_from_v2->j(), NULL);
// field 'k' is new in version 2 with a default of 56.
TEST_EQ(root_v1_viewed_from_v2->k(), 56);
// field 'c' of 'TableA' is new in version 2, so it should be null.
TEST_EQ(root_v1_viewed_from_v2->e()->c(), NULL);
// 'TableC' was added to field 'c' union in version 2, so it should be null.
TEST_EQ(root_v1_viewed_from_v2->c_as_TableC(), NULL);
// 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 UnionVectorTest() {
// load FlatBuffer fbs schema and json.
std::string schemafile, jsonfile;
@@ -3070,6 +3142,7 @@ int FlatBufferTests() {
FixedLengthArrayJsonTest(true);
ReflectionTest(flatbuf.data(), flatbuf.size());
ParseProtoTest();
EvolutionTest();
UnionVectorTest();
LoadVerifyBinaryTest();
GenerateTableTextTest();