-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
[C++] Adds basic schema evolution tests #5611
Conversation
King, | ||
Queen | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum(union) without at least one explicit value isn't a good example for a scheme with evolution.
The left-added value will break the schema.
enum Enum : byte {
Person, // 0
King, // 1, was 0
Queen // 2, was 1
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is just looking at properly evolved schema changes. I suggest another PR for testing cases where the schema are not evolved properly (like your Person example above).
Nice! This will be good to have. Of course, the test coverage we get out of a correct schema evolution is minimal, since this already a fairly common path. Testing incorrectness is harder, and would almost be done better with some kind of fuzzing approach (see the C++ tests that randomly generate schemas at runtime)? Also of note is Whenever possible, I'd prefer for such tests to work at runtime (do not generate code), just to keep the bulk of test files under control. |
Part of this is to test the runtime verifiers as well, as there was a bug in the verifier when a Union was evolved. |
Looks like some of the CI errors may be related to this PR |
For the Xcode issue in travis I see: "ld: library not found for -lgrpc++_unsecure So it looks like a linking error that shouldn't be impacted by this PR. I did see a previous error about the Enum value 3 not be valid in the verifier (though the current issue masks this), but that seems like a bug in the verifier to me. Especially since it works in all the other environments. |
I see:
Instead of snprintf, maybe use |
That's odd, I don't see that. Maybe you have a different view into Travis than non owners? Or I might just be looking into the wrong place. I'll explore using |
Do you not see AppVeyor test results? I thought that information is the same for everyone. Can you see: https://ci.appveyor.com/project/google-admin/flatbuffers/builds/28618031 Not sure what that "google-admin" is doing in there, maybe that is the source of the problem? |
I see those results. So it was user error, I was just looking at the wrong place. |
19b602f
to
3863fd1
Compare
For the XCode build I see the following error:
Which is seemingly failing because the V1 of the schema doesn't contain an enum value of 3 (which was added in the V2 of the schema). But all the other builds are fine, so I am confused on why it would fail in this configuration. |
XCode build uses |
3863fd1
to
0fdcd90
Compare
Thanks for the pointer, I'll try it out. Won't the |
e53a08b
to
bfd292e
Compare
I have installed clang9. auto v_d = root_v2_viewed_from_v1->d(); // ubsan catches here
TEST_EQ(v_d, 3); The auto v_d = static_cast<int8_t>(root_v2_viewed_from_v1->d());
TEST_EQ(v_d, 3); |
Thanks for looking into this. But isn't this a problem for forward compatibility? Reading an evolved schema causes an exception even though it is valid? @aardappel you might have some opinions. |
bfd292e
to
e81bcdb
Compare
There are two points of view on this issue:
The first is trivial and described by the C++ standard (C++17, 10.2.8):
The enum By the standard:
The UBSAN catches that UB in runtime. Lines 1605 to 1613 in 33d5dd9
|
The second is a consequence of first: Example of well-declared enum: enum Enum : int32 { King =0, Queen, } This enum has the fixed underlying type and at least one fixed value. There are two (thee) possible ways to map this fbs-declaration into C++ code:
Now, the third is enabled if From my point of view enums without a fixed underlying type must be deprecated both in schemas and C++. |
I don't believe the test is ill-formed, I never explicitly write a value that is not valid in its current context. Both the V1 and V2 buffers are valid according to their schema. The issue arises when reading those buffers with older versions of the schema. Reading a valid buffer with an older schema shouldn't cause any exceptions/UB to be occur, but it appears to happen is the case. But only in the case of using C++17 according to the information you provide. And that's why only the XCode configuration was catching it. So these test did expose a real compatibility error. Perhaps the generated getters for enum values should not cast the underlying type to the enum type, but just return the underlying type as is. This will at least prevent flatbuffers from being the code that is causing the UB. Also, the
Are you also suggesting that option |
Yes, generated enums must be declared as fixed type enums. The cast (or initialization) from an integer to an enum without the fixed type is a problem in all versions of C++. C++11 standard (2013, N3690):
|
We have to somehow be able to support values outside of enum range, so we have to work around any UB issues. Our current minspec of VS2010 is arbitrary, as that seemed sensible at the time. FlatBuffers is widely enough used that it is valuable to keep supporting older C++. That said, we can start working towards flipping defaults for the most painful features. For |
Sound good to me. I'll probably add the |
I suggest add a enum Enum : int32_t { King=0, Queen} Additionally, if this flag isn't active, |
Maybe we want a more general Problem with enums is that there are reasons why even under a newer compiler one might prefer the old style enums, if you are using them very much like integers or bit-flags (new ones require hacks like |
The enum name : type { enumerator = constexpr , enumerator = constexpr , ... }
I'm working with this, a PR isn't ready yet. |
@vglavnyy ok sgtm, I await your new flags :) |
Thanks! |
This merge broke the tests under MSVC2019.
Problem is here: TEST_EQ(root_v1_viewed_from_v2->j(), NULL);
TEST_EQ(root_v1_viewed_from_v2->e()->c(), NULL);
TEST_EQ(root_v1_viewed_from_v2->c_as_TableC(), NULL); The TEST_ASSERT(nullptr == root_v1_viewed_from_v2->j()); @dbaileychess Could you fix this? Update:
line 2345: verifiers[i] = new flatbuffers::Verifier(&binaries[i].front(), bufLen); Why raw pointers are used instead of |
Leak-sanitizer added to CI: |
* Add flatc '--cpp_std' switch and sandbox for C++17 code generator - Added 'flac --cpp_std legacy' for compatibility with old compilers (VS2010); - Added experimental switch 'flac --cpp_std c++17' for future development; - Added C++17 sandbox test_cpp17.cpp; - C++ code generator generates enums with explicit underlying type to avoid problems with the forward and backward schema compatibility; - Adjusted CMakeLists.txt, CI and generate code scripts to support of introduced '--cpp_std'; * Fix --cpp_std values: c++0x, c++11, c++17 * Add 'cpp::CppStandard' enum * Add testing engine into test_cpp17 * Rebase to upstream/master * Set default '--cpp-std C++0x' * Fix code generation (--cpp_std C++11) in CMakeLists.txt - Fix dependency declaration of grpctest target * Revert --cpp-std for the tests from explicit C++11 to flatc default value (C++0x)
* 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 change adds some basic schema evolution tests in C++. It verifies that the proper evolution of a schema is valid in a backwards- and forwards-compatible manner. It also checks that the
Verifiers
for the multiple versions of the schema can correctly read new and old data.It adds two schema, that are properly evolved from each other. The second version of the schema is annotated with the changes from the first version. The generated C++ headers for those schema are also included.
I tried to test the most common evolution points:
id
attributeTests:
flattest
runs successfully.For a follow up to this PR, tests should be added to test improper evolution of schema.
I would also take suggestions on other tests that should be performed.