summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2019-12-23 11:12:41 -0800
committerWouter van Oortmerssen <aardappel@gmail.com>2019-12-23 11:49:59 -0800
commit3e8f15df908c31b4c52308b621fed490cbac2ccc (patch)
tree657365aa0fc64f7932f7e90eaa7e9ff5617a4e4d /tests
parent602721a7355a3193a6770450d4ed082b6ba0f70f (diff)
downloadflatbuffers-3e8f15df908c31b4c52308b621fed490cbac2ccc.tar.gz
flatbuffers-3e8f15df908c31b4c52308b621fed490cbac2ccc.tar.bz2
flatbuffers-3e8f15df908c31b4c52308b621fed490cbac2ccc.zip
Fix for FlexBuffers FBT_VECTOR_STRING size bit-width.
For details, test.cpp/FlexBuffersDeprecatedTest(), and also https://github.com/google/flatbuffers/issues/5627 Change-Id: I6e86e1138a5777e31055cfa2f79276d44732efbc
Diffstat (limited to 'tests')
-rw-r--r--tests/test.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/test.cpp b/tests/test.cpp
index 80c18768..cc6086a9 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -2813,6 +2813,68 @@ void FlexBuffersTest() {
TEST_EQ_STR(jsontest, jsonback.c_str());
}
+void FlexBuffersDeprecatedTest() {
+ // FlexBuffers as originally designed had a flaw involving the
+ // FBT_VECTOR_STRING datatype, and this test documents/tests the fix for it.
+ // Discussion: https://github.com/google/flatbuffers/issues/5627
+ flexbuffers::Builder slb;
+ // FBT_VECTOR_* are "typed vectors" where all elements are of the same type.
+ // Problem is, when storing FBT_STRING elements, it relies on that type to
+ // get the bit-width for the size field of the string, which in this case
+ // isn't present, and instead defaults to 8-bit. This means that any strings
+ // stored inside such a vector, when accessed thru the old API that returns
+ // a String reference, will appear to be truncated if the string stored is
+ // actually >=256 bytes.
+ std::string test_data(300, 'A');
+ auto start = slb.StartVector();
+ // This one will have a 16-bit size field.
+ slb.String(test_data);
+ // This one will have an 8-bit size field.
+ slb.String("hello");
+ // We're asking this to be serialized as a typed vector (true), but not
+ // fixed size (false). The type will be FBT_VECTOR_STRING with a bit-width
+ // of whatever the offsets in the vector need, the bit-widths of the strings
+ // are not stored(!) <- the actual design flaw.
+ // Note that even in the fixed code, we continue to serialize the elements of
+ // FBT_VECTOR_STRING as FBT_STRING, since there may be old code out there
+ // reading new data that we want to continue to function.
+ // Thus, FBT_VECTOR_STRING, while deprecated, will always be represented the
+ // same way, the fix lies on the reading side.
+ slb.EndVector(start, true, false);
+ slb.Finish();
+ // So now lets read this data back.
+ // For existing data, since we have no way of knowing what the actual
+ // bit-width of the size field of the string is, we are going to ignore this
+ // field, and instead treat these strings as FBT_KEY (null-terminated), so we
+ // can deal with strings of arbitrary length. This of course truncates strings
+ // with embedded nulls, but we think that that is preferrable over truncating
+ // strings >= 256 bytes.
+ auto vec = flexbuffers::GetRoot(slb.GetBuffer()).AsTypedVector();
+ // Even though this was serialized as FBT_VECTOR_STRING, it is read as
+ // FBT_VECTOR_KEY:
+ TEST_EQ(vec.ElementType(), flexbuffers::FBT_KEY);
+ // Access the long string. Previously, this would return a string of size 1,
+ // since it would read the high-byte of the 16-bit length.
+ // This should now correctly test the full 300 bytes, using AsKey():
+ TEST_EQ_STR(vec[0].AsKey(), test_data.c_str());
+ // Old code that called AsString will continue to work, as the String
+ // accessor objects now use a cached size that can come from a key as well.
+ TEST_EQ_STR(vec[0].AsString().c_str(), test_data.c_str());
+ // Short strings work as before:
+ TEST_EQ_STR(vec[1].AsKey(), "hello");
+ TEST_EQ_STR(vec[1].AsString().c_str(), "hello");
+ // So, while existing code and data mostly "just work" with the fixes applied
+ // to AsTypedVector and AsString, what do you do going forward?
+ // Code accessing existing data doesn't necessarily need to change, though
+ // you could consider using AsKey instead of AsString for a) documenting
+ // that you are accessing keys, or b) a speedup if you don't actually use
+ // the string size.
+ // For new data, or data that doesn't need to be backwards compatible,
+ // instead serialize as FBT_VECTOR (call EndVector with typed = false, then
+ // read elements with AsString), or, for maximum compactness, use
+ // FBT_VECTOR_KEY (call slb.Key above instead, read with AsKey or AsString).
+}
+
void TypeAliasesTest() {
flatbuffers::FlatBufferBuilder builder;
@@ -3237,6 +3299,7 @@ int FlatBufferTests() {
JsonDefaultTest();
JsonEnumsTest();
FlexBuffersTest();
+ FlexBuffersDeprecatedTest();
UninitializedVectorTest();
EqualOperatorTest();
NumericUtilsTest();