From 297a808535140e6ec691e3220f231d09b7c98155 Mon Sep 17 00:00:00 2001 From: Paul Quiring Date: Wed, 29 Jul 2026 16:14:10 +0200 Subject: [PATCH 1/2] Add tests flatbufferscpp library --- score/flatbuffers/BUILD | 17 +- ...est.cpp => flatbuffers_allocator_test.cpp} | 0 .../details/flatbuffers_array_test.cpp | 751 ++++++++ .../details/flatbuffers_base_test.cpp | 333 ++++ .../details/flatbuffers_buffer_ref_test.cpp | 159 ++ .../details/flatbuffers_buffer_test.cpp | 470 +++++ .../flatbuffers_default_allocator_test.cpp | 312 +++ .../flatbuffers_detached_buffer_test.cpp | 213 +++ .../flatbuffers_flatbuffer_builder_test.cpp | 1699 +++++++++++++++++ .../details/flatbuffers_flatbuffers_test.cpp | 272 +++ .../flatbuffers_stl_emulation_test.cpp | 306 +++ .../details/flatbuffers_string_test.cpp | 225 +++ .../details/flatbuffers_struct_test.cpp | 196 ++ .../details/flatbuffers_table_test.cpp | 276 +++ .../flatbuffers_vector_downward_test.cpp | 397 ++++ .../details/flatbuffers_vector_test.cpp | 351 ++++ .../details/flatbuffers_verifier_test.cpp | 351 ++++ 17 files changed, 6327 insertions(+), 1 deletion(-) rename score/flatbuffers/details/{flatfbuffer_allocator_test.cpp => flatbuffers_allocator_test.cpp} (100%) create mode 100644 score/flatbuffers/details/flatbuffers_array_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_base_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_buffer_ref_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_buffer_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_default_allocator_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_detached_buffer_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_flatbuffer_builder_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_flatbuffers_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_stl_emulation_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_string_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_struct_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_table_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_vector_downward_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_vector_test.cpp create mode 100644 score/flatbuffers/details/flatbuffers_verifier_test.cpp diff --git a/score/flatbuffers/BUILD b/score/flatbuffers/BUILD index fb087f4d91..73785b9c73 100644 --- a/score/flatbuffers/BUILD +++ b/score/flatbuffers/BUILD @@ -144,7 +144,22 @@ cc_test( name = "flatbuffers_cpp_library_test", testonly = True, srcs = [ - "details/flatfbuffer_allocator_test.cpp", + "details/flatbuffers_allocator_test.cpp", + "details/flatbuffers_array_test.cpp", + "details/flatbuffers_base_test.cpp", + "details/flatbuffers_buffer_ref_test.cpp", + "details/flatbuffers_buffer_test.cpp", + "details/flatbuffers_default_allocator_test.cpp", + "details/flatbuffers_detached_buffer_test.cpp", + "details/flatbuffers_flatbuffer_builder_test.cpp", + "details/flatbuffers_flatbuffers_test.cpp", + "details/flatbuffers_stl_emulation_test.cpp", + "details/flatbuffers_string_test.cpp", + "details/flatbuffers_struct_test.cpp", + "details/flatbuffers_table_test.cpp", + "details/flatbuffers_vector_downward_test.cpp", + "details/flatbuffers_vector_test.cpp", + "details/flatbuffers_verifier_test.cpp", ], deps = [ ":flatbufferscpp", diff --git a/score/flatbuffers/details/flatfbuffer_allocator_test.cpp b/score/flatbuffers/details/flatbuffers_allocator_test.cpp similarity index 100% rename from score/flatbuffers/details/flatfbuffer_allocator_test.cpp rename to score/flatbuffers/details/flatbuffers_allocator_test.cpp diff --git a/score/flatbuffers/details/flatbuffers_array_test.cpp b/score/flatbuffers/details/flatbuffers_array_test.cpp new file mode 100644 index 0000000000..e003088507 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_array_test.cpp @@ -0,0 +1,751 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/array.h" + +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Magic-number sentinels used across tests. +constexpr int32_t kFirstElement = 10; +constexpr int32_t kMiddleElement = 20; +constexpr int32_t kLastElement = 30; +constexpr int32_t kMutateValue = 42; + +// ------------------------------------------------------- +// Minimal Point struct used across tests. +// ------------------------------------------------------- +struct Point +{ + int32_t x; + int32_t y; + + bool operator==(const Point& other) const + { + return x == other.x && y == other.y; + } +}; + +// --------------------------------------------------------------------------- +// ArrayCastTest +// Tests casting raw C arrays to flatbuffers::Array. +// --------------------------------------------------------------------------- + +TEST(ArrayCastTest, CastToArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::CastToArray"); + RecordProperty("Description", "casting a raw C array to flatbuffers::Array preserves elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {10, 20, 30}; + auto& arr = CastToArray(raw); + EXPECT_EQ(arr.size(), 3u); + EXPECT_EQ(arr.Get(0), 10); + EXPECT_EQ(arr.Get(1), 20); + EXPECT_EQ(arr.Get(2), 30); + + int32_t raw1[1] = {42}; + auto& arr1 = CastToArray(raw1); + EXPECT_EQ(arr1.size(), 1u); + EXPECT_EQ(arr1.Get(0), 42); +} + +TEST(ArrayCastTest, CastToArrayConst) +{ + RecordProperty("FullyVerifies", "::flatbuffers::CastToArray"); + RecordProperty("Description", "const array cast produces a const-referenced Array"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + const int32_t raw[2] = {77, 88}; + const auto& arr = CastToArray(raw); + EXPECT_EQ(arr.size(), 2u); + EXPECT_EQ(arr.Get(0), 77); + EXPECT_EQ(arr.Get(1), 88); +} + +// --------------------------------------------------------------------------- +// ArrayIndexTest +// Tests Array::operator[]. +// --------------------------------------------------------------------------- + +TEST(ArrayIndexTest, ReturnsSameAsGet) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::operator[]"); + RecordProperty("Description", "operator[] returns same value as Get for every index"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + uint16_t raw[4] = {100, 200, 300, 400}; + auto& arr = CastToArray(raw); + for (uint16_t i = 0; i < arr.size(); ++i) + { + EXPECT_EQ(arr[i], arr.Get(i)); + } +} + +// --------------------------------------------------------------------------- +// ArrayMutateTest +// Tests Array::Mutate. +// --------------------------------------------------------------------------- + +TEST(ArrayMutateTest, ScalarInPlaceMutation) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Mutate, ::flatbuffers::Array::MutateImpl(true_type)"); + RecordProperty("Description", "in-place mutation of scalar array elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + int32_t raw[3] = {1, 2, 3}; + auto& arr = CastToArray(raw); + + arr.Mutate(0, 100); + EXPECT_EQ(arr.Get(0), 100); + + arr.Mutate(2, 0); + EXPECT_EQ(arr.Get(2), 0); + + arr.Mutate(1, std::numeric_limits::max()); + EXPECT_EQ(arr.Get(1), std::numeric_limits::max()); +} + +// --------------------------------------------------------------------------- +// ArrayIteratorTest +// Tests Array::begin, Array::end. +// --------------------------------------------------------------------------- + +TEST(ArrayIteratorTest, ForwardIteration) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::begin, ::flatbuffers::Array::end"); + RecordProperty("Description", "forward iteration yields expected elements in order"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[4] = {5, 10, 15, 20}; + const auto& arr = CastToArray(raw); + + int count = 0; + int expected[] = {5, 10, 15, 20}; + for (auto it = arr.begin(); it != arr.end(); ++it) + { + EXPECT_EQ(*it, expected[count]); + ++count; + } + EXPECT_EQ(count, 4); +} + +// --------------------------------------------------------------------------- +// ArrayReverseIteratorTest +// Tests Array::rbegin, Array::rend. +// --------------------------------------------------------------------------- + +TEST(ArrayReverseIteratorTest, ReverseIteration) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::rbegin, ::flatbuffers::Array::rend"); + RecordProperty("Description", "reverse iteration yields elements in reverse order"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {1, 2, 3}; + const auto& arr = CastToArray(raw); + + std::vector rev; + for (auto it = arr.rbegin(); it != arr.rend(); ++it) + { + rev.push_back(*it); + } + ASSERT_EQ(rev.size(), 3u); + EXPECT_EQ(rev[0], 3); + EXPECT_EQ(rev[1], 2); + EXPECT_EQ(rev[2], 1); +} + +// --------------------------------------------------------------------------- +// ArraySizeTest +// Tests Array::size. +// --------------------------------------------------------------------------- + +TEST(ArraySizeTest, ReturnsTemplateSize) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::size"); + RecordProperty("Description", "size() returns the compile-time template parameter N"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[5] = {}; + auto& arr = CastToArray(raw); + EXPECT_EQ(arr.size(), 5u); +} + +// --------------------------------------------------------------------------- +// ArrayMakeSpanTest +// Tests make_span, make_bytes_span. +// --------------------------------------------------------------------------- + +TEST(ArrayMakeSpanTest, SpanFromArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_span(Array&)"); + RecordProperty("Description", "make_span creates a fixed-size span over array data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {100, 200, 300}; + auto& arr = CastToArray(raw); + auto s = make_span(arr); + EXPECT_EQ(s.size(), 3u); + EXPECT_EQ(s[0], 100); + EXPECT_EQ(s[2], 300); +} + +TEST(ArrayMakeSpanTest, BytesSpanFromArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_bytes_span(Array&)"); + RecordProperty("Description", "make_bytes_span returns span over raw bytes"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[2] = {0, 0}; + auto& arr = CastToArray(raw); + auto bs = make_bytes_span(arr); + EXPECT_EQ(bs.size(), 2u * sizeof(int32_t)); +} + +// --------------------------------------------------------------------------- +// ArrayDataTest +// Tests Array::Data(), Array::data(). +// --------------------------------------------------------------------------- + +TEST(ArrayDataTest, DataPointers) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Data, ::flatbuffers::Array::data"); + RecordProperty("Description", "Data() and data() return pointers to underlying storage"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {1, 2, 3}; + auto& arr = CastToArray(raw); + EXPECT_EQ(reinterpret_cast(raw), + static_cast(arr.Data())); + EXPECT_EQ(raw, arr.data()); +} + +// --------------------------------------------------------------------------- +// ArrayEqualityTest +// Tests operator==. +// --------------------------------------------------------------------------- + +TEST(ArrayEqualityTest, ScalarEquality) +{ + RecordProperty("FullyVerifies", "::flatbuffers::operator=="); + RecordProperty("Description", "operator== compares all elements for equality"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t a[3] = {1, 2, 3}; + int32_t b[3] = {1, 2, 3}; + int32_t c[3] = {1, 2, 4}; + + auto& aa = CastToArray(a); + auto& ab = CastToArray(b); + auto& ac = CastToArray(c); + + EXPECT_TRUE(aa == ab); + EXPECT_FALSE(aa == ac); + EXPECT_TRUE(aa == aa); +} + +// --------------------------------------------------------------------------- +// ArrayEnumTest +// Tests CastToArrayOfEnum, GetEnum. +// --------------------------------------------------------------------------- + +TEST(ArrayEnumTest, CastToArrayOfEnum) +{ + RecordProperty("FullyVerifies", "::flatbuffers::CastToArrayOfEnum"); + RecordProperty("Description", "CastToArrayOfEnum casts raw array to Array of enum type"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + enum class Color : int32_t { Red = 0, Green = 1, Blue = 2 }; + int32_t raw[3] = {0, 1, 2}; + auto& arr = CastToArrayOfEnum(raw); + EXPECT_EQ(arr.size(), 3u); + EXPECT_EQ(static_cast(arr.Get(0)), 0); + EXPECT_EQ(static_cast(arr.Get(1)), 1); + EXPECT_EQ(static_cast(arr.Get(2)), 2); +} + +TEST(ArrayEnumTest, GetEnum) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::GetEnum"); + RecordProperty("Description", "GetEnum retrieves element cast to enum type"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + enum class Fruit : int32_t { Apple = 0, Banana = 1, Cherry = 2 }; + int32_t raw[3] = {0, 1, 2}; + auto& arr = CastToArray(raw); + EXPECT_EQ(arr.GetEnum(0), Fruit::Apple); + EXPECT_EQ(arr.GetEnum(1), Fruit::Banana); + EXPECT_EQ(arr.GetEnum(2), Fruit::Cherry); +} + +// --------------------------------------------------------------------------- +// ArrayConstIteratorsTest +// Tests cbegin, cend, crbegin, crend. +// --------------------------------------------------------------------------- + +TEST(ArrayConstIteratorsTest, CBeginCEnd) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::cbegin, ::flatbuffers::Array::cend"); + RecordProperty("Description", "cbegin/cend produce const forward iterators"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {10, 20, 30}; + const auto& arr = CastToArray(raw); + + int32_t expected[] = {10, 20, 30}; + int idx = 0; + for (auto it = arr.cbegin(); it != arr.cend(); ++it) + { + EXPECT_EQ(*it, expected[idx]); + ++idx; + } + EXPECT_EQ(idx, 3); +} + +TEST(ArrayConstIteratorsTest, CRBeginCREnd) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::crbegin, ::flatbuffers::Array::crend"); + RecordProperty("Description", "crbegin/crend produce const reverse iterators"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {1, 2, 3}; + const auto& arr = CastToArray(raw); + + std::vector result; + for (auto it = arr.crbegin(); it != arr.crend(); ++it) + { + result.push_back(*it); + } + ASSERT_EQ(result.size(), 3u); + EXPECT_EQ(result[0], 3); + EXPECT_EQ(result[1], 2); + EXPECT_EQ(result[2], 1); +} + +// --------------------------------------------------------------------------- +// ArrayMutableDataTest +// Tests mutable Data() and data(). +// --------------------------------------------------------------------------- + +TEST(ArrayMutableDataTest, MutableData) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Data"); + RecordProperty("Description", "mutable Data() returns writable uint8_t pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[2] = {0, 0}; + auto& arr = CastToArray(raw); + uint8_t* mutable_ptr = arr.Data(); + EXPECT_NE(mutable_ptr, nullptr); + int32_t val = 42; + std::memcpy(mutable_ptr, &val, sizeof(val)); + EXPECT_EQ(arr.Get(0), 42); +} + +TEST(ArrayMutableDataTest, MutableDataTyped) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::data"); + RecordProperty("Description", "mutable data() returns writable T* pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {1, 2, 3}; + auto& arr = CastToArray(raw); + int32_t* typed_ptr = arr.data(); + EXPECT_EQ(typed_ptr, raw); + typed_ptr[1] = 99; + EXPECT_EQ(arr.Get(1), 99); +} + +// --------------------------------------------------------------------------- +// ArrayStructTest +// Tests struct-related Array functionality. +// --------------------------------------------------------------------------- + +TEST(ArrayStructTest, GetMutablePointerStruct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::GetMutablePointer"); + RecordProperty("Description", "GetMutablePointer on struct array returns writable pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Point raw[2] = {{1, 2}, {3, 4}}; + auto& arr = CastToArray(raw); + Point* p = arr.GetMutablePointer(0); + ASSERT_NE(p, nullptr); + p->x = 100; + p->y = 200; + EXPECT_EQ(arr.Get(0)->x, 100); + EXPECT_EQ(arr.Get(0)->y, 200); + EXPECT_EQ(arr.Get(1)->x, 3); + EXPECT_EQ(arr.Get(1)->y, 4); +} + +TEST(ArrayStructTest, MutateStruct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Mutate, ::flatbuffers::Array::MutateImpl(false_type)"); + RecordProperty("Description", "Mutate on struct array uses MutateImpl(false_type)"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Point raw[2] = {{10, 20}, {30, 40}}; + auto& arr = CastToArray(raw); + Point new_val = {50, 60}; + arr.Mutate(1, new_val); + EXPECT_EQ(arr.Get(1)->x, 50); + EXPECT_EQ(arr.Get(1)->y, 60); + EXPECT_EQ(arr.Get(0)->x, 10); + EXPECT_EQ(arr.Get(0)->y, 20); +} + +// --------------------------------------------------------------------------- +// ArrayCopyFromSpanTest +// Tests Array::CopyFromSpan. +// --------------------------------------------------------------------------- + +TEST(ArrayCopyFromSpanTest, Scalar) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpan"); + RecordProperty("Description", "CopyFromSpan with scalar (span-observable) path"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {0, 0, 0}; + auto& arr = CastToArray(raw); + + const int32_t src[3] = {7, 8, 9}; + span src_span(src, 3); + arr.CopyFromSpan(src_span); + + EXPECT_EQ(arr.Get(0), 7); + EXPECT_EQ(arr.Get(1), 8); + EXPECT_EQ(arr.Get(2), 9); +} + +TEST(ArrayCopyFromSpanTest, Struct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpan"); + RecordProperty("Description", "CopyFromSpan with struct type"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Point raw[2] = {{0, 0}, {0, 0}}; + auto& arr = CastToArray(raw); + + const Point src[2] = {{11, 22}, {33, 44}}; + span src_span(src, 2); + arr.CopyFromSpan(src_span); + + EXPECT_EQ(arr.Get(0)->x, 11); + EXPECT_EQ(arr.Get(0)->y, 22); + EXPECT_EQ(arr.Get(1)->x, 33); + EXPECT_EQ(arr.Get(1)->y, 44); +} + +// --------------------------------------------------------------------------- +// ArrayConstSpanTest +// Tests make_span with const Array. +// --------------------------------------------------------------------------- + +TEST(ArrayConstSpanTest, MakeSpanConst) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_span(const Array&)"); + RecordProperty("Description", "make_span with const Array"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + const int32_t raw[3] = {5, 10, 15}; + const auto& arr = CastToArray(raw); + auto s = make_span(arr); + EXPECT_EQ(s.size(), 3u); + EXPECT_EQ(s[0], 5); + EXPECT_EQ(s[1], 10); + EXPECT_EQ(s[2], 15); +} + +TEST(ArrayConstSpanTest, MakeBytesSpanConst) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_bytes_span(const Array&)"); + RecordProperty("Description", "make_bytes_span with const Array"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + const int32_t raw[2] = {1, 2}; + const auto& arr = CastToArray(raw); + auto bs = make_bytes_span(arr); + EXPECT_EQ(bs.size(), 2u * sizeof(int32_t)); + EXPECT_EQ(bs.data(), arr.Data()); +} + +TEST(ArrayConstSpanTest, ConstCastToArrayOfEnum) +{ + RecordProperty("FullyVerifies", "::flatbuffers::CastToArrayOfEnum"); + RecordProperty("Description", "const CastToArrayOfEnum"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + enum class Color : int32_t { Red = 0, Green = 1, Blue = 2 }; + const int32_t raw[3] = {0, 1, 2}; + const auto& arr = CastToArrayOfEnum(raw); + EXPECT_EQ(arr.size(), 3u); + EXPECT_EQ(static_cast(arr.Get(0)), 0); + EXPECT_EQ(static_cast(arr.Get(1)), 1); + EXPECT_EQ(static_cast(arr.Get(2)), 2); +} + +// --------------------------------------------------------------------------- +// ArraySpanObservableTest +// Tests is_span_observable. +// --------------------------------------------------------------------------- + +TEST(ArraySpanObservableTest, StaticAssertions) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::is_span_observable"); + RecordProperty("Description", "is_span_observable static member for scalar and struct types"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + static_assert(Array::is_span_observable, "int32_t should be span-observable on LE"); + static_assert(Array::is_span_observable, "uint16_t should be span-observable on LE"); + static_assert(Array::is_span_observable, "int64_t should be span-observable on LE"); + static_assert(Array::is_span_observable, "uint8_t should always be span-observable"); + static_assert(Array::is_span_observable, "int8_t should always be span-observable"); + static_assert(Array::is_span_observable, "POD struct should be span-observable"); + + EXPECT_TRUE((Array::is_span_observable)); + EXPECT_TRUE((Array::is_span_observable)); + EXPECT_TRUE((Array::is_span_observable)); +} + +// --------------------------------------------------------------------------- +// CopyFromSpanImplTest +// Direct access helper for CopyFromSpanImpl true_type and false_type paths. +// --------------------------------------------------------------------------- + +template +struct ArrayTestAccess : public Array +{ + void CallCopyObservable(span src) + { + this->CopyFromSpanImpl(true_type(), src); + } + void CallCopyNonObservable(span src) + { + this->CopyFromSpanImpl(false_type(), src); + } +}; + +TEST(CopyFromSpanImplTest, Observable) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpanImpl(true_type)"); + RecordProperty("Description", "CopyFromSpanImpl(true_type) — memcpy path"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {0, 0, 0}; + auto& accessor = reinterpret_cast&>(raw); + + const int32_t src[3] = {10, 20, 30}; + span src_span(src, 3); + accessor.CallCopyObservable(src_span); + + EXPECT_EQ(raw[0], 10); + EXPECT_EQ(raw[1], 20); + EXPECT_EQ(raw[2], 30); +} + +TEST(CopyFromSpanImplTest, NonObservableScalar) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpanImpl(false_type)"); + RecordProperty("Description", "CopyFromSpanImpl(false_type) — element-wise Mutate path for scalars"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int32_t raw[3] = {0, 0, 0}; + auto& accessor = reinterpret_cast&>(raw); + + const int32_t src[3] = {100, 200, 300}; + span src_span(src, 3); + accessor.CallCopyNonObservable(src_span); + + EXPECT_EQ(raw[0], 100); + EXPECT_EQ(raw[1], 200); + EXPECT_EQ(raw[2], 300); +} + +TEST(CopyFromSpanImplTest, NonObservableStruct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpanImpl(false_type)"); + RecordProperty("Description", "CopyFromSpanImpl(false_type) with struct type"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Point raw[2] = {{0, 0}, {0, 0}}; + auto& accessor = reinterpret_cast&>(raw); + + const Point src[2] = {{7, 8}, {9, 10}}; + span src_span(src, 2); + accessor.CallCopyNonObservable(src_span); + + EXPECT_EQ(raw[0].x, 7); + EXPECT_EQ(raw[0].y, 8); + EXPECT_EQ(raw[1].x, 9); + EXPECT_EQ(raw[1].y, 10); +} + +// --------------------------------------------------------------------------- +// OffsetSpecializationTest +// Tests the Array, N> specialization. +// --------------------------------------------------------------------------- + +TEST(OffsetSpecializationTest, Data) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array, N>::Data"); + RecordProperty("Description", "Data() on Offset specialization returns internal data pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + uint8_t buf[4] = {0xAA, 0xBB, 0xCC, 0xDD}; + const auto& arr = *reinterpret_cast, 2>*>(buf); + EXPECT_EQ(arr.Data(), buf); +} + +TEST(OffsetSpecializationTest, StructArrayEquality) +{ + RecordProperty("FullyVerifies", "::flatbuffers::operator=="); + RecordProperty("Description", "operator== on struct arrays"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Point a[2] = {{1, 2}, {3, 4}}; + Point b[2] = {{1, 2}, {3, 4}}; + Point c[2] = {{1, 2}, {3, 5}}; + + auto& aa = CastToArray(a); + auto& ab = CastToArray(b); + auto& ac = CastToArray(c); + + EXPECT_TRUE(aa == ab); + EXPECT_FALSE(aa == ac); + EXPECT_TRUE(aa == aa); +} + +TEST(OffsetSpecializationTest, SizeType) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::size_type"); + RecordProperty("Description", "size_type is uint16_t"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + static_assert(std::is_same::size_type, uint16_t>::value, + "size_type must be uint16_t"); +} + +// --------------------------------------------------------------------------- +// ArrayFaultInjectionTest +// Fault injection tests for Array. +// --------------------------------------------------------------------------- + +TEST(ArrayFaultInjectionTest, OffsetSpecializationOperatorIndexDeathTest) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array, N>::operator[]"); + RecordProperty("Description", "Array, N>::operator[] triggers assert(false) at runtime"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + uint8_t buf[2] = {0}; + const auto& arr = *reinterpret_cast, 2>*>(buf); + EXPECT_DEATH({arr[0]; }, ""); +} + +TEST(ArrayFaultInjectionTest, FaultGetOutOfBounds) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Get"); + RecordProperty("Description", "Get() with index == size triggers assert(false)"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + int32_t raw[3] = {1, 2, 3}; + const auto& arr = CastToArray(raw); + EXPECT_DEATH({arr.Get(3u); }, ""); +} + +TEST(ArrayFaultInjectionTest, FaultGetMutablePointerOutOfBounds) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::GetMutablePointer"); + RecordProperty("Description", "GetMutablePointer() with index == size triggers assert(false)"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + Point raw[2] = {{1, 2}, {3, 4}}; + auto& arr = CastToArray(raw); + EXPECT_DEATH({arr.GetMutablePointer(2u); }, ""); +} + +TEST(ArrayFaultInjectionTest, FaultMutateScalarOutOfBounds) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::Mutate, ::flatbuffers::Array::MutateImpl(true_type)"); + RecordProperty("Description", "Mutate() with index == size triggers assert(false)"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + int32_t raw[3] = {0, 0, 0}; + auto& arr = CastToArray(raw); + EXPECT_DEATH({arr.Mutate(3u, 42); }, ""); +} + +TEST(ArrayFaultInjectionTest, FaultMutateStructOutOfBounds) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::MutateImpl(false_type)"); + RecordProperty("Description", "Mutate() with index == size on struct triggers assert(false) via false_type path"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + Point raw[2] = {{0, 0}, {0, 0}}; + auto& arr = CastToArray(raw); + const Point p = {1, 2}; + EXPECT_DEATH({arr.Mutate(2u, p); }, ""); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_base_test.cpp b/score/flatbuffers/details/flatbuffers_base_test.cpp new file mode 100644 index 0000000000..6986596eff --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_base_test.cpp @@ -0,0 +1,333 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/base.h" + +#include +#include + +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// BaseVersionMacrosTest +// Tests FLATBUFFERS_VERSION macros and FLATBUFFERS_VERSION(). +// --------------------------------------------------------------------------- + +TEST(BaseVersionMacrosTest, VersionInfo) +{ + RecordProperty("FullyVerifies", "FLATBUFFERS_VERSION_MAJOR, FLATBUFFERS_VERSION_MINOR, FLATBUFFERS_VERSION_REVISION, FLATBUFFERS_VERSION"); + RecordProperty("Description", "FLATBUFFERS_VERSION macros return non-negative values; version string has format X.Y.Z"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_GE(FLATBUFFERS_VERSION_MAJOR, 0); + EXPECT_GE(FLATBUFFERS_VERSION_MINOR, 0); + EXPECT_GE(FLATBUFFERS_VERSION_REVISION, 0); + + const char* v = FLATBUFFERS_VERSION(); + EXPECT_NE(v, nullptr); + EXPECT_GE(strlen(v), 5u); + + int dot_count = 0; + for (const char* p = v; *p; ++p) + { + if (*p == '.') + ++dot_count; + } + EXPECT_EQ(dot_count, 2); +} + +// --------------------------------------------------------------------------- +// BaseTypeSizesTest +// Tests fundamental type sizes. +// --------------------------------------------------------------------------- + +TEST(BaseTypeSizesTest, WireFormatTypes) +{ + RecordProperty("FullyVerifies", "uoffset_t, soffset_t, uoffset64_t, soffset64_t, voffset_t"); + RecordProperty("Description", "wire-format type sizes match expected widths"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + EXPECT_EQ(sizeof(uoffset_t), 4u); + EXPECT_EQ(sizeof(soffset_t), 4u); + EXPECT_EQ(sizeof(uoffset64_t), 8u); + EXPECT_EQ(sizeof(soffset64_t), 8u); + EXPECT_EQ(sizeof(voffset_t), 2u); +} + +// --------------------------------------------------------------------------- +// BaseEndianSwapTest +// Tests EndianSwap. +// --------------------------------------------------------------------------- + +TEST(BaseEndianSwapTest, SwapValues) +{ + RecordProperty("FullyVerifies", "::flatbuffers::EndianSwap"); + RecordProperty("Description", "EndianSwap reverses byte order for 1, 2, 4 and 8 byte values"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + EXPECT_EQ(EndianSwap(static_cast(0x00)), static_cast(0x00)); + EXPECT_EQ(EndianSwap(static_cast(0xFF)), static_cast(0xFF)); + EXPECT_EQ(EndianSwap(static_cast(0x42)), static_cast(0x42)); + + EXPECT_EQ(EndianSwap(static_cast(0x0000)), static_cast(0x0000)); + EXPECT_EQ(EndianSwap(static_cast(0xFFFF)), static_cast(0xFFFF)); + EXPECT_EQ(EndianSwap(static_cast(0x0102)), static_cast(0x0201)); + + EXPECT_EQ(EndianSwap(static_cast(0x00000000u)), static_cast(0x00000000u)); + EXPECT_EQ(EndianSwap(static_cast(0xFFFFFFFFu)), static_cast(0xFFFFFFFFu)); + EXPECT_EQ(EndianSwap(static_cast(0x01020304u)), static_cast(0x04030201u)); + + EXPECT_EQ(EndianSwap(static_cast(0x0000000000000000ULL)), static_cast(0x0000000000000000ULL)); + EXPECT_EQ(EndianSwap(static_cast(0xFFFFFFFFFFFFFFFFULL)), static_cast(0xFFFFFFFFFFFFFFFFULL)); + EXPECT_EQ(EndianSwap(static_cast(0x0102030405060708ULL)), static_cast(0x0807060504030201ULL)); + + EXPECT_EQ(EndianSwap(EndianSwap(static_cast(0x1234))), static_cast(0x1234)); + EXPECT_EQ(EndianSwap(EndianSwap(static_cast(0xDEADBEEFu))), static_cast(0xDEADBEEFu)); + EXPECT_EQ(EndianSwap(EndianSwap(static_cast(0x123456789ABCDEF0ULL))), static_cast(0x123456789ABCDEF0ULL)); +} + +// --------------------------------------------------------------------------- +// BaseEndianScalarTest +// Tests EndianScalar. +// --------------------------------------------------------------------------- + +TEST(BaseEndianScalarTest, SwapValue) +{ + RecordProperty("FullyVerifies", "::flatbuffers::EndianScalar"); + RecordProperty("Description", "EndianScalar applies correct byte swap based on platform endianness"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + +#if FLATBUFFERS_LITTLEENDIAN + EXPECT_EQ(EndianScalar(static_cast(0x01020304u)), static_cast(0x01020304u)); +#else + EXPECT_EQ(EndianScalar(static_cast(0x01020304u)), EndianSwap(static_cast(0x01020304u))); +#endif + EXPECT_EQ(EndianScalar(EndianScalar(static_cast(42u))), static_cast(42u)); +} + +// --------------------------------------------------------------------------- +// BaseReadWriteScalarTest +// Tests ReadScalar, WriteScalar. +// --------------------------------------------------------------------------- + +TEST(BaseReadWriteScalarTest, ScalarReadWrite) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ReadScalar, ::flatbuffers::WriteScalar"); + RecordProperty("Description", "ReadScalar and WriteScalar round-trip values for various scalar types"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + uint8_t buf[4] = {}; + WriteScalar(buf, static_cast(0xDEADBEEFu)); + EXPECT_EQ(ReadScalar(buf), static_cast(0xDEADBEEFu)); + } + { + uint8_t buf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + WriteScalar(buf, static_cast(0u)); + EXPECT_EQ(ReadScalar(buf), static_cast(0u)); + } + { + uint8_t buf[2] = {}; + WriteScalar(buf, static_cast(-1)); + EXPECT_EQ(ReadScalar(buf), static_cast(-1)); + } + { + uint8_t buf[2] = {}; + WriteScalar(buf, std::numeric_limits::min()); + EXPECT_EQ(ReadScalar(buf), std::numeric_limits::min()); + } + { + uint8_t buf[8] = {}; + WriteScalar(buf, std::numeric_limits::max()); + EXPECT_EQ(ReadScalar(buf), std::numeric_limits::max()); + } + { + uint8_t buf[4] = {}; + float expected = 3.14f; + WriteScalar(buf, expected); + float result = ReadScalar(buf); + EXPECT_EQ(0, memcmp(&result, &expected, sizeof(float))); + } +} + +// --------------------------------------------------------------------------- +// BasePaddingBytesTest +// Tests PaddingBytes. +// --------------------------------------------------------------------------- + +TEST(BasePaddingBytesTest, PaddingCalculation) +{ + RecordProperty("FullyVerifies", "::flatbuffers::PaddingBytes"); + RecordProperty("Description", "PaddingBytes computes correct padding for alignment"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + EXPECT_EQ(PaddingBytes(0, 1), 0u); + EXPECT_EQ(PaddingBytes(1, 1), 0u); + EXPECT_EQ(PaddingBytes(100, 1), 0u); + + EXPECT_EQ(PaddingBytes(0, 4), 0u); + EXPECT_EQ(PaddingBytes(1, 4), 3u); + EXPECT_EQ(PaddingBytes(2, 4), 2u); + EXPECT_EQ(PaddingBytes(3, 4), 1u); + EXPECT_EQ(PaddingBytes(4, 4), 0u); + + EXPECT_EQ(PaddingBytes(0, 8), 0u); + EXPECT_EQ(PaddingBytes(1, 8), 7u); + EXPECT_EQ(PaddingBytes(7, 8), 1u); + EXPECT_EQ(PaddingBytes(8, 8), 0u); +} + +// --------------------------------------------------------------------------- +// BaseVerifyAlignmentRequirementsTest +// Tests VerifyAlignmentRequirements. +// --------------------------------------------------------------------------- + +TEST(BaseVerifyAlignmentRequirementsTest, AlignmentChecks) +{ + RecordProperty("FullyVerifies", "::flatbuffers::VerifyAlignmentRequirements"); + RecordProperty("Description", "VerifyAlignmentRequirements accepts powers of two and rejects others"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE(VerifyAlignmentRequirements(1)); + EXPECT_TRUE(VerifyAlignmentRequirements(2)); + EXPECT_TRUE(VerifyAlignmentRequirements(4)); + EXPECT_TRUE(VerifyAlignmentRequirements(8)); + EXPECT_TRUE(VerifyAlignmentRequirements(16)); + EXPECT_TRUE(VerifyAlignmentRequirements(FLATBUFFERS_MAX_ALIGNMENT)); + + EXPECT_FALSE(VerifyAlignmentRequirements(0)); + EXPECT_FALSE(VerifyAlignmentRequirements(3)); + EXPECT_FALSE(VerifyAlignmentRequirements(5)); + EXPECT_FALSE(VerifyAlignmentRequirements(6)); + EXPECT_FALSE(VerifyAlignmentRequirements(static_cast(FLATBUFFERS_MAX_ALIGNMENT) * 2)); + + EXPECT_TRUE(VerifyAlignmentRequirements(4, 2)); + EXPECT_TRUE(VerifyAlignmentRequirements(4, 4)); + EXPECT_FALSE(VerifyAlignmentRequirements(2, 4)); +} + +// --------------------------------------------------------------------------- +// BaseIsTheSameAsTest +// Tests IsTheSameAs. +// --------------------------------------------------------------------------- + +TEST(BaseIsTheSameAsTest, Comparison) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IsTheSameAs"); + RecordProperty("Description", "IsTheSameAs compares values for equality"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE(IsTheSameAs(0, 0)); + EXPECT_TRUE(IsTheSameAs(42, 42)); + EXPECT_FALSE(IsTheSameAs(0, 1)); + EXPECT_TRUE(IsTheSameAs(-1, -1)); + EXPECT_FALSE(IsTheSameAs(-1, 1)); + EXPECT_TRUE(IsTheSameAs(std::numeric_limits::max(), std::numeric_limits::max())); + EXPECT_TRUE(IsTheSameAs(1.0f, 1.0f)); + EXPECT_FALSE(IsTheSameAs(1.0f, 2.0f)); +} + +// --------------------------------------------------------------------------- +// BaseIsInRangeTest +// Tests IsInRange. +// --------------------------------------------------------------------------- + +TEST(BaseIsInRangeTest, RangeChecks) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IsInRange"); + RecordProperty("Description", "IsInRange checks if a value falls within a closed range"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + EXPECT_TRUE(IsInRange(0, 0, 10)); + EXPECT_TRUE(IsInRange(10, 0, 10)); + EXPECT_TRUE(IsInRange(5, 0, 10)); + EXPECT_FALSE(IsInRange(-1, 0, 10)); + EXPECT_FALSE(IsInRange(11, 0, 10)); + EXPECT_TRUE(IsInRange(5, 5, 5)); + EXPECT_FALSE(IsInRange(4, 5, 5)); + EXPECT_FALSE(IsInRange(6, 5, 5)); +} + +// --------------------------------------------------------------------------- +// BaseIsOutRangeTest +// Tests IsOutRange. +// --------------------------------------------------------------------------- + +TEST(BaseIsOutRangeTest, OutOfRangeChecks) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IsOutRange"); + RecordProperty("Description", "IsOutRange returns true when value is outside the given range"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_FALSE(IsOutRange(0, 0, 10)); + EXPECT_FALSE(IsOutRange(10, 0, 10)); + EXPECT_TRUE(IsOutRange(-1, 0, 10)); + EXPECT_TRUE(IsOutRange(11, 0, 10)); +} + +// --------------------------------------------------------------------------- +// BaseIsConstTrueTest +// Tests IsConstTrue. +// --------------------------------------------------------------------------- + +TEST(BaseIsConstTrueTest, ConstBoolValues) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IsConstTrue"); + RecordProperty("Description", "IsConstTrue evaluates constant true/false values"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE(IsConstTrue(true)); + EXPECT_FALSE(IsConstTrue(false)); + EXPECT_TRUE(IsConstTrue(1)); + EXPECT_FALSE(IsConstTrue(0)); +} + +// --------------------------------------------------------------------------- +// BaseFileIdentifierLengthTest +// Tests kFileIdentifierLength. +// --------------------------------------------------------------------------- + +TEST(BaseFileIdentifierLengthTest, ConstantValue) +{ + RecordProperty("FullyVerifies", "kFileIdentifierLength"); + RecordProperty("Description", "kFileIdentifierLength equals 4"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(kFileIdentifierLength, 4u); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_buffer_ref_test.cpp b/score/flatbuffers/details/flatbuffers_buffer_ref_test.cpp new file mode 100644 index 0000000000..e0f92a78ea --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_buffer_ref_test.cpp @@ -0,0 +1,159 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/buffer_ref.h" + +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "flatbuffers/verifier.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// A minimal "verifiable" wrapper so BufferRef::Verify() +// can call table->Verify(verifier). +struct VerifiableTable : public Table +{ + bool Verify(Verifier& verifier) const + { + return VerifyTableStart(verifier) && verifier.EndTable(); + } +}; + +static DetachedBuffer BuildVerifiable(const char* identifier = nullptr) +{ + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + if (identifier) + { + fbb.Finish(Offset(root), identifier); + } + else + { + fbb.Finish(Offset
(root)); + } + return fbb.Release(); +} + +// --------------------------------------------------------------------------- +// BufferRefValidTest +// Tests that a valid buffer verifies successfully. +// --------------------------------------------------------------------------- + +TEST(BufferRefValidTest, ValidBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferRef::Verify"); + RecordProperty("Description", "BufferRef with valid buffer data verifies successfully"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto db = BuildVerifiable(); + BufferRef ref; + ref.buf = db.data(); + ref.len = static_cast(db.size()); + EXPECT_TRUE(ref.Verify()); +} + +// --------------------------------------------------------------------------- +// BufferRefDefaultTest +// Tests that a default-constructed BufferRef is not valid. +// --------------------------------------------------------------------------- + +TEST(BufferRefDefaultTest, Empty) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferRef::BufferRef"); + RecordProperty("Description", "default-constructed BufferRef has null pointer and zero length"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + BufferRef ref; + EXPECT_EQ(ref.buf, nullptr); + EXPECT_EQ(ref.len, 0u); +} + +// --------------------------------------------------------------------------- +// BufferRefInvalidTest +// Tests that truncated / corrupted buffer fails verification. +// --------------------------------------------------------------------------- + +TEST(BufferRefInvalidTest, TruncatedBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferRef::Verify"); + RecordProperty("Description", "truncated buffer fails verification"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + uint8_t tiny[] = {0x00, 0x01, 0x02, 0x03}; + BufferRef ref; + ref.buf = tiny; + ref.len = 4; + EXPECT_FALSE(ref.Verify()); +} + +// --------------------------------------------------------------------------- +// BufferRefGetRootTest +// Tests BufferRef::GetRoot. +// --------------------------------------------------------------------------- + +TEST(BufferRefGetRootTest, ReturnsRoot) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferRef::GetRoot"); + RecordProperty("Description", "GetRoot returns a usable pointer for valid buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto db = BuildVerifiable(); + BufferRef ref; + ref.buf = db.data(); + ref.len = static_cast(db.size()); + EXPECT_TRUE(ref.Verify()); + + const auto* root = ref.GetRoot(); + ASSERT_NE(root, nullptr); +} + +// --------------------------------------------------------------------------- +// BufferRefWithIdentifierTest +// Tests buffer with identifier. +// --------------------------------------------------------------------------- + +TEST(BufferRefWithIdentifierTest, IdentifierPresent) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferRef::Verify, ::flatbuffers::BufferHasIdentifier"); + RecordProperty("Description", "buffer with matching identifier verifies and passes BufferHasIdentifier"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto db = BuildVerifiable("ABCD"); + BufferRef ref; + ref.buf = db.data(); + ref.len = static_cast(db.size()); + EXPECT_TRUE(ref.Verify()); + EXPECT_TRUE(BufferHasIdentifier(ref.buf, "ABCD")); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_buffer_test.cpp b/score/flatbuffers/details/flatbuffers_buffer_test.cpp new file mode 100644 index 0000000000..bc781bb9e0 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_buffer_test.cpp @@ -0,0 +1,470 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/buffer.h" + +#include +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// =========================================================================== +// Offset +// =========================================================================== + +// --------------------------------------------------------------------------- +// OffsetDefaultTest +// --------------------------------------------------------------------------- + +TEST(OffsetDefaultTest, Null) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Offset::IsNull, ::flatbuffers::Offset::o"); + RecordProperty("Description", "default Offset is null (o == 0)"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Offset off; + EXPECT_TRUE(off.IsNull()); + EXPECT_EQ(off.o, 0u); +} + +// --------------------------------------------------------------------------- +// OffsetNonNullTest +// --------------------------------------------------------------------------- + +TEST(OffsetNonNullTest, NotNull) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Offset::IsNull, ::flatbuffers::Offset::o"); + RecordProperty("Description", "non-zero Offset is not null, including max value"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + Offset off(1); + EXPECT_FALSE(off.IsNull()); + EXPECT_EQ(off.o, 1u); + } + { + Offset off(std::numeric_limits::max()); + EXPECT_FALSE(off.IsNull()); + } +} + +// --------------------------------------------------------------------------- +// OffsetUnionTest +// --------------------------------------------------------------------------- + +TEST(OffsetUnionTest, UntypedConversion) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Offset::Union"); + RecordProperty("Description", "Union() returns untyped Offset preserving value"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Offset typed(42); + Offset<> untyped = typed.Union(); + EXPECT_EQ(untyped.o, 42u); +} + +// --------------------------------------------------------------------------- +// OffsetSizeTest +// --------------------------------------------------------------------------- + +TEST(OffsetSizeTest, Width) +{ + RecordProperty("FullyVerifies", "sizeof(Offset)"); + RecordProperty("Description", "sizeof(Offset) == 4 bytes"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(sizeof(Offset<>), 4u); +} + +// =========================================================================== +// Offset64 +// =========================================================================== + +// --------------------------------------------------------------------------- +// Offset64DefaultTest +// --------------------------------------------------------------------------- + +TEST(Offset64DefaultTest, Null) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Offset64::IsNull, ::flatbuffers::Offset64::o"); + RecordProperty("Description", "default Offset64 is null"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Offset64 off; + EXPECT_TRUE(off.IsNull()); + EXPECT_EQ(off.o, static_cast(0)); +} + +// --------------------------------------------------------------------------- +// Offset64NonNullTest +// --------------------------------------------------------------------------- + +TEST(Offset64NonNullTest, NotNull) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Offset64::IsNull"); + RecordProperty("Description", "Offset64 with value is not null"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Offset64 off(1); + EXPECT_FALSE(off.IsNull()); +} + +// --------------------------------------------------------------------------- +// Offset64SizeTest +// --------------------------------------------------------------------------- + +TEST(Offset64SizeTest, Width) +{ + RecordProperty("FullyVerifies", "sizeof(Offset64)"); + RecordProperty("Description", "sizeof(Offset64) == 8 bytes"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(sizeof(Offset64<>), 8u); +} + +// =========================================================================== +// Offset traits +// =========================================================================== + +// --------------------------------------------------------------------------- +// OffsetTraitsTest +// --------------------------------------------------------------------------- + +TEST(OffsetTraitsTest, TypeTraits) +{ + RecordProperty("FullyVerifies", "::flatbuffers::is_specialisation_of_Offset, ::flatbuffers::is_specialisation_of_Offset64"); + RecordProperty("Description", "traits correctly identify Offset and Offset64 specializations"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE((is_specialisation_of_Offset>::value)); + EXPECT_TRUE((is_specialisation_of_Offset>::value)); + EXPECT_FALSE((is_specialisation_of_Offset::value)); + EXPECT_FALSE((is_specialisation_of_Offset>::value)); + + EXPECT_TRUE((is_specialisation_of_Offset64>::value)); + EXPECT_FALSE((is_specialisation_of_Offset64>::value)); + EXPECT_FALSE((is_specialisation_of_Offset64::value)); +} + +// =========================================================================== +// StringLessThan +// =========================================================================== + +// --------------------------------------------------------------------------- +// StringLessThanTest +// --------------------------------------------------------------------------- + +TEST(StringLessThanTest, Comparison) +{ + RecordProperty("FullyVerifies", "::flatbuffers::StringLessThan"); + RecordProperty("Description", "StringLessThan compares length-prefixed strings lexicographically"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE(StringLessThan("abc", 3, "abd", 3)); + EXPECT_FALSE(StringLessThan("abd", 3, "abc", 3)); + EXPECT_TRUE(StringLessThan("ab", 2, "abc", 3)); + EXPECT_FALSE(StringLessThan("abc", 3, "ab", 2)); + EXPECT_TRUE(StringLessThan("", 0, "a", 1)); + EXPECT_FALSE(StringLessThan("a", 1, "", 0)); + EXPECT_FALSE(StringLessThan("", 0, "", 0)); +} + +// =========================================================================== +// BufferIdentifier +// =========================================================================== + +// --------------------------------------------------------------------------- +// BufferIdentifierTest +// --------------------------------------------------------------------------- + +TEST(BufferIdentifierTest, IdentifierCheck) +{ + RecordProperty("FullyVerifies", "::flatbuffers::BufferHasIdentifier, ::flatbuffers::GetBufferIdentifier"); + RecordProperty("Description", "BufferHasIdentifier and GetBufferIdentifier check buffer magic"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root), "TEST"); + + auto buf = fbb.GetBufferPointer(); + EXPECT_TRUE(BufferHasIdentifier(buf, "TEST")); + EXPECT_FALSE(BufferHasIdentifier(buf, "XXXX")); + + const char* id = GetBufferIdentifier(buf); + EXPECT_EQ(memcmp(id, "TEST", 4), 0); +} + +// =========================================================================== +// GetRoot / GetMutableRoot +// =========================================================================== + +// --------------------------------------------------------------------------- +// GetRootTest +// --------------------------------------------------------------------------- + +TEST(GetRootTest, Access) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetRoot, ::flatbuffers::GetMutableRoot"); + RecordProperty("Description", "GetRoot and GetMutableRoot return pointers to root table"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto buf = fbb.GetBufferPointer(); + const Table* t = GetRoot
(buf); + EXPECT_NE(t, nullptr); + + Table* mt = GetMutableRoot
(buf); + EXPECT_NE(mt, nullptr); + + EXPECT_EQ(reinterpret_cast(t), reinterpret_cast(mt)); +} + +// =========================================================================== +// IndirectHelper +// =========================================================================== + +// --------------------------------------------------------------------------- +// IndirectHelperScalarTest +// --------------------------------------------------------------------------- + +TEST(IndirectHelperScalarTest, Read) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper::Read"); + RecordProperty("Description", "IndirectHelper reads scalars at various indices"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + uint32_t arr[] = {10, 20, 30}; + auto* p = reinterpret_cast(arr); + EXPECT_EQ(IndirectHelper::Read(p, 0), EndianScalar(10u)); + EXPECT_EQ(IndirectHelper::Read(p, 1), EndianScalar(20u)); + EXPECT_EQ(IndirectHelper::Read(p, 2), EndianScalar(30u)); +} + +TEST(IndirectHelperScalarTest, MutableRead) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper::Read"); + RecordProperty("Description", "mutable IndirectHelper Read returns same value as const Read"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + uint32_t arr[] = {100, 200}; + auto* p = reinterpret_cast(arr); + EXPECT_EQ(IndirectHelper::Read(p, 0), EndianScalar(100u)); + EXPECT_EQ(IndirectHelper::Read(p, 1), EndianScalar(200u)); +} + +// --------------------------------------------------------------------------- +// IndirectHelperOffsetTest +// --------------------------------------------------------------------------- + +TEST(IndirectHelperOffsetTest, Read) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper>::Read"); + RecordProperty("Description", "follows 32-bit offset indirection to reach a String"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto s0 = fbb.CreateString("alpha"); + auto s1 = fbb.CreateString("beta"); + std::vector> offsets = {s0, s1}; + auto vec = fbb.CreateVector(offsets); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 2u); + + const String* str0 = v->Get(0); + const String* str1 = v->Get(1); + ASSERT_NE(str0, nullptr); + ASSERT_NE(str1, nullptr); + EXPECT_STREQ(str0->c_str(), "alpha"); + EXPECT_STREQ(str1->c_str(), "beta"); +} + +TEST(IndirectHelperOffsetTest, MutableRead) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper>::Read"); + RecordProperty("Description", "mutable Read via raw data pointer returns same object as const Get"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto s0 = fbb.CreateString("hello"); + std::vector> offsets = {s0}; + auto vec = fbb.CreateVector(offsets); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetMutableRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + + const String* str = v->Get(0); + ASSERT_NE(str, nullptr); + EXPECT_STREQ(str->c_str(), "hello"); + + auto* data = const_cast(v->Data()); + String* mstr = IndirectHelper>::Read(data, 0); + ASSERT_NE(mstr, nullptr); + EXPECT_EQ(reinterpret_cast(str), reinterpret_cast(mstr)); +} + +// =========================================================================== +// IndirectHelper for structs +// =========================================================================== + +#pragma pack(push, 1) +struct TestPoint FLATBUFFERS_FINAL_CLASS +{ + int16_t x_; + int16_t y_; + + public: + TestPoint() : x_(0), y_(0) {} + TestPoint(int16_t x, int16_t y) : x_(EndianScalar(x)), y_(EndianScalar(y)) {} + int16_t x() const + { + return EndianScalar(x_); + } + int16_t y() const + { + return EndianScalar(y_); + } +}; +#pragma pack(pop) +static_assert(sizeof(TestPoint) == 4, "TestPoint must be 4 bytes"); + +TEST(IndirectHelperStructTest, Read) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper::Read"); + RecordProperty("Description", "reads structs stored inline at various indices"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + TestPoint pts[] = {TestPoint(1, 2), TestPoint(3, 4), TestPoint(5, 6)}; + auto* p = reinterpret_cast(pts); + + const TestPoint* r0 = IndirectHelper::Read(p, 0); + const TestPoint* r1 = IndirectHelper::Read(p, 1); + const TestPoint* r2 = IndirectHelper::Read(p, 2); + + EXPECT_EQ(r0->x(), 1); + EXPECT_EQ(r0->y(), 2); + EXPECT_EQ(r1->x(), 3); + EXPECT_EQ(r1->y(), 4); + EXPECT_EQ(r2->x(), 5); + EXPECT_EQ(r2->y(), 6); +} + +TEST(IndirectHelperStructTest, MutableRead) +{ + RecordProperty("FullyVerifies", "::flatbuffers::IndirectHelper::Read"); + RecordProperty("Description", "mutable IndirectHelper Read returns writable pointer to same data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + TestPoint pts[] = {TestPoint(10, 20), TestPoint(30, 40)}; + auto* p = reinterpret_cast(pts); + + TestPoint* r0 = IndirectHelper::Read(p, 0); + TestPoint* r1 = IndirectHelper::Read(p, 1); + + EXPECT_EQ(r0->x(), 10); + EXPECT_EQ(r1->x(), 30); + + EXPECT_EQ(reinterpret_cast(r0), p); + EXPECT_EQ(reinterpret_cast(r1), p + sizeof(TestPoint)); +} + +// =========================================================================== +// GetMutableSizePrefixedRoot +// =========================================================================== + +// --------------------------------------------------------------------------- +// GetMutableSizePrefixedRootTest +// --------------------------------------------------------------------------- + +TEST(GetMutableSizePrefixedRootTest, Access) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetMutableSizePrefixedRoot"); + RecordProperty("Description", "returns mutable pointer into a size-prefixed buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.FinishSizePrefixed(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + + const Table* ct = GetSizePrefixedRoot
(buf); + ASSERT_NE(ct, nullptr); + EXPECT_EQ(ct->GetField(4, 0), 42); + + Table* mt = GetMutableSizePrefixedRoot
(buf); + ASSERT_NE(mt, nullptr); + EXPECT_EQ(mt->GetField(4, 0), 42); + + EXPECT_EQ(reinterpret_cast(ct), reinterpret_cast(mt)); + + bool ok = mt->SetField(4, 99, 0); + EXPECT_TRUE(ok); + EXPECT_EQ(ct->GetField(4, 0), 99); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_default_allocator_test.cpp b/score/flatbuffers/details/flatbuffers_default_allocator_test.cpp new file mode 100644 index 0000000000..1b0b4a812f --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_default_allocator_test.cpp @@ -0,0 +1,312 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/default_allocator.h" + +#include +#include + +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Magic-number sentinels used across tests. +constexpr uint8_t kFillByte = 0xAA; +constexpr uint8_t kBackFillByte = 0x5A; + +// --------------------------------------------------------------------------- +// DefaultAllocatorBasicTest +// Directly exercises the DefaultAllocator member functions. +// --------------------------------------------------------------------------- + +TEST(DefaultAllocatorBasicTest, AllocateReturnsWritableMemory) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::allocate, ::flatbuffers::DefaultAllocator::deallocate"); + RecordProperty("Description", "allocate returns non-null and the memory is writable"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + constexpr size_t kSize = 128; + uint8_t* p = alloc.allocate(kSize); + ASSERT_NE(p, nullptr); + std::memset(p, kFillByte, kSize); + EXPECT_EQ(p[0], kFillByte); + EXPECT_EQ(p[kSize - 1], kFillByte); + alloc.deallocate(p, kSize); +} + +TEST(DefaultAllocatorBasicTest, AllocateSingleByte) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::allocate, ::flatbuffers::DefaultAllocator::deallocate"); + RecordProperty("Description", "allocate a single byte and write to it"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + DefaultAllocator alloc; + uint8_t* p = alloc.allocate(1); + ASSERT_NE(p, nullptr); + *p = 0xFF; + EXPECT_EQ(*p, 0xFF); + alloc.deallocate(p, 1); +} + +TEST(DefaultAllocatorBasicTest, AllocateLargeRegion) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::allocate, ::flatbuffers::DefaultAllocator::deallocate"); + RecordProperty("Description", "allocate a large (1 MiB) region"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + DefaultAllocator alloc; + constexpr size_t kSize = 1024 * 1024; + uint8_t* p = alloc.allocate(kSize); + ASSERT_NE(p, nullptr); + std::memset(p, kBackFillByte, kSize); + EXPECT_EQ(p[0], kBackFillByte); + EXPECT_EQ(p[kSize - 1], kBackFillByte); + alloc.deallocate(p, kSize); +} + +TEST(DefaultAllocatorBasicTest, DeallocateSizeArgumentIgnored) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::deallocate"); + RecordProperty("Description", "deallocate accepts any size argument without crashing"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + uint8_t* p = alloc.allocate(64); + ASSERT_NE(p, nullptr); + alloc.deallocate(p, 999); +} + +TEST(DefaultAllocatorBasicTest, StaticDeallocDoesNotCrash) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::dealloc"); + RecordProperty("Description", "static dealloc method frees memory without crashing"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + uint8_t* p = alloc.allocate(32); + ASSERT_NE(p, nullptr); + DefaultAllocator::dealloc(static_cast(p), 32); +} + +TEST(DefaultAllocatorBasicTest, UsableThroughBasePointer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::allocate, ::flatbuffers::DefaultAllocator::deallocate, ~DefaultAllocator, Allocator virtual interface"); + RecordProperty("Description", "DefaultAllocator is usable through base Allocator pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Allocator* alloc = new DefaultAllocator(); + uint8_t* p = alloc->allocate(16); + ASSERT_NE(p, nullptr); + alloc->deallocate(p, 16); + delete alloc; +} + +TEST(DefaultAllocatorBasicTest, MultipleAllocationsDoNotAlias) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DefaultAllocator::allocate, ::flatbuffers::DefaultAllocator::deallocate"); + RecordProperty("Description", "multiple independent allocations do not alias"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + uint8_t* p1 = alloc.allocate(64); + uint8_t* p2 = alloc.allocate(64); + ASSERT_NE(p1, nullptr); + ASSERT_NE(p2, nullptr); + EXPECT_NE(p1, p2); + alloc.deallocate(p1, 64); + alloc.deallocate(p2, 64); +} + +// --------------------------------------------------------------------------- +// AllocateFreeHelperTest +// Tests Allocate(Allocator*, size_t). +// --------------------------------------------------------------------------- + +TEST(AllocateFreeHelperTest, NullAllocatorUsesDefault) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Allocate"); + RecordProperty("Description", "null allocator falls back to DefaultAllocator"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + uint8_t* p = Allocate(nullptr, 64); + ASSERT_NE(p, nullptr); + std::memset(p, 0x11, 64); + EXPECT_EQ(p[0], 0x11); + Deallocate(nullptr, p, 64); +} + +TEST(AllocateFreeHelperTest, CustomAllocatorIsUsed) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Allocate"); + RecordProperty("Description", "valid allocator is delegated to by Allocate"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + uint8_t* p = Allocate(&alloc, 64); + ASSERT_NE(p, nullptr); + std::memset(p, 0x22, 64); + EXPECT_EQ(p[0], 0x22); + Deallocate(&alloc, p, 64); +} + +// --------------------------------------------------------------------------- +// DeallocateFreeHelperTest +// Tests Deallocate(Allocator*, uint8_t*, size_t). +// --------------------------------------------------------------------------- + +TEST(DeallocateFreeHelperTest, NullAllocatorUsesDefault) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Deallocate"); + RecordProperty("Description", "null allocator falls back to DefaultAllocator"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator default_alloc; + uint8_t* p = default_alloc.allocate(32); + ASSERT_NE(p, nullptr); + Deallocate(nullptr, p, 32); +} + +TEST(DeallocateFreeHelperTest, CustomAllocatorIsUsed) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Deallocate"); + RecordProperty("Description", "valid allocator is delegated to by Deallocate"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + uint8_t* p = alloc.allocate(32); + ASSERT_NE(p, nullptr); + Deallocate(&alloc, p, 32); +} + +// --------------------------------------------------------------------------- +// ReallocateDownwardFreeHelperTest +// Tests ReallocateDownward. +// --------------------------------------------------------------------------- + +TEST(ReallocateDownwardFreeHelperTest, NullAllocatorUsesDefault) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ReallocateDownward"); + RecordProperty("Description", "null allocator falls back to DefaultAllocator"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator tmp; + constexpr size_t kOld = 64; + constexpr size_t kNew = 128; + uint8_t* old_p = tmp.allocate(kOld); + ASSERT_NE(old_p, nullptr); + + uint8_t* new_p = ReallocateDownward(nullptr, old_p, kOld, kNew, 0, 0); + ASSERT_NE(new_p, nullptr); + Deallocate(nullptr, new_p, kNew); +} + +TEST(ReallocateDownwardFreeHelperTest, CustomAllocatorIsUsed) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ReallocateDownward"); + RecordProperty("Description", "valid allocator is delegated to by ReallocateDownward"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DefaultAllocator alloc; + constexpr size_t kOld = 64; + constexpr size_t kNew = 128; + uint8_t* old_p = alloc.allocate(kOld); + ASSERT_NE(old_p, nullptr); + + uint8_t* new_p = ReallocateDownward(&alloc, old_p, kOld, kNew, 0, 0); + ASSERT_NE(new_p, nullptr); + alloc.deallocate(new_p, kNew); +} + +TEST(ReallocateDownwardFreeHelperTest, NullAllocatorPreservesBackData) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ReallocateDownward"); + RecordProperty("Description", "ReallocateDownward preserves back data via null-allocator path"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + DefaultAllocator tmp; + constexpr size_t kOld = 64; + constexpr size_t kNew = 128; + constexpr size_t kBack = 16; + + uint8_t* old_p = tmp.allocate(kOld); + ASSERT_NE(old_p, nullptr); + for (size_t i = 0; i < kBack; ++i) + { + old_p[kOld - kBack + i] = static_cast(i + 10); + } + + uint8_t* new_p = ReallocateDownward(nullptr, old_p, kOld, kNew, kBack, 0); + ASSERT_NE(new_p, nullptr); + + for (size_t i = 0; i < kBack; ++i) + { + EXPECT_EQ(new_p[kNew - kBack + i], static_cast(i + 10)) << "mismatch at back index " << i; + } + Deallocate(nullptr, new_p, kNew); +} + +TEST(ReallocateDownwardFreeHelperTest, CustomAllocatorPreservesFrontData) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ReallocateDownward"); + RecordProperty("Description", "ReallocateDownward preserves front data via custom-allocator path"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + DefaultAllocator alloc; + constexpr size_t kOld = 64; + constexpr size_t kNew = 128; + constexpr size_t kFront = 8; + + uint8_t* old_p = alloc.allocate(kOld); + ASSERT_NE(old_p, nullptr); + for (size_t i = 0; i < kFront; ++i) + { + old_p[i] = static_cast(0xC0 + i); + } + + uint8_t* new_p = ReallocateDownward(&alloc, old_p, kOld, kNew, 0, kFront); + ASSERT_NE(new_p, nullptr); + + for (size_t i = 0; i < kFront; ++i) + { + EXPECT_EQ(new_p[i], static_cast(0xC0 + i)) << "mismatch at front index " << i; + } + alloc.deallocate(new_p, kNew); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_detached_buffer_test.cpp b/score/flatbuffers/details/flatbuffers_detached_buffer_test.cpp new file mode 100644 index 0000000000..e506260be6 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_detached_buffer_test.cpp @@ -0,0 +1,213 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/detached_buffer.h" + +#include +#include + +#include "flatbuffers/default_allocator.h" +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// DetachedBufferDefaultConstructTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferDefaultConstructTest, Empty) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::DetachedBuffer"); + RecordProperty("Description", "default-constructed DetachedBuffer is empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + DetachedBuffer db; + EXPECT_EQ(db.data(), nullptr); + EXPECT_EQ(db.size(), 0u); + EXPECT_EQ(db.begin(), db.end()); +} + +// --------------------------------------------------------------------------- +// DetachedBufferFromBuilderTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferFromBuilderTest, FromBuilder) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::data, ::flatbuffers::DetachedBuffer::size, ::flatbuffers::DetachedBuffer::begin, ::flatbuffers::DetachedBuffer::end"); + RecordProperty("Description", "DetachedBuffer produced by Release has correct data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto str = fbb.CreateString("hello"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, str); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + DetachedBuffer db = fbb.Release(); + EXPECT_NE(db.data(), nullptr); + EXPECT_GT(db.size(), 0u); + EXPECT_EQ(static_cast(db.end() - db.begin()), db.size()); +} + +// --------------------------------------------------------------------------- +// DetachedBufferMoveConstructTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferMoveConstructTest, TransfersOwnership) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::DetachedBuffer(DetachedBuffer&&)"); + RecordProperty("Description", "move constructor transfers ownership; source becomes empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + DetachedBuffer original = fbb.Release(); + auto original_size = original.size(); + auto* original_data = original.data(); + EXPECT_GT(original_size, 0u); + + DetachedBuffer moved(std::move(original)); + EXPECT_EQ(moved.size(), original_size); + EXPECT_EQ(moved.data(), original_data); + EXPECT_EQ(original.data(), nullptr); + EXPECT_EQ(original.size(), 0u); +} + +// --------------------------------------------------------------------------- +// DetachedBufferMoveAssignTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferMoveAssignTest, TransfersOwnership) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::operator=(DetachedBuffer&&)"); + RecordProperty("Description", "move assignment transfers; destination cleaned up"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb1; + { + auto start = fbb1.StartTable(); + auto root = fbb1.EndTable(start); + fbb1.Finish(Offset
(root)); + } + DetachedBuffer db1 = fbb1.Release(); + auto size1 = db1.size(); + + FlatBufferBuilder fbb2; + { + auto start = fbb2.StartTable(); + auto root = fbb2.EndTable(start); + fbb2.Finish(Offset
(root)); + } + DetachedBuffer db2 = fbb2.Release(); + + db2 = std::move(db1); + EXPECT_EQ(db2.size(), size1); + EXPECT_EQ(db1.data(), nullptr); + EXPECT_EQ(db1.size(), 0u); +} + +// --------------------------------------------------------------------------- +// DetachedBufferSelfMoveAssignTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferSelfMoveAssignTest, Safe) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::operator=(DetachedBuffer&&)"); + RecordProperty("Description", "self-move-assignment is safe"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + DetachedBuffer db = fbb.Release(); + auto sz = db.size(); + auto* ptr = db.data(); + + DetachedBuffer& ref = db; + db = std::move(ref); + EXPECT_EQ(db.size(), sz); + EXPECT_EQ(db.data(), ptr); +} + +// --------------------------------------------------------------------------- +// DetachedBufferBeginEndTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferBeginEndTest, SpanCorrectRange) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::begin, ::flatbuffers::DetachedBuffer::end, ::flatbuffers::DetachedBuffer::data"); + RecordProperty("Description", "begin/end span the correct range"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + DetachedBuffer db = fbb.Release(); + EXPECT_EQ(static_cast(db.end() - db.begin()), db.size()); + + const DetachedBuffer& cdb = db; + EXPECT_EQ(static_cast(cdb.end() - cdb.begin()), cdb.size()); + EXPECT_EQ(cdb.data(), cdb.begin()); +} + +// --------------------------------------------------------------------------- +// DetachedBufferDestroyOwnedAllocatorTest +// --------------------------------------------------------------------------- + +TEST(DetachedBufferDestroyOwnedAllocatorTest, OwnsAllocator) +{ + RecordProperty("FullyVerifies", "::flatbuffers::DetachedBuffer::destroy"); + RecordProperty("Description", "DetachedBuffer with own_allocator=true deletes the allocator on destruction"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto* alloc = new DefaultAllocator(); + + constexpr size_t kBufSize = 64; + uint8_t* buf = alloc->allocate(kBufSize); + ASSERT_NE(buf, nullptr); + + std::memset(buf, 0xAB, kBufSize); + + DetachedBuffer db(alloc, true, buf, kBufSize, buf, kBufSize); + + EXPECT_EQ(db.data(), buf); + EXPECT_EQ(db.size(), kBufSize); + EXPECT_EQ(db.data()[0], 0xAB); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_flatbuffer_builder_test.cpp b/score/flatbuffers/details/flatbuffers_flatbuffer_builder_test.cpp new file mode 100644 index 0000000000..552e787433 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_flatbuffer_builder_test.cpp @@ -0,0 +1,1699 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/flatbuffer_builder.h" + +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// ----------------------- +// FlatBufferBuilderBasicTest +// Tests construction. +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderBasicTest, DefaultConstruct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::FlatBufferBuilder"); + RecordProperty("Description", "newly-constructed builder has no data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + EXPECT_EQ(fbb.GetSize(), 0u); +} + +TEST(FlatBufferBuilderBasicTest, CustomInitialSize) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::FlatBufferBuilder(size_t)"); + RecordProperty("Description", "custom initial size accepted, builder still has zero size"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb1(1); + EXPECT_EQ(fbb1.GetSize(), 0u); + + FlatBufferBuilder fbb2(4096); + EXPECT_EQ(fbb2.GetSize(), 0u); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateStringTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateStringTest, Normal) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateString"); + RecordProperty("Description", "string creation works for normal, empty, const std::string, char*, and long strings"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + FlatBufferBuilder fbb; + auto s = fbb.CreateString("hello"); + EXPECT_FALSE(s.IsNull()); + } + { + FlatBufferBuilder fbb; + std::string str = "world"; + auto s = fbb.CreateString(str); + EXPECT_FALSE(s.IsNull()); + } + { + FlatBufferBuilder fbb; + auto s = fbb.CreateString(""); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* str = table->GetPointer(4); + ASSERT_NE(str, nullptr); + EXPECT_EQ(str->size(), 0u); + EXPECT_STREQ(str->c_str(), ""); + } + { + FlatBufferBuilder fbb; + std::string long_str(10000, 'Z'); + auto s = fbb.CreateString(long_str); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* str = table->GetPointer(4); + ASSERT_NE(str, nullptr); + EXPECT_EQ(str->size(), 10000u); + } + { + FlatBufferBuilder fbb; + char str[] = "mutable_string"; + auto s = fbb.CreateString(str); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* result = table->GetPointer(4); + ASSERT_NE(result, nullptr); + EXPECT_STREQ(result->c_str(), "mutable_string"); + EXPECT_EQ(result->size(), 14u); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateStringFromPtrTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateStringFromPtrTest, FromStringPtr) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateString(const String*)"); + RecordProperty("Description", "CreateString(const String*) copies a String pointer or returns null for nullptr"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto off = fbb.CreateString(static_cast(nullptr)); + EXPECT_EQ(off.o, 0u); + } + { + FlatBufferBuilder fbb; + auto s = fbb.CreateString("source_string"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + const String* str_ptr = table->GetPointer(4); + ASSERT_NE(str_ptr, nullptr); + + FlatBufferBuilder fbb2; + auto s2 = fbb2.CreateString(str_ptr); + EXPECT_FALSE(s2.IsNull()); + auto start2 = fbb2.StartTable(); + fbb2.AddOffset(4, s2); + auto root2 = fbb2.EndTable(start2); + fbb2.Finish(Offset
(root2)); + + auto* buf2 = fbb2.GetBufferPointer(); + auto* table2 = GetRoot
(buf2); + const String* result = table2->GetPointer(4); + ASSERT_NE(result, nullptr); + EXPECT_STREQ(result->c_str(), "source_string"); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorTest, Scalars) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVector"); + RecordProperty("Description", "CreateVector works for std::vector, plain array, initializer_list, empty, and null elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + std::vector data = {1, 2, 3, 4, 5}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 5u); + EXPECT_EQ(v->Get(0), 1); + EXPECT_EQ(v->Get(4), 5); + } + { + FlatBufferBuilder fbb; + std::vector data; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 0u); + } + { + FlatBufferBuilder fbb; + int32_t raw[] = {10, 20}; + auto vec = fbb.CreateVector(raw, 2); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 2u); + EXPECT_EQ(v->Get(0), 10); + EXPECT_EQ(v->Get(1), 20); + } + { + FlatBufferBuilder fbb; + auto vec = fbb.CreateVector({10, 20, 30}); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(0), 10); + EXPECT_EQ(v->Get(2), 30); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorOfStringsTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorOfStringsTest, FromStrings) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfStrings"); + RecordProperty("Description", "CreateVectorOfStrings creates vector of string offsets from std::vector and iterators"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + std::vector strs = {"alpha", "beta", "gamma"}; + auto vec = fbb.CreateVectorOfStrings(strs); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_STREQ(v->Get(0)->c_str(), "alpha"); + EXPECT_STREQ(v->Get(2)->c_str(), "gamma"); + } + { + FlatBufferBuilder fbb; + std::vector strs = {"one", "two", "three"}; + auto vec = fbb.CreateVectorOfStrings(strs.begin(), strs.end()); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_STREQ(v->Get(0)->c_str(), "one"); + EXPECT_STREQ(v->Get(2)->c_str(), "three"); + } +} + +TEST(FlatBufferBuilderCreateVectorOfStringsTest, OfOffsetsRawArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVector(const Offset*, size_t)"); + RecordProperty("Description", "CreateVector with raw array of Offset elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto s0 = fbb.CreateString("first"); + auto s1 = fbb.CreateString("second"); + Offset offsets[2] = {s0, s1}; + auto vec = fbb.CreateVector(offsets, 2); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 2u); + EXPECT_STREQ(v->Get(0)->c_str(), "first"); + EXPECT_STREQ(v->Get(1)->c_str(), "second"); +} + +TEST(FlatBufferBuilderCreateVectorOfStringsTest, BoolVector) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVector(const std::vector&)"); + RecordProperty("Description", "vector serialises as vector of uint8_t"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + std::vector bools = {true, false, true, true, false}; + auto vec = fbb.CreateVector(bools); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 5u); + EXPECT_EQ(v->Get(0), 1u); + EXPECT_EQ(v->Get(1), 0u); + EXPECT_EQ(v->Get(2), 1u); + EXPECT_EQ(v->Get(3), 1u); + EXPECT_EQ(v->Get(4), 0u); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorGeneratorTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorGeneratorTest, FuncAndStateful) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVector(size_t, std::function, CreateVector(size_t, F, S*))"); + RecordProperty("Description", "generator function and stateful generator function produce correct values"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto vec = fbb.CreateVector(5, [](size_t i) { return static_cast(i * i); }); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 5u); + for (size_t i = 0; i < 5; i++) + { + EXPECT_EQ(v->Get(static_cast(i)), static_cast(i * i)); + } + } + { + FlatBufferBuilder fbb; + int base = 100; + auto vec = fbb.CreateVector(4, [](size_t i, int* state) { return static_cast(*state + i); }, &base); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 4u); + EXPECT_EQ(v->Get(0), 100); + EXPECT_EQ(v->Get(3), 103); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderTableBuildTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderTableBuildTest, ScalarFields) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::StartTable, EndTable, AddElement"); + RecordProperty("Description", "building a table with scalar fields stores and reads back correctly"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + fbb.AddElement(6, -100, 0); + fbb.AddElement(8, 255, 0); + fbb.AddElement(10, 1, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + + EXPECT_EQ(table->GetField(4, 0), 42); + EXPECT_EQ(table->GetField(6, 0), static_cast(-100)); + EXPECT_EQ(table->GetField(8, 0), 255); + EXPECT_EQ(table->GetField(10, 0), 1); +} + +TEST(FlatBufferBuilderTableBuildTest, AddElementNoDefault) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::AddElement (two-argument overload)"); + RecordProperty("Description", "two-argument AddElement always stores the field regardless of value"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_TRUE(table->CheckField(4)); + EXPECT_EQ(table->GetField(4, 99), 0); +} + +TEST(FlatBufferBuilderTableBuildTest, MultipleTables) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::StartTable, EndTable, AddOffset"); + RecordProperty("Description", "building multiple tables in the same buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + + auto start1 = fbb.StartTable(); + fbb.AddElement(4, 100, 0); + auto sub1 = fbb.EndTable(start1); + + auto start2 = fbb.StartTable(); + fbb.AddElement(4, 200, 0); + auto sub2 = fbb.EndTable(start2); + + auto start_root = fbb.StartTable(); + fbb.AddOffset(4, Offset<>(sub1)); + fbb.AddOffset(6, Offset<>(sub2)); + auto root = fbb.EndTable(start_root); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* t1 = table->GetPointer(4); + auto* t2 = table->GetPointer(6); + ASSERT_NE(t1, nullptr); + ASSERT_NE(t2, nullptr); + EXPECT_EQ(t1->GetField(4, 0), 100); + EXPECT_EQ(t2->GetField(4, 0), 200); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderForceDefaultsTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderForceDefaultsTest, ForceDefaults) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::ForceDefaults"); + RecordProperty("Description", "ForceDefaults controls whether default values are stored"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 0, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_FALSE(table->CheckField(4)); + } + { + FlatBufferBuilder fbb; + fbb.ForceDefaults(true); + auto start = fbb.StartTable(); + fbb.AddElement(4, 0, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_TRUE(table->CheckField(4)); + EXPECT_EQ(table->GetField(4, 99), 0); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderFinishTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderFinishTest, WithIdentifier) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::Finish"); + RecordProperty("Description", "Finish with a file identifier stores it in the buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root), "MYID"); + + auto* buf = fbb.GetBufferPointer(); + EXPECT_TRUE(BufferHasIdentifier(buf, "MYID")); + EXPECT_FALSE(BufferHasIdentifier(buf, "XXXX")); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderFinishSizePrefixedTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderFinishSizePrefixedTest, Prefix) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::FinishSizePrefixed"); + RecordProperty("Description", "FinishSizePrefixed produces a size-prefixed buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.FinishSizePrefixed(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto size = fbb.GetSize(); + + auto prefix = ReadScalar(buf); + EXPECT_EQ(static_cast(prefix + sizeof(uoffset_t)), size); + + auto* table = GetSizePrefixedRoot
(buf); + ASSERT_NE(table, nullptr); + EXPECT_EQ(table->GetField(4, 0), 42); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderReleaseTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderReleaseTest, Reset) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::Release, ReleaseRaw, Reset, Clear"); + RecordProperty("Description", "Release / ReleaseRaw return buffer data; Reset / Clear for reuse"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto size_before = fbb.GetSize(); + EXPECT_GT(size_before, 0u); + + auto db = fbb.Release(); + EXPECT_EQ(db.size(), size_before); + EXPECT_NE(db.data(), nullptr); + EXPECT_EQ(fbb.GetSize(), 0u); + } + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + size_t size, offset; + auto* raw = fbb.ReleaseRaw(size, offset); + EXPECT_NE(raw, nullptr); + EXPECT_GT(size, 0u); + Deallocate(nullptr, raw, size); + } + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + EXPECT_GT(fbb.GetSize(), 0u); + + fbb.Clear(); + EXPECT_EQ(fbb.GetSize(), 0u); + + start = fbb.StartTable(); + fbb.AddElement(4, 99, 0); + root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 0), 99); + } + { + FlatBufferBuilder fbb(2048); + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + EXPECT_GT(fbb.GetSize(), 0u); + + fbb.Reset(); + EXPECT_EQ(fbb.GetSize(), 0u); + + start = fbb.StartTable(); + fbb.AddElement(4, 77, 0); + root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 0), 77); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderMoveTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderMoveTest, ConstructAndAssign) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::FlatBufferBuilder(FlatBufferBuilder&&), operator=(FlatBufferBuilder&&)"); + RecordProperty("Description", "move constructor and move assignment transfer builder state"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto str = fbb.CreateString("test"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, str); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto size = fbb.GetSize(); + FlatBufferBuilder moved(std::move(fbb)); + EXPECT_EQ(moved.GetSize(), size); +} + +TEST(FlatBufferBuilderMoveTest, Assign) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::operator=(FlatBufferBuilder&&)"); + RecordProperty("Description", "move assignment transfers builder state to another builder"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + auto size = fbb.GetSize(); + + FlatBufferBuilder other; + other = std::move(fbb); + EXPECT_EQ(other.GetSize(), size); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderSwapTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderSwapTest, Exchanges) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::Swap"); + RecordProperty("Description", "Swap exchanges two builders' contents"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb1; + { + auto start = fbb1.StartTable(); + fbb1.AddElement(4, 1, 0); + auto root = fbb1.EndTable(start); + fbb1.Finish(Offset
(root)); + } + auto size1 = fbb1.GetSize(); + + FlatBufferBuilder fbb2; + { + auto start = fbb2.StartTable(); + fbb2.AddElement(4, 2, 0); + auto root = fbb2.EndTable(start); + fbb2.Finish(Offset
(root)); + } + auto size2 = fbb2.GetSize(); + + fbb1.Swap(fbb2); + EXPECT_EQ(fbb1.GetSize(), size2); + EXPECT_EQ(fbb2.GetSize(), size1); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderSharedStringTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderSharedStringTest, Deduplication) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateSharedString, CreateSharedStringStdString, CreateSharedStringFromStringPtr"); + RecordProperty("Description", "CreateSharedString deduplicates identical strings"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto s1 = fbb.CreateSharedString("duplicate"); + auto s2 = fbb.CreateSharedString("duplicate"); + auto s3 = fbb.CreateSharedString("different"); + EXPECT_EQ(s1.o, s2.o); + EXPECT_NE(s1.o, s3.o); + } + { + FlatBufferBuilder fbb; + std::string s = "shared_std"; + auto off1 = fbb.CreateSharedString(s); + auto off2 = fbb.CreateSharedString(s); + EXPECT_EQ(off1.o, off2.o); + } + { + FlatBufferBuilder fbb; + auto off = fbb.CreateSharedString(static_cast(nullptr)); + EXPECT_EQ(off.o, 0u); + } + { + FlatBufferBuilder fbb; + auto off1 = fbb.CreateSharedString("ptr_shared"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, off1); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + const String* str_ptr = table->GetPointer(4); + ASSERT_NE(str_ptr, nullptr); + EXPECT_STREQ(str_ptr->c_str(), "ptr_shared"); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderStructTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderStructTest, StartEndStruct) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::StartStruct, EndStruct"); + RecordProperty("Description", "struct alignment and offset tracking"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto off1 = fbb.StartStruct(8); + EXPECT_EQ(off1, 0u); + + uint64_t val = 0x0102030405060708ULL; + fbb.PushBytes(reinterpret_cast(&val), sizeof(val)); + + auto off2 = fbb.EndStruct(); + EXPECT_EQ(off2, static_cast(sizeof(val))); + EXPECT_GT(off2, off1); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderAddOffset64Test +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderAddOffset64Test, Offset64) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::AddOffset (Offset64 overload)"); + RecordProperty("Description", "AddOffset with Offset64: null not stored, non-null stored"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder64 fbb; + auto start = fbb.StartTable(); + Offset64 null_off{0}; + fbb.AddOffset(4, null_off); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_FALSE(table->CheckField(4)); + } + { + FlatBufferBuilder64 fbb; + auto str = fbb.CreateString("test", 4); + EXPECT_FALSE(str.IsNull()); + auto start = fbb.StartTable(); + fbb.AddOffset(4, str); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + EXPECT_GT(fbb.GetSize(), 0u); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_TRUE(table->CheckField(4)); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderAddStructOffsetTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderAddStructOffsetTest, TracksOffset) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::AddStructOffset"); + RecordProperty("Description", "manually tracks a struct field at a given offset"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.Align(4); + uint32_t val = 0x12345678; + fbb.PushBytes(reinterpret_cast(&val), sizeof(val)); + fbb.AddStructOffset(4, static_cast(fbb.GetSizeRelative32BitRegion())); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_TRUE(table->CheckField(4)); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderReferToTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderReferToTest, UOffset64AndTemplated) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::ReferTo"); + RecordProperty("Description", "ReferTo computes relative offsets for uoffset64_t and templated overloads"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder64 fbb; + const uint8_t zeros[16] = {}; + fbb.PushBytes(zeros, 16); + auto result = fbb.ReferTo(static_cast(8)); + EXPECT_EQ(result, static_cast(16)); + } + { + FlatBufferBuilder fbb; + auto r = fbb.ReferTo(static_cast(10), static_cast(20)); + EXPECT_EQ(r, 14u); + } + { + FlatBufferBuilder fbb; + auto r = fbb.ReferTo(static_cast(5), static_cast(30)); + EXPECT_EQ(r, static_cast(33)); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderEndTableDeprecatedTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderEndTableDeprecatedTest, Delegates) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::EndTable (deprecated two-argument overload)"); + RecordProperty("Description", "deprecated two-argument EndTable delegates to single-argument version"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start, 1); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 0), 42); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderRequiredTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderRequiredTest, PresentField) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::Required"); + RecordProperty("Description", "Required does not assert when field is present"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto str = fbb.CreateString("required_field"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, str); + auto root = fbb.EndTable(start); + + fbb.Required(Offset
(root), 4); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_STREQ(s->c_str(), "required_field"); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderFieldIndexToOffsetTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderFieldIndexToOffsetTest, VtableLayout) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FieldIndexToOffset"); + RecordProperty("Description", "field index 0 gives 4, field index n gives 4+n*2"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(FieldIndexToOffset(0), static_cast(4)); + EXPECT_EQ(FieldIndexToOffset(1), static_cast(6)); + EXPECT_EQ(FieldIndexToOffset(2), static_cast(8)); + EXPECT_EQ(FieldIndexToOffset(10), static_cast(24)); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderDedupVtablesTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderDedupVtablesTest, DisabledCreatesLargerBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::DedupVtables"); + RecordProperty("Description", "disabling dedup creates larger buffer for identical vtables"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb_dedup; + { + uoffset_t last = 0; + for (int i = 0; i < 4; i++) + { + auto s = fbb_dedup.StartTable(); + fbb_dedup.AddElement(4, i + 1, 0); + fbb_dedup.AddElement(6, i + 10, 0); + fbb_dedup.AddElement(8, i + 100, 0); + last = fbb_dedup.EndTable(s); + } + fbb_dedup.Finish(Offset
(last)); + } + auto size_dedup = fbb_dedup.GetSize(); + + FlatBufferBuilder fbb_no_dedup; + fbb_no_dedup.DedupVtables(false); + { + uoffset_t last = 0; + for (int i = 0; i < 4; i++) + { + auto s = fbb_no_dedup.StartTable(); + fbb_no_dedup.AddElement(4, i + 1, 0); + fbb_no_dedup.AddElement(6, i + 10, 0); + fbb_no_dedup.AddElement(8, i + 100, 0); + last = fbb_no_dedup.EndTable(s); + } + fbb_no_dedup.Finish(Offset
(last)); + } + auto size_no_dedup = fbb_no_dedup.GetSize(); + + EXPECT_GT(size_no_dedup, size_dedup); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderPushFlatBufferTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderPushFlatBufferTest, PushesRawBytes) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::PushFlatBuffer"); + RecordProperty("Description", "PushFlatBuffer pushes raw bytes and marks buffer as finished"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder orig; + auto start = orig.StartTable(); + orig.AddElement(4, 42, 0); + auto root = orig.EndTable(start); + orig.Finish(Offset
(root)); + + auto* orig_ptr = orig.GetBufferPointer(); + auto orig_size = orig.GetSize(); + + FlatBufferBuilder fbb; + fbb.PushFlatBuffer(orig_ptr, orig_size); + + auto* buf = fbb.GetBufferPointer(); + EXPECT_NE(buf, nullptr); + EXPECT_EQ(fbb.GetSize(), orig_size); + + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 0), 42); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderDataFreeFunctionTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderDataFreeFunctionTest, VectorOverloads) +{ + RecordProperty("FullyVerifies", "::flatbuffers::data (std::vector overloads)"); + RecordProperty("Description", "data returns &front() for non-empty, non-null for empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + std::vector v = {10, 20, 30}; + int32_t* ptr = data(v); + EXPECT_EQ(ptr, &v.front()); + *ptr = 99; + EXPECT_EQ(v[0], 99); + } + { + const std::vector cv = {1, 2, 3}; + const int32_t* cptr = data(cv); + EXPECT_EQ(cptr, &cv.front()); + } + { + std::vector empty; + int32_t* ptr = data(empty); + EXPECT_NE(ptr, nullptr); + } + { + const std::vector empty; + const int32_t* cptr = data(empty); + EXPECT_NE(cptr, nullptr); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderBufferSpanTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderBufferSpanTest, MatchesBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::GetBufferSpan"); + RecordProperty("Description", "GetBufferSpan returns span matching buffer pointer and size"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto span = fbb.GetBufferSpan(); + EXPECT_EQ(span.data(), fbb.GetBufferPointer()); + EXPECT_EQ(span.size(), fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderGetCurrentBufferPointerTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderGetCurrentBufferPointerTest, BeforeAndAfterFinish) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::GetCurrentBufferPointer"); + RecordProperty("Description", "GetCurrentBufferPointer available before Finish, equals GetBufferPointer after"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + + uint8_t* ptr_before = fbb.GetCurrentBufferPointer(); + EXPECT_NE(ptr_before, nullptr); + + fbb.Finish(Offset
(root)); + EXPECT_EQ(fbb.GetCurrentBufferPointer(), fbb.GetBufferPointer()); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderBufferMinAlignmentTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderBufferMinAlignmentTest, ReflectsLargestScalar) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::GetBufferMinAlignment"); + RecordProperty("Description", "alignment reflects largest scalar written"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 1, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + EXPECT_GE(fbb.GetBufferMinAlignment(), 1u); + } + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 3.14, 0.0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + EXPECT_GE(fbb.GetBufferMinAlignment(), sizeof(double)); + } +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderTemporaryPointersTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderTemporaryPointersTest, GetTemporaryPointer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetTemporaryPointer, ::flatbuffers::GetMutableTemporaryPointer"); + RecordProperty("Description", "temporary pointer functions return typed pointer into in-progress buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto table_off = fbb.EndTable(start); + Offset
off(table_off); + + Table* mutable_ptr = GetMutableTemporaryPointer(fbb, off); + ASSERT_NE(mutable_ptr, nullptr); + EXPECT_EQ(mutable_ptr->GetField(4, 0), 42); + + const Table* const_ptr = GetTemporaryPointer(static_cast(fbb), off); + ASSERT_NE(const_ptr, nullptr); + EXPECT_EQ(reinterpret_cast(mutable_ptr), reinterpret_cast(const_ptr)); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderSwapBufAllocatorTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderSwapBufAllocatorTest, PreservesData) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::SwapBufAllocator"); + RecordProperty("Description", "swapping allocators between builders preserves buffer data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb1; + auto start = fbb1.StartTable(); + fbb1.AddElement(4, 77, 0); + auto root = fbb1.EndTable(start); + fbb1.Finish(Offset
(root)); + auto size1 = fbb1.GetSize(); + + FlatBufferBuilder fbb2; + fbb1.SwapBufAllocator(fbb2); + + EXPECT_EQ(fbb1.GetSize(), size1); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderFileIdentifierLengthTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderFileIdentifierLengthTest, ConstantEqualsFour) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::kFileIdentifierLength"); + RecordProperty("Description", "kFileIdentifierLength equals 4"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(FlatBufferBuilder::kFileIdentifierLength + 0u, 4u); + EXPECT_EQ(FlatBufferBuilder64::kFileIdentifierLength + 0u, 4u); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVector64Test +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVector64Test, Produces64BitVector) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder64::CreateVector64"); + RecordProperty("Description", "CreateVector64 produces a 64-bit offset vector"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder64 fbb; + std::vector vals = {1.0f, 2.0f, 3.0f}; + auto vec = fbb.CreateVector64(vals); + EXPECT_FALSE(vec.IsNull()); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderReleaseOwnedAllocatorTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderReleaseOwnedAllocatorTest, DetachedBufferGetsAllocator) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::Release"); + RecordProperty("Description", "Release with owned allocator transfers ownership to DetachedBuffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(1024, new DefaultAllocator(), true); + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + const auto size_before = fbb.GetSize(); + auto db = fbb.Release(); + EXPECT_EQ(db.size(), size_before); + EXPECT_NE(db.data(), nullptr); + EXPECT_EQ(fbb.GetSize(), 0u); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderForceVectorAlignmentTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderForceVectorAlignmentTest, AcceptsAlignment) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::ForceVectorAlignment"); + RecordProperty("Description", "ForceVectorAlignment specifies alignment for vectors"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + fbb.ForceVectorAlignment(4, sizeof(uint8_t), 16); + auto vec = fbb.CreateVector({1, 2, 3, 4}); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 4u); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderForceStringAlignmentTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderForceStringAlignmentTest, AcceptsAlignment) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::ForceStringAlignment"); + RecordProperty("Description", "ForceStringAlignment specifies alignment for strings"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + fbb.ForceStringAlignment(5, 8); + auto s = fbb.CreateString("align_me"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* str = table->GetPointer(4); + ASSERT_NE(str, nullptr); + EXPECT_STREQ(str->c_str(), "align_me"); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorOfStructsTest +// --------------------------------------------------------------------------- + +#pragma pack(push, 1) +struct Point2D FLATBUFFERS_FINAL_CLASS +{ + int32_t x_; + int32_t y_; + + public: + Point2D() : x_(0), y_(0) {} + Point2D(int32_t x, int32_t y) : x_(EndianScalar(x)), y_(EndianScalar(y)) {} + int32_t x() const + { + return EndianScalar(x_); + } + int32_t y() const + { + return EndianScalar(y_); + } + bool KeyCompareLessThan(const Point2D* other) const + { + return x() < other->x(); + } +}; +#pragma pack(pop) +static_assert(sizeof(Point2D) == 8, "Point2D must be 8 bytes"); + +struct NativePoint +{ + int32_t x; + int32_t y; +}; + +static Point2D PackNativePoint(const NativePoint& src) +{ + return Point2D(src.x, src.y); +} + +TEST(FlatBufferBuilderCreateVectorOfStructsTest, RawArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfStructs(const T*, size_t)"); + RecordProperty("Description", "CreateVectorOfStructs with raw struct array"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + Point2D pts[3] = {Point2D(1, 2), Point2D(3, 4), Point2D(5, 6)}; + auto vec = fbb.CreateVectorOfStructs(pts, 3); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(0)->x(), 1); + EXPECT_EQ(v->Get(2)->x(), 5); +} + +TEST(FlatBufferBuilderCreateVectorOfStructsTest, StdVector) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfStructs(const std::vector&)"); + RecordProperty("Description", "CreateVectorOfStructs with std::vector of structs"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + std::vector pts = {Point2D(10, 20), Point2D(30, 40)}; + auto vec = fbb.CreateVectorOfStructs(pts); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 2u); + EXPECT_EQ(v->Get(0)->x(), 10); + EXPECT_EQ(v->Get(1)->x(), 30); +} + +TEST(FlatBufferBuilderCreateVectorOfStructsTest, FillerFunc) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfStructs(size_t, std::function)"); + RecordProperty("Description", "CreateVectorOfStructs with filler function"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto vec = fbb.CreateVectorOfStructs(3, [](size_t i, Point2D* pt) { *pt = Point2D(static_cast(i), static_cast(i * 2)); }); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(0)->x(), 0); + EXPECT_EQ(v->Get(2)->x(), 2); +} + +TEST(FlatBufferBuilderCreateVectorOfStructsTest, StatefulFiller) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfStructs(size_t, F, S*)"); + RecordProperty("Description", "CreateVectorOfStructs with stateful filler function"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + int32_t base = 5; + auto vec = fbb.CreateVectorOfStructs(3, [](size_t i, Point2D* pt, int32_t* b) { *pt = Point2D(static_cast(i) + *b, 0); }, &base); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(0)->x(), 5); + EXPECT_EQ(v->Get(2)->x(), 7); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorOfNativeStructsTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorOfNativeStructsTest, WithPackFunc) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfNativeStructs(const S*, size_t, pack_func)"); + RecordProperty("Description", "CreateVectorOfNativeStructs with pack function"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + NativePoint pts[3] = {{1, 2}, {3, 4}, {5, 6}}; + auto vec = fbb.CreateVectorOfNativeStructs(pts, 3, PackNativePoint); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(2)->y(), 6); +} + +TEST(FlatBufferBuilderCreateVectorOfNativeStructsTest, StdVectorWithPackFunc) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfNativeStructs(const std::vector&, pack_func)"); + RecordProperty("Description", "CreateVectorOfNativeStructs with std::vector and pack function"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + std::vector pts = {{10, 20}, {30, 40}}; + auto vec = fbb.CreateVectorOfNativeStructs(pts, PackNativePoint); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 2u); + EXPECT_EQ(v->Get(1)->x(), 30); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorOfSortedStructsTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorOfSortedStructsTest, RawArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfSortedStructs(T*, size_t)"); + RecordProperty("Description", "CreateVectorOfSortedStructs sorts structs by key before serialisation"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + Point2D pts[4] = {Point2D(40, 0), Point2D(10, 0), Point2D(30, 0), Point2D(20, 0)}; + auto vec = fbb.CreateVectorOfSortedStructs(pts, 4); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 4u); + EXPECT_EQ(v->Get(0)->x(), 10); + EXPECT_EQ(v->Get(3)->x(), 40); +} + +TEST(FlatBufferBuilderCreateVectorOfSortedStructsTest, StdVector) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorOfSortedStructs(std::vector*)"); + RecordProperty("Description", "CreateVectorOfSortedStructs modifies vector in-place"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + std::vector pts = {Point2D(5, 0), Point2D(2, 0), Point2D(8, 0)}; + auto vec = fbb.CreateVectorOfSortedStructs(&pts); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_EQ(v->Get(1)->x(), 5); + EXPECT_EQ(v->Get(2)->x(), 8); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateUninitializedVectorTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateUninitializedVectorTest, RawAndTyped) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateUninitializedVector"); + RecordProperty("Description", "CreateUninitializedVector reserves space for manual filling"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + uint8_t* data_ptr = nullptr; + auto vec_offset = fbb.CreateUninitializedVector(4, sizeof(int32_t), alignof(int32_t), &data_ptr); + ASSERT_NE(data_ptr, nullptr); + auto* typed = reinterpret_cast(data_ptr); + typed[0] = 10; typed[1] = 20; typed[2] = 30; typed[3] = 40; + + auto start = fbb.StartTable(); + fbb.AddOffset(4, Offset>(vec_offset)); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->Get(3), 40); + } + { + FlatBufferBuilder fbb; + float* data_ptr = nullptr; + auto vec = fbb.CreateUninitializedVector(3u, &data_ptr); + ASSERT_NE(data_ptr, nullptr); + data_ptr[0] = 1.0f; data_ptr[1] = 2.0f; data_ptr[2] = 3.0f; + + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_FLOAT_EQ(v->Get(2), 3.0f); + } +} + +TEST(FlatBufferBuilderCreateUninitializedVectorOfStructsTest, Works) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateUninitializedVectorOfStructs"); + RecordProperty("Description", "CreateUninitializedVectorOfStructs reserves space for struct filling"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + Point2D* data_ptr = nullptr; + auto vec = fbb.CreateUninitializedVectorOfStructs(2u, &data_ptr); + ASSERT_NE(data_ptr, nullptr); + data_ptr[0] = Point2D(7, 8); + data_ptr[1] = Point2D(9, 10); + + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->Get(0)->x(), 7); + EXPECT_EQ(v->Get(1)->y(), 10); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateVectorScalarCastTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateVectorScalarCastTest, Casts) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateVectorScalarCast"); + RecordProperty("Description", "CreateVectorScalarCast casts each element from U to T"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + int8_t src[] = {1, -1, 127, -128}; + auto vec = fbb.CreateVectorScalarCast(src, 4); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->Get(0), 1); + EXPECT_EQ(v->Get(1), -1); + EXPECT_EQ(v->Get(3), -128); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderCreateStructTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderCreateStructTest, Standalone) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::CreateStruct"); + RecordProperty("Description", "CreateStruct writes a standalone struct"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + Point2D p(42, 99); + auto off = fbb.CreateStruct(p); + EXPECT_FALSE(off.IsNull()); +} + +// --------------------------------------------------------------------------- +// FlatBufferBuilderAddStructTest +// --------------------------------------------------------------------------- + +TEST(FlatBufferBuilderAddStructTest, NullAndNonNull) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder::AddStruct"); + RecordProperty("Description", "AddStruct: null pointer not stored, non-null stored"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddStruct(4, nullptr); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_FALSE(table->CheckField(4)); + } + { + FlatBufferBuilder fbb; + Point2D pt(3, 7); + auto start = fbb.StartTable(); + fbb.AddStruct(4, &pt); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_TRUE(table->CheckField(4)); + const Point2D* result = table->GetStruct(4); + ASSERT_NE(result, nullptr); + EXPECT_EQ(result->x(), 3); + EXPECT_EQ(result->y(), 7); + } +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_flatbuffers_test.cpp b/score/flatbuffers/details/flatbuffers_flatbuffers_test.cpp new file mode 100644 index 0000000000..4bea832d30 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_flatbuffers_test.cpp @@ -0,0 +1,272 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/flatbuffers.h" + +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Helper: build a simple buffer for reuse. +static std::vector BuildBuffer() +{ + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 99, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + auto* p = fbb.GetBufferPointer(); + return std::vector(p, p + fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// GetBufferStartFromRootPointerTest +// --------------------------------------------------------------------------- + +TEST(GetBufferStartFromRootPointerTest, NavigatesBack) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetBufferStartFromRootPointer"); + RecordProperty("Description", "navigates backwards from root pointer to find buffer start"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildBuffer(); + const auto* root = GetRoot
(buf.data()); + const auto* start = GetBufferStartFromRootPointer(root); + EXPECT_EQ(start, buf.data()); +} + +// --------------------------------------------------------------------------- +// GetPrefixedSizeTest +// --------------------------------------------------------------------------- + +TEST(GetPrefixedSizeTest, SizePrefixedBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetPrefixedSize"); + RecordProperty("Description", "GetPrefixedSize returns the embedded size from a size-prefixed buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.FinishSizePrefixed(Offset
(root)); + + auto* p = fbb.GetBufferPointer(); + auto prefix = GetPrefixedSize(p); + EXPECT_EQ(static_cast(prefix) + sizeof(uoffset_t), fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// GetSizePrefixedBufferLengthTest +// --------------------------------------------------------------------------- + +TEST(GetSizePrefixedBufferLengthTest, TotalLength) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetSizePrefixedBufferLength"); + RecordProperty("Description", "GetSizePrefixedBufferLength returns total buffer length including prefix"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.FinishSizePrefixed(Offset
(root)); + + auto len = GetSizePrefixedBufferLength(fbb.GetBufferPointer()); + EXPECT_EQ(len, fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// LookupEnumTest +// --------------------------------------------------------------------------- + +TEST(LookupEnumTest, StringToEnum) +{ + RecordProperty("FullyVerifies", "::flatbuffers::LookupEnum"); + RecordProperty("Description", "LookupEnum maps string names to enum indices"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + const char* names[] = {"Red", "Green", "Blue", nullptr}; + + EXPECT_EQ(LookupEnum(names, "Red"), 0); + EXPECT_EQ(LookupEnum(names, "Blue"), 2); + EXPECT_EQ(LookupEnum(names, "Yellow"), -1); +} + +// --------------------------------------------------------------------------- +// FieldIndexToOffsetTest +// --------------------------------------------------------------------------- + +TEST(FieldIndexToOffsetTest, VtableOffset) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FieldIndexToOffset"); + RecordProperty("Description", "field index maps to vtable offset"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(FieldIndexToOffset(0), 4u); + EXPECT_EQ(FieldIndexToOffset(1), 6u); + EXPECT_EQ(FieldIndexToOffset(2), 8u); +} + +// --------------------------------------------------------------------------- +// VersionStringTest +// --------------------------------------------------------------------------- + +TEST(VersionStringTest, WellFormed) +{ + RecordProperty("FullyVerifies", "FLATBUFFERS_VERSION"); + RecordProperty("Description", "version string is non-empty and well-formed"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + const char* vs = FLATBUFFERS_VERSION(); + EXPECT_NE(vs, nullptr); + EXPECT_GT(strlen(vs), 0u); + EXPECT_NE(strchr(vs, '.'), nullptr); +} + +// --------------------------------------------------------------------------- +// ElementaryTypeTest +// --------------------------------------------------------------------------- + +TEST(ElementaryTypeTest, EnumValuesExist) +{ + RecordProperty("FullyVerifies", "::flatbuffers::ElementaryType"); + RecordProperty("Description", "ElementaryType enum values exist and differ"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(static_cast(ET_UTYPE), 0); + EXPECT_EQ(static_cast(ET_BOOL), 1); + EXPECT_NE(static_cast(ET_STRING), static_cast(ET_BOOL)); +} + +// --------------------------------------------------------------------------- +// TypeCodeSizeTest +// --------------------------------------------------------------------------- + +TEST(TypeCodeSizeTest, TypeCodeToSize) +{ + RecordProperty("FullyVerifies", "ElementaryType size mapping"); + RecordProperty("Description", "type code maps to correct byte size"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + static const size_t sizes[] = { + 0, // ET_UTYPE + sizeof(uint8_t), // ET_BOOL + sizeof(int8_t), // ET_CHAR + sizeof(uint8_t), // ET_UCHAR + sizeof(int16_t), // ET_SHORT + sizeof(uint16_t), // ET_USHORT + sizeof(int32_t), // ET_INT + sizeof(uint32_t), // ET_UINT + sizeof(int64_t), // ET_LONG + sizeof(uint64_t), // ET_ULONG + sizeof(float), // ET_FLOAT + sizeof(double), // ET_DOUBLE + }; + EXPECT_EQ(sizes[ET_CHAR], 1u); + EXPECT_EQ(sizes[ET_INT], 4u); + EXPECT_EQ(sizes[ET_DOUBLE], 8u); +} + +// --------------------------------------------------------------------------- +// NativeTableTest +// --------------------------------------------------------------------------- + +TEST(NativeTableTest, BaseClass) +{ + RecordProperty("FullyVerifies", "::flatbuffers::NativeTable"); + RecordProperty("Description", "NativeTable base class exists"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + struct MyNativeTable : public NativeTable + { + int x = 5; + }; + MyNativeTable nt; + EXPECT_EQ(nt.x, 5); +} + +// --------------------------------------------------------------------------- +// RoundTripTest +// --------------------------------------------------------------------------- + +TEST(RoundTripTest, BuildReadVerify) +{ + RecordProperty("FullyVerifies", "::flatbuffers::FlatBufferBuilder round-trip, ::flatbuffers::Verifier"); + RecordProperty("Description", "round-trip build -> read -> verify"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto s = fbb.CreateString("roundtrip"); + auto start = fbb.StartTable(); + fbb.AddElement(4, 12345, 0); + fbb.AddOffset(6, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 0), 12345); + + auto* str = table->GetPointer(6); + ASSERT_NE(str, nullptr); + EXPECT_STREQ(str->c_str(), "roundtrip"); + + Verifier verifier(buf, fbb.GetSize()); + EXPECT_TRUE(verifier.Check(true)); +} + +// --------------------------------------------------------------------------- +// GetBufferStartFaultTest +// --------------------------------------------------------------------------- + +TEST(GetBufferStartFaultTest, CorruptRoot) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetBufferStartFromRootPointer"); + RecordProperty("Description", "corrupt root causes GetBufferStartFromRootPointer to trigger assert"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + uint8_t fake[64] = {}; + EXPECT_DEATH( + { + GetBufferStartFromRootPointer(fake + 32); + }, + ""); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_stl_emulation_test.cpp b/score/flatbuffers/details/flatbuffers_stl_emulation_test.cpp new file mode 100644 index 0000000000..6f48f79339 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_stl_emulation_test.cpp @@ -0,0 +1,306 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/stl_emulation.h" + +#include +#include + +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// OptionalDefaultConstructTest +// --------------------------------------------------------------------------- + +TEST(OptionalDefaultConstructTest, Empty) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::Optional"); + RecordProperty("Description", "default-constructed Optional is empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional o; + EXPECT_FALSE(o.has_value()); + EXPECT_FALSE(static_cast(o)); + EXPECT_EQ(o.value_or(42), 42); +} + +// --------------------------------------------------------------------------- +// OptionalNulloptTest +// --------------------------------------------------------------------------- + +TEST(OptionalNulloptTest, FromNullopt) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::Optional(nullopt_t)"); + RecordProperty("Description", "Optional constructed from nullopt is empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional o(nullopt); + EXPECT_FALSE(o.has_value()); +} + +// --------------------------------------------------------------------------- +// OptionalWithValueTest +// --------------------------------------------------------------------------- + +TEST(OptionalWithValueTest, ContainsValue) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::has_value, ::flatbuffers::Optional::operator*, ::flatbuffers::Optional::value_or"); + RecordProperty("Description", "Optional with value: checks value_or returns stored value"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + Optional o(0); + EXPECT_TRUE(o.has_value()); + EXPECT_EQ(*o, 0); + EXPECT_EQ(o.value_or(99), 0); + } + { + Optional o(42); + EXPECT_TRUE(o.has_value()); + EXPECT_EQ(*o, 42); + } + { + Optional o(-1); + EXPECT_TRUE(o.has_value()); + EXPECT_EQ(*o, -1); + } + { + Optional o(std::numeric_limits::max()); + EXPECT_TRUE(o.has_value()); + EXPECT_EQ(*o, std::numeric_limits::max()); + } +} + +// --------------------------------------------------------------------------- +// OptionalCopyTest +// --------------------------------------------------------------------------- + +TEST(OptionalCopyTest, Construction) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::Optional(const Optional&)"); + RecordProperty("Description", "copy construction copies value state"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional a(7); + Optional b(a); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(*b, 7); + + Optional c; + Optional d(c); + EXPECT_FALSE(d.has_value()); +} + +// --------------------------------------------------------------------------- +// OptionalAssignmentTest +// --------------------------------------------------------------------------- + +TEST(OptionalAssignmentTest, Operations) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::operator="); + RecordProperty("Description", "assignment from value and from nullopt"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional o; + o = 10; + EXPECT_TRUE(o.has_value()); + EXPECT_EQ(*o, 10); + + o = nullopt; + EXPECT_FALSE(o.has_value()); +} + +// --------------------------------------------------------------------------- +// OptionalResetTest +// --------------------------------------------------------------------------- + +TEST(OptionalResetTest, ClearValue) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::reset"); + RecordProperty("Description", "reset clears the stored value"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional o(5); + EXPECT_TRUE(o.has_value()); + o.reset(); + EXPECT_FALSE(o.has_value()); + o.reset(); + EXPECT_FALSE(o.has_value()); +} + +// --------------------------------------------------------------------------- +// OptionalSwapTest +// --------------------------------------------------------------------------- + +TEST(OptionalSwapTest, ExchangeValues) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::swap"); + RecordProperty("Description", "swap exchanges values between Optionals"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional a(1); + Optional b; + a.swap(b); + EXPECT_FALSE(a.has_value()); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(*b, 1); +} + +// --------------------------------------------------------------------------- +// OptionalNulloptComparisonTest +// --------------------------------------------------------------------------- + +TEST(OptionalNulloptComparisonTest, Equality) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Optional::operator==, ::flatbuffers::Optional::operator!="); + RecordProperty("Description", "comparison with nullopt"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Optional empty; + Optional full(3); + EXPECT_TRUE(empty == nullopt); + EXPECT_TRUE(nullopt == empty); + EXPECT_FALSE(full == nullopt); + EXPECT_TRUE(full != nullopt); +} + +// --------------------------------------------------------------------------- +// SpanFromArrayTest +// --------------------------------------------------------------------------- + +TEST(SpanFromArrayTest, FromCArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_span"); + RecordProperty("Description", "make_span creates span from C-array"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int arr[] = {10, 20, 30}; + auto s = make_span(arr); + EXPECT_EQ(s.size(), 3u); + EXPECT_EQ(s[0], 10); + EXPECT_EQ(s[1], 20); + EXPECT_EQ(s[2], 30); + EXPECT_FALSE(s.empty()); +} + +// --------------------------------------------------------------------------- +// SpanFromPointerTest +// --------------------------------------------------------------------------- + +TEST(SpanFromPointerTest, RawPtrAndCount) +{ + RecordProperty("FullyVerifies", "::flatbuffers::span::span(pointer, size_type)"); + RecordProperty("Description", "span from raw pointer + count"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + std::vector v = {1, 2, 3, 4, 5}; + span s(v.data(), v.size()); + EXPECT_EQ(s.size(), 5u); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[4], 5); +} + +// --------------------------------------------------------------------------- +// SpanEmptyTest +// --------------------------------------------------------------------------- + +TEST(SpanEmptyTest, DefaultConstructed) +{ + RecordProperty("FullyVerifies", "::flatbuffers::span::span()"); + RecordProperty("Description", "empty span via default constructor"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + span s; + EXPECT_EQ(s.size(), 0u); + EXPECT_TRUE(s.empty()); +} + +// --------------------------------------------------------------------------- +// SpanPtrCountTest +// --------------------------------------------------------------------------- + +TEST(SpanPtrCountTest, PartialArray) +{ + RecordProperty("FullyVerifies", "::flatbuffers::span::span(pointer, size_type)"); + RecordProperty("Description", "span from pointer + smaller count"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + int arr[] = {7, 8, 9}; + span s(&arr[0], 2); + EXPECT_EQ(s.size(), 2u); + EXPECT_EQ(s[0], 7); + EXPECT_EQ(s[1], 8); +} + +// --------------------------------------------------------------------------- +// TypeTraitsTest +// --------------------------------------------------------------------------- + +TEST(TypeTraitsTest, CompileTimeTraits) +{ + RecordProperty("FullyVerifies", "::flatbuffers::is_scalar, is_same, is_floating_point, is_unsigned"); + RecordProperty("Description", "type traits aliases work correctly"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_TRUE((is_scalar::value)); + EXPECT_FALSE((is_scalar::value)); + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_TRUE((is_floating_point::value)); + EXPECT_FALSE((is_floating_point::value)); + EXPECT_TRUE((is_unsigned::value)); + EXPECT_FALSE((is_unsigned::value)); +} + +// --------------------------------------------------------------------------- +// NumericLimitsTest +// --------------------------------------------------------------------------- + +TEST(NumericLimitsTest, ValueRanges) +{ + RecordProperty("FullyVerifies", "::flatbuffers::numeric_limits"); + RecordProperty("Description", "numeric_limits alias provides correct min/max values"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(numeric_limits::max(), static_cast(255)); + EXPECT_EQ(numeric_limits::min(), static_cast(-128)); + EXPECT_EQ(numeric_limits::max(), std::numeric_limits::max()); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_string_test.cpp b/score/flatbuffers/details/flatbuffers_string_test.cpp new file mode 100644 index 0000000000..821510ff80 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_string_test.cpp @@ -0,0 +1,225 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/string.h" + +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Helper: build buffer with a single string field. +static std::vector BuildStringTable(const char* str) +{ + FlatBufferBuilder fbb(256); + auto s = fbb.CreateString(str); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + auto* ptr = fbb.GetBufferPointer(); + return std::vector(ptr, ptr + fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// StringCStrTest +// --------------------------------------------------------------------------- + +TEST(StringCStrTest, Content) +{ + RecordProperty("FullyVerifies", "::flatbuffers::String::c_str, ::flatbuffers::String::size"); + RecordProperty("Description", "c_str() and size() return correct content for non-empty, empty, and single-char strings"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + auto buf = BuildStringTable("hello"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_STREQ(s->c_str(), "hello"); + EXPECT_EQ(s->size(), 5u); + } + { + auto buf = BuildStringTable(""); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_STREQ(s->c_str(), ""); + EXPECT_EQ(s->size(), 0u); + } + { + auto buf = BuildStringTable("X"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_STREQ(s->c_str(), "X"); + EXPECT_EQ(s->size(), 1u); + } +} + +// --------------------------------------------------------------------------- +// StringStrTest +// --------------------------------------------------------------------------- + +TEST(StringStrTest, StdString) +{ + RecordProperty("FullyVerifies", "::flatbuffers::String::str"); + RecordProperty("Description", "str() returns std::string with correct content"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildStringTable("world"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + std::string cpp_str = s->str(); + EXPECT_STREQ(cpp_str.c_str(), "world"); + EXPECT_EQ(cpp_str.size(), 5u); +} + +// --------------------------------------------------------------------------- +// StringViewTest +// --------------------------------------------------------------------------- + +TEST(StringViewTest, View) +{ + RecordProperty("FullyVerifies", "::flatbuffers::String::string_view"); + RecordProperty("Description", "string_view returns correct view into string content"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildStringTable("viewme"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + auto sv = s->string_view(); + EXPECT_EQ(sv.size(), 6u); + EXPECT_EQ(sv[0], 'v'); + EXPECT_EQ(sv[5], 'e'); +} + +// --------------------------------------------------------------------------- +// StringComparisonTest +// --------------------------------------------------------------------------- + +TEST(StringComparisonTest, Ordering) +{ + RecordProperty("FullyVerifies", "::flatbuffers::String::operator<"); + RecordProperty("Description", "operator< compares strings lexicographically"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto sa = fbb.CreateString("abc"); + auto sb = fbb.CreateString("abd"); + auto sc = fbb.CreateString("abc"); + auto sd = fbb.CreateString(""); + + auto start = fbb.StartTable(); + fbb.AddOffset(4, sa); + fbb.AddOffset(6, sb); + fbb.AddOffset(8, sc); + fbb.AddOffset(10, sd); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + + const String* s_abc = table->GetPointer(4); + const String* s_abd = table->GetPointer(6); + const String* s_abc2 = table->GetPointer(8); + const String* s_empty = table->GetPointer(10); + + ASSERT_NE(s_abc, nullptr); + ASSERT_NE(s_abd, nullptr); + ASSERT_NE(s_abc2, nullptr); + ASSERT_NE(s_empty, nullptr); + + EXPECT_TRUE(*s_abc < *s_abd); + EXPECT_FALSE(*s_abd < *s_abc); + EXPECT_FALSE(*s_abc < *s_abc2); + EXPECT_FALSE(*s_abc2 < *s_abc); + EXPECT_TRUE(*s_empty < *s_abc); +} + +// --------------------------------------------------------------------------- +// GetStringFunctionsTest +// --------------------------------------------------------------------------- + +TEST(GetStringFunctionsTest, NullSafe) +{ + RecordProperty("FullyVerifies", "::flatbuffers::GetCstring, ::flatbuffers::GetStringView"); + RecordProperty("Description", "GetCstring and GetStringView handle null pointer gracefully"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_STREQ(GetCstring(nullptr), ""); + + auto buf = BuildStringTable("hello"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + EXPECT_STREQ(GetCstring(s), "hello"); + + auto sv = GetStringView(s); + EXPECT_EQ(sv.size(), 5u); + + auto sv_null = GetStringView(nullptr); + EXPECT_EQ(sv_null.size(), 0u); +} + +// --------------------------------------------------------------------------- +// StringSpecialCharsTest +// --------------------------------------------------------------------------- + +TEST(StringSpecialCharsTest, SpecialAndLong) +{ + RecordProperty("FullyVerifies", "::flatbuffers::String::c_str, ::flatbuffers::String::size"); + RecordProperty("Description", "strings with special characters and long strings"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + { + auto buf = BuildStringTable("line1\nline2\ttab"); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_EQ(s->size(), 15u); + EXPECT_STREQ(s->c_str(), "line1\nline2\ttab"); + } + { + std::string long_str(1000, 'A'); + auto buf = BuildStringTable(long_str.c_str()); + auto* table = GetRoot
(buf.data()); + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_EQ(s->size(), 1000u); + } +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_struct_test.cpp b/score/flatbuffers/details/flatbuffers_struct_test.cpp new file mode 100644 index 0000000000..f176bac0f2 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_struct_test.cpp @@ -0,0 +1,196 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/struct.h" + +#include +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace flatbuffers +{ + +namespace test +{ + +} // namespace test +} // namespace flatbuffers + +// We define a simple packed struct outside the test namespace scope +// to avoid issues with #pragma pack inside class/namespace scope. +// Layout: { int32_t x (offset 0), int16_t y (offset 4), padding 2 bytes, int32_t z (offset 8) } +// Total size: 12, alignment: 4 + +#pragma pack(push, 1) +struct __attribute__((aligned(4))) TestVec3 FLATBUFFERS_FINAL_CLASS +{ + private: + int32_t x_; + int16_t y_; + int16_t pad0_; + int32_t z_; + + public: + TestVec3() : x_(0), y_(0), pad0_(0), z_(0) {} + TestVec3(int32_t x, int16_t y, int32_t z) + : x_(::flatbuffers::EndianScalar(x)), + y_(::flatbuffers::EndianScalar(y)), + pad0_(0), + z_(::flatbuffers::EndianScalar(z)) + {} + + int32_t x() const + { + return ::flatbuffers::EndianScalar(x_); + } + int16_t y() const + { + return ::flatbuffers::EndianScalar(y_); + } + int32_t z() const + { + return ::flatbuffers::EndianScalar(z_); + } +}; +#pragma pack(pop) +static_assert(sizeof(TestVec3) == 12, "compiler breaks packing rules"); + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// StructInTableTest +// --------------------------------------------------------------------------- + +TEST(StructInTableTest, Embedded) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetStruct"); + RecordProperty("Description", "a struct embedded inline in a table is retrievable"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + TestVec3 vec(100, -5, 999); + + auto start = fbb.StartTable(); + fbb.AddStruct(4, &vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + ASSERT_NE(table, nullptr); + + const TestVec3* s = table->GetStruct(4); + ASSERT_NE(s, nullptr); + EXPECT_EQ(s->x(), 100); + EXPECT_EQ(s->y(), static_cast(-5)); + EXPECT_EQ(s->z(), 999); +} + +// --------------------------------------------------------------------------- +// StructGetFieldTest +// --------------------------------------------------------------------------- + +TEST(StructGetFieldTest, ScalarFields) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Struct::GetField"); + RecordProperty("Description", "reading raw scalar fields from a Struct pointer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + TestVec3 vec(42, 7, -1); + + auto start = fbb.StartTable(); + fbb.AddStruct(4, &vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + const auto* s = reinterpret_cast(table->GetStruct(4)); + ASSERT_NE(s, nullptr); + + int32_t field_x = s->GetField(0); + EXPECT_EQ(field_x, 42); + int16_t field_y = s->GetField(4); + EXPECT_EQ(field_y, static_cast(7)); + int32_t field_z = s->GetField(8); + EXPECT_EQ(field_z, -1); +} + +// --------------------------------------------------------------------------- +// StructBoundaryTest +// --------------------------------------------------------------------------- + +TEST(StructBoundaryTest, MinMaxZero) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetStruct"); + RecordProperty("Description", "struct boundary values: int32_t max, int16_t min, 0"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + TestVec3 vec(std::numeric_limits::max(), std::numeric_limits::min(), 0); + + auto start = fbb.StartTable(); + fbb.AddStruct(4, &vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + const TestVec3* s = table->GetStruct(4); + ASSERT_NE(s, nullptr); + EXPECT_EQ(s->x(), std::numeric_limits::max()); + EXPECT_EQ(s->y(), std::numeric_limits::min()); + EXPECT_EQ(s->z(), 0); +} + +// --------------------------------------------------------------------------- +// StructAbsentFieldTest +// --------------------------------------------------------------------------- + +TEST(StructAbsentFieldTest, ReturnsNullptr) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetStruct"); + RecordProperty("Description", "absent struct field returns nullptr"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + const TestVec3* s = table->GetStruct(4); + EXPECT_EQ(s, nullptr); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_table_test.cpp b/score/flatbuffers/details/flatbuffers_table_test.cpp new file mode 100644 index 0000000000..3d193b54fd --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_table_test.cpp @@ -0,0 +1,276 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/table.h" + +#include +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Helper: build a table with scalar fields. +struct SimpleTableHelper +{ + static std::vector Build(int32_t f0, int16_t f1, uint8_t f2) + { + FlatBufferBuilder fbb(256); + auto start = fbb.StartTable(); + fbb.AddElement(4, f0, 0); + fbb.AddElement(6, f1, 0); + fbb.AddElement(8, f2, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + auto* ptr = fbb.GetBufferPointer(); + return std::vector(ptr, ptr + fbb.GetSize()); + } +}; + +// --------------------------------------------------------------------------- +// TableGetVTableTest +// --------------------------------------------------------------------------- + +TEST(TableGetVTableTest, Pointer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetVTable"); + RecordProperty("Description", "GetVTable returns a pointer within the buffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(42, 7, 1); + auto* table = GetRoot
(buf.data()); + ASSERT_NE(table, nullptr); + auto* vtable = table->GetVTable(); + EXPECT_NE(vtable, nullptr); + EXPECT_GE(vtable, buf.data()); + EXPECT_LT(vtable, buf.data() + buf.size()); +} + +// --------------------------------------------------------------------------- +// TableGetOptionalFieldOffsetTest +// --------------------------------------------------------------------------- + +TEST(TableGetOptionalFieldOffsetTest, PresentAbsent) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetOptionalFieldOffset"); + RecordProperty("Description", "present field returns non-zero offset, absent returns 0"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(42, 7, 1); + auto* table = GetRoot
(buf.data()); + + EXPECT_NE(table->GetOptionalFieldOffset(4), 0); + EXPECT_NE(table->GetOptionalFieldOffset(6), 0); + EXPECT_NE(table->GetOptionalFieldOffset(8), 0); + EXPECT_EQ(table->GetOptionalFieldOffset(10), static_cast(0)); + EXPECT_EQ(table->GetOptionalFieldOffset(1000), static_cast(0)); +} + +// --------------------------------------------------------------------------- +// TableGetFieldTest +// --------------------------------------------------------------------------- + +TEST(TableGetFieldTest, DefaultOrDefault) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetField"); + RecordProperty("Description", "GetField returns stored value or provided default"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + { + auto buf = SimpleTableHelper::Build(42, -3, 255); + auto* table = GetRoot
(buf.data()); + EXPECT_EQ(table->GetField(4, 0), 42); + EXPECT_EQ(table->GetField(6, 0), static_cast(-3)); + EXPECT_EQ(table->GetField(8, 0), 255); + } + { + auto buf = SimpleTableHelper::Build(42, 7, 1); + auto* table = GetRoot
(buf.data()); + EXPECT_EQ(table->GetField(10, 999), 999); + } +} + +TEST(TableGetFieldTest, ForceDefaults) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetField"); + RecordProperty("Description", "zero values with ForceDefaults are stored and retrievable"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + fbb.ForceDefaults(true); + auto start = fbb.StartTable(); + fbb.AddElement(4, 0, 0); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + EXPECT_EQ(table->GetField(4, 99), 0); +} + +// --------------------------------------------------------------------------- +// TableSetFieldTest +// --------------------------------------------------------------------------- + +TEST(TableSetFieldTest, ModifyInPlace) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::SetField"); + RecordProperty("Description", "SetField modifies the value in-place"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(10, 20, 30); + auto* table = GetMutableRoot
(buf.data()); + + bool ok = table->SetField(4, 100, 0); + EXPECT_TRUE(ok); + EXPECT_EQ(table->GetField(4, 0), 100); + + ok = table->SetField(10, 0, 0); + EXPECT_TRUE(ok); + ok = table->SetField(10, 42, 0); + EXPECT_FALSE(ok); +} + +// --------------------------------------------------------------------------- +// TableCheckFieldTest +// --------------------------------------------------------------------------- + +TEST(TableCheckFieldTest, PresentAbsent) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::CheckField"); + RecordProperty("Description", "CheckField returns true for present fields, false for absent"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(1, 2, 3); + auto* table = GetRoot
(buf.data()); + EXPECT_TRUE(table->CheckField(4)); + EXPECT_FALSE(table->CheckField(10)); +} + +// --------------------------------------------------------------------------- +// TableGetOptionalTest +// --------------------------------------------------------------------------- + +TEST(TableGetOptionalTest, PresentAbsent) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetOptional"); + RecordProperty("Description", "present field returns Optional with value, absent returns empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(42, 7, 1); + auto* table = GetRoot
(buf.data()); + + auto opt = table->GetOptional(4); + EXPECT_TRUE(opt.has_value()); + EXPECT_EQ(*opt, 42); + + auto opt2 = table->GetOptional(10); + EXPECT_FALSE(opt2.has_value()); +} + +// --------------------------------------------------------------------------- +// TableGetAddressOfTest +// --------------------------------------------------------------------------- + +TEST(TableGetAddressOfTest, PresentAbsent) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetAddressOf"); + RecordProperty("Description", "GetAddressOf returns non-null for present field, null for absent"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = SimpleTableHelper::Build(42, 7, 1); + auto* table = GetMutableRoot
(buf.data()); + + EXPECT_NE(table->GetAddressOf(4), nullptr); + EXPECT_EQ(table->GetAddressOf(10), nullptr); + + const Table* ctable = table; + EXPECT_NE(ctable->GetAddressOf(4), nullptr); + EXPECT_EQ(ctable->GetAddressOf(10), nullptr); +} + +// --------------------------------------------------------------------------- +// TableGetPointerTest +// --------------------------------------------------------------------------- + +TEST(TableGetPointerTest, OffsetField) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetPointer"); + RecordProperty("Description", "GetPointer for offset fields"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto str = fbb.CreateString("test_string"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, str); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + + const String* s = table->GetPointer(4); + ASSERT_NE(s, nullptr); + EXPECT_STREQ(s->c_str(), "test_string"); + + const String* s2 = table->GetPointer(6); + EXPECT_EQ(s2, nullptr); +} + +// --------------------------------------------------------------------------- +// TableGetVectorPointerOrEmptyTest +// --------------------------------------------------------------------------- + +TEST(TableGetVectorPointerOrEmptyTest, NoOptionalField) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Table::GetVectorPointerOrEmpty"); + RecordProperty("Description", "absent vector field returns empty vector (not nullptr)"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto start = fbb.StartTable(); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + + const Vector* v = table->GetVectorPointerOrEmpty(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 0u); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_vector_downward_test.cpp b/score/flatbuffers/details/flatbuffers_vector_downward_test.cpp new file mode 100644 index 0000000000..c7884461e7 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_vector_downward_test.cpp @@ -0,0 +1,397 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/vector_downward.h" + +#include +#include + +#include "flatbuffers/default_allocator.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// VectorDownwardDefaultConstructTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardDefaultConstructTest, Empty) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::vector_downward"); + RecordProperty("Description", "freshly constructed vector_downward is empty"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(256, nullptr, false, 1); + EXPECT_EQ(vd.size(), static_cast(0)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardPushTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardPushTest, Bytes) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::push"); + RecordProperty("Description", "pushing bytes increases size"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + vector_downward<> vd(64, nullptr, false, 1); + + uint8_t dummy = 0x42; + vd.push(&dummy, 0); + EXPECT_EQ(vd.size(), static_cast(0)); + + vd.push(&dummy, 1); + EXPECT_EQ(vd.size(), static_cast(1)); + EXPECT_EQ(vd.data()[0], 0x42); + + uint8_t data4[] = {0x01, 0x02, 0x03, 0x04}; + vd.push(data4, 4); + EXPECT_EQ(vd.size(), static_cast(5)); + EXPECT_EQ(vd.data()[0], 0x01); + EXPECT_EQ(vd.data()[4], 0x42); +} + +// --------------------------------------------------------------------------- +// VectorDownwardPushSmallTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardPushSmallTest, Scalar) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::push_small"); + RecordProperty("Description", "push_small for scalar types"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint32_t val = EndianScalar(static_cast(0xDEADBEEF)); + vd.push_small(val); + EXPECT_EQ(vd.size(), static_cast(4)); + EXPECT_EQ(ReadScalar(vd.data()), static_cast(0xDEADBEEF)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardFillTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardFillTest, Zeros) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::fill"); + RecordProperty("Description", "fill writes zero bytes"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + + vd.fill(0); + EXPECT_EQ(vd.size(), static_cast(0)); + + vd.fill(1); + EXPECT_EQ(vd.size(), static_cast(1)); + EXPECT_EQ(vd.data()[0], 0); + + vd.fill(4); + EXPECT_EQ(vd.size(), static_cast(5)); + for (int i = 0; i < 4; ++i) + { + EXPECT_EQ(vd.data()[i], 0); + } +} + +// --------------------------------------------------------------------------- +// VectorDownwardPopTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardPopTest, RemoveBytes) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::pop"); + RecordProperty("Description", "pop removes bytes from the front"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {1, 2, 3, 4}; + vd.push(data, 4); + EXPECT_EQ(vd.size(), static_cast(4)); + + vd.pop(2); + EXPECT_EQ(vd.size(), static_cast(2)); + + vd.pop(0); + EXPECT_EQ(vd.size(), static_cast(2)); + + vd.pop(2); + EXPECT_EQ(vd.size(), static_cast(0)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardClearTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardClearTest, PreservesCapacity) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::clear"); + RecordProperty("Description", "clear resets size but preserves capacity"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {1, 2, 3}; + vd.push(data, 3); + EXPECT_GT(vd.size(), static_cast(0)); + auto cap_before = vd.capacity(); + + vd.clear(); + EXPECT_EQ(vd.size(), static_cast(0)); + EXPECT_EQ(vd.capacity(), cap_before); +} + +// --------------------------------------------------------------------------- +// VectorDownwardResetTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardResetTest, Deallocates) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::reset"); + RecordProperty("Description", "reset clears buffer AND deallocates"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {1, 2, 3}; + vd.push(data, 3); + + vd.reset(); + EXPECT_EQ(vd.size(), static_cast(0)); + EXPECT_EQ(vd.capacity(), 0u); +} + +// --------------------------------------------------------------------------- +// VectorDownwardReleaseTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardReleaseTest, DetachedBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::release"); + RecordProperty("Description", "release returns a DetachedBuffer with the data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {0xAA, 0xBB}; + vd.push(data, 2); + + auto db = vd.release(); + EXPECT_EQ(db.size(), 2u); + EXPECT_EQ(db.data()[0], 0xAA); + EXPECT_EQ(db.data()[1], 0xBB); + EXPECT_EQ(vd.size(), static_cast(0)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardReleaseRawTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardReleaseRawTest, RawPointer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::release_raw, ::flatbuffers::Deallocate"); + RecordProperty("Description", "release_raw returns raw pointer and clears"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {1, 2, 3, 4, 5}; + vd.push(data, 5); + + size_t allocated, offset; + uint8_t* raw = vd.release_raw(allocated, offset); + EXPECT_NE(raw, nullptr); + EXPECT_GT(allocated, 0u); + EXPECT_EQ(vd.size(), static_cast(0)); + EXPECT_EQ(raw[offset + 0], 1); + EXPECT_EQ(raw[offset + 1], 2); + + Deallocate(nullptr, raw, allocated); +} + +// --------------------------------------------------------------------------- +// VectorDownwardMoveConstructTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardMoveConstructTest, TransfersOwnership) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::vector_downward(vector_downward&&)"); + RecordProperty("Description", "move constructor transfers ownership"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {10, 20}; + vd.push(data, 2); + + vector_downward<> moved(std::move(vd)); + EXPECT_EQ(moved.size(), static_cast(2)); + EXPECT_EQ(moved.data()[0], 10); + EXPECT_EQ(moved.data()[1], 20); +} + +// --------------------------------------------------------------------------- +// VectorDownwardMoveAssignTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardMoveAssignTest, TransfersOwnership) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::operator=(vector_downward&&)"); + RecordProperty("Description", "move assignment transfers ownership"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {10, 20}; + vd.push(data, 2); + + vector_downward<> other(64, nullptr, false, 1); + other = std::move(vd); + EXPECT_EQ(other.size(), static_cast(2)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardSwapTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardSwapTest, Exchanges) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::swap"); + RecordProperty("Description", "swap exchanges contents of two vectors"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> a(64, nullptr, false, 1); + vector_downward<> b(64, nullptr, false, 1); + + uint8_t da[] = {1, 2, 3}; + a.push(da, 3); + uint8_t db[] = {4, 5}; + b.push(db, 2); + + a.swap(b); + EXPECT_EQ(a.size(), static_cast(2)); + EXPECT_EQ(b.size(), static_cast(3)); + EXPECT_EQ(a.data()[0], 4); + EXPECT_EQ(b.data()[0], 1); +} + +// --------------------------------------------------------------------------- +// VectorDownwardScratchTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardScratchTest, PushPopSize) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::scratch_push_small, scratch_size, scratch_pop"); + RecordProperty("Description", "scratch memory push/pop/size work correctly"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + vector_downward<> vd(64, nullptr, false, 1); + uint8_t data[] = {0xFF}; + vd.push(data, 1); + + EXPECT_EQ(vd.scratch_size(), static_cast(0)); + + vd.scratch_push_small(static_cast(42)); + EXPECT_EQ(vd.scratch_size(), static_cast(4)); + + vd.scratch_pop(4); + EXPECT_EQ(vd.scratch_size(), static_cast(0)); +} + +// --------------------------------------------------------------------------- +// VectorDownwardGrowthTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardGrowthTest, Reallocates) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::push"); + RecordProperty("Description", "pushing more than initial_size forces reallocation"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + vector_downward<> vd(8, nullptr, false, 1); + uint8_t data[16]; + memset(data, 0xAB, sizeof(data)); + vd.push(data, sizeof(data)); + + EXPECT_EQ(vd.size(), static_cast(16)); + EXPECT_GE(vd.capacity(), 16u); + for (int i = 0; i < 16; ++i) + { + EXPECT_EQ(vd.data()[i], 0xAB); + } +} + +// --------------------------------------------------------------------------- +// VectorDownwardClearAllocatorOwnedTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardClearAllocatorOwnedTest, DeletesAllocator) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::clear_allocator"); + RecordProperty("Description", "when own_allocator_ is true, destruction path deletes allocator"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto* alloc = new DefaultAllocator(); + { + vector_downward<> vd(64, alloc, true, 1); + uint8_t data[] = {1, 2, 3}; + vd.push(data, 3); + // ~vector_downward() -> reset() -> clear_allocator() -> delete alloc + } +} + +// --------------------------------------------------------------------------- +// VectorDownwardReleaseOwnedAllocatorTest +// --------------------------------------------------------------------------- + +TEST(VectorDownwardReleaseOwnedAllocatorTest, TransfersOwnership) +{ + RecordProperty("FullyVerifies", "::flatbuffers::vector_downward::release"); + RecordProperty("Description", "release transfers owned allocator to returned DetachedBuffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto* alloc = new DefaultAllocator(); + vector_downward<> vd(64, alloc, true, 1); + uint8_t data[] = {0xAA, 0xBB}; + vd.push(data, 2); + + auto db = vd.release(); + EXPECT_EQ(db.size(), 2u); + EXPECT_EQ(db.data()[0], 0xAA); + EXPECT_EQ(db.data()[1], 0xBB); + // ~DetachedBuffer() will delete alloc via the owned-allocator path. +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_vector_test.cpp b/score/flatbuffers/details/flatbuffers_vector_test.cpp new file mode 100644 index 0000000000..7ebcd31815 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_vector_test.cpp @@ -0,0 +1,351 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/vector.h" + +#include +#include +#include +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// --------------------------------------------------------------------------- +// VectorGetTest +// --------------------------------------------------------------------------- + +TEST(VectorGetTest, Scalars) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::Get, operator[], size, empty"); + RecordProperty("Description", "Get, operator[] access elements; size/empty report correct state"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + std::vector data = {10, 20, 30, 40, 50}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + EXPECT_EQ(v->size(), 5u); + EXPECT_FALSE(v->empty()); + EXPECT_EQ(v->Get(0), 10); + EXPECT_EQ(v->Get(4), 50); + EXPECT_EQ(v->Get(2), 30); + EXPECT_EQ((*v)[0], 10); + EXPECT_EQ((*v)[4], 50); +} + +// --------------------------------------------------------------------------- +// VectorEmptyTest +// --------------------------------------------------------------------------- + +TEST(VectorEmptyTest, ZeroElements) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::size, empty"); + RecordProperty("Description", "empty vector has size 0 and empty() is true"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + std::vector data; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 0u); + EXPECT_TRUE(v->empty()); +} + +// --------------------------------------------------------------------------- +// VectorLengthTest +// --------------------------------------------------------------------------- + +TEST(VectorLengthTest, NullAndNotNull) +{ + RecordProperty("FullyVerifies", "::flatbuffers::VectorLength"); + RecordProperty("Description", "null vector returns 0, non-null returns actual size"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + EXPECT_EQ(VectorLength(nullptr), 0u); + + FlatBufferBuilder fbb(256); + std::vector data = {1, 2, 3}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + EXPECT_EQ(VectorLength(v), 3u); +} + +// --------------------------------------------------------------------------- +// VectorMutateTest +// --------------------------------------------------------------------------- + +TEST(VectorMutateTest, InPlace) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::Mutate"); + RecordProperty("Description", "in-place mutation of vector elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + std::vector data = {100, 200, 300}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetMutableRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + v->Mutate(0, 999); + EXPECT_EQ(v->Get(0), 999); + v->Mutate(2, 0); + EXPECT_EQ(v->Get(2), 0); + v->Mutate(1, std::numeric_limits::max()); + EXPECT_EQ(v->Get(1), std::numeric_limits::max()); +} + +// --------------------------------------------------------------------------- +// VectorForwardIteratorTest +// --------------------------------------------------------------------------- + +TEST(VectorForwardIteratorTest, RangeBased) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::begin, ::flatbuffers::Vector::end"); + RecordProperty("Description", "forward iteration collects elements in order"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + std::vector data = {5, 10, 15, 20}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + std::vector collected; + for (auto it = v->begin(); it != v->end(); ++it) + { + collected.push_back(*it); + } + ASSERT_EQ(collected.size(), 4u); + EXPECT_EQ(collected[0], 5); + EXPECT_EQ(collected[3], 20); +} + +// --------------------------------------------------------------------------- +// VectorReverseIteratorTest +// --------------------------------------------------------------------------- + +TEST(VectorReverseIteratorTest, RangeBased) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::rbegin, ::flatbuffers::Vector::rend"); + RecordProperty("Description", "reverse iteration collects elements in reverse order"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + std::vector data = {1, 2, 3}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + std::vector rev; + for (auto it = v->rbegin(); it != v->rend(); ++it) + { + rev.push_back(*it); + } + ASSERT_EQ(rev.size(), 3u); + EXPECT_EQ(rev[0], 3); + EXPECT_EQ(rev[2], 1); +} + +// --------------------------------------------------------------------------- +// VectorIteratorArithmeticTest +// --------------------------------------------------------------------------- + +TEST(VectorIteratorArithmeticTest, Operators) +{ + RecordProperty("FullyVerifies", "VectorIterator arithmetic"); + RecordProperty("Description", "iterator arithmetic for subtraction, addition, comparison"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + std::vector data = {10, 20, 30, 40}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + auto b = v->begin(); + auto e = v->end(); + + EXPECT_EQ(e - b, 4); + auto it = b + 2; + EXPECT_EQ(*it, 30); + EXPECT_LT(b, e); + EXPECT_LE(b, b); + EXPECT_GE(e, b); + EXPECT_FALSE(b > e); +} + +// --------------------------------------------------------------------------- +// VectorMakeSpanTest +// --------------------------------------------------------------------------- + +TEST(VectorMakeSpanTest, SpanOverData) +{ + RecordProperty("FullyVerifies", "::flatbuffers::make_span(const Vector&)"); + RecordProperty("Description", "make_span creates a span over vector data"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + std::vector data = {0xAA, 0xBB, 0xCC}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + + auto s = make_span(*v); + EXPECT_EQ(s.size(), 3u); + EXPECT_EQ(s[0], 0xAA); + EXPECT_EQ(s[2], 0xCC); +} + +// --------------------------------------------------------------------------- +// VectorOfStringsTest +// --------------------------------------------------------------------------- + +TEST(VectorOfStringsTest, Offsets) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector>::Get"); + RecordProperty("Description", "vector of Offset elements"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb(256); + auto s1 = fbb.CreateString("alpha"); + auto s2 = fbb.CreateString("beta"); + auto s3 = fbb.CreateString("gamma"); + std::vector> str_offsets = {s1, s2, s3}; + auto vec = fbb.CreateVector(str_offsets); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer>*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 3u); + EXPECT_STREQ(v->Get(0)->c_str(), "alpha"); + EXPECT_STREQ(v->Get(2)->c_str(), "gamma"); +} + +// --------------------------------------------------------------------------- +// VectorSingleElementTest +// --------------------------------------------------------------------------- + +TEST(VectorSingleElementTest, OneElement) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Vector::size, Get"); + RecordProperty("Description", "vector with exactly 1 element"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + FlatBufferBuilder fbb(256); + std::vector data = {42}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* buf = fbb.GetBufferPointer(); + auto* table = GetRoot
(buf); + auto* v = table->GetPointer*>(4); + ASSERT_NE(v, nullptr); + EXPECT_EQ(v->size(), 1u); + EXPECT_EQ(v->Get(0), 42); + EXPECT_FALSE(v->empty()); + EXPECT_EQ(v->end() - v->begin(), 1); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file diff --git a/score/flatbuffers/details/flatbuffers_verifier_test.cpp b/score/flatbuffers/details/flatbuffers_verifier_test.cpp new file mode 100644 index 0000000000..cbc66787d4 --- /dev/null +++ b/score/flatbuffers/details/flatbuffers_verifier_test.cpp @@ -0,0 +1,351 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "flatbuffers/verifier.h" + +#include +#include +#include + +#include "flatbuffers/flatbuffer_builder.h" +#include "gtest/gtest.h" + +namespace score +{ + +namespace flatbuffers +{ + +namespace test +{ + +using namespace ::flatbuffers; + +// Minimal table type that can be verified. +struct VerifiableTable : public Table +{ + bool Verify(Verifier& verifier) const + { + return VerifyTableStart(verifier) && verifier.EndTable(); + } + bool Verify(SizeVerifier& verifier) const + { + return VerifyTableStart(verifier) && verifier.EndTable(); + } +}; + +// Helper: build a minimal valid buffer with one int32 field. +static std::vector BuildSimpleBuffer(const char* identifier = nullptr) +{ + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + if (identifier) + { + fbb.Finish(Offset
(root), identifier); + } + else + { + fbb.Finish(Offset
(root)); + } + auto* p = fbb.GetBufferPointer(); + return std::vector(p, p + fbb.GetSize()); +} + +// --------------------------------------------------------------------------- +// VerifierOptionsDefaultTest +// --------------------------------------------------------------------------- + +TEST(VerifierOptionsDefaultTest, Values) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::Options"); + RecordProperty("Description", "default verifier options"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + Verifier::Options opts; + EXPECT_GT(opts.max_depth, 0u); + EXPECT_GT(opts.max_tables, 0u); + EXPECT_EQ(opts.assert, false); +} + +// --------------------------------------------------------------------------- +// VerifierCheckTest +// --------------------------------------------------------------------------- + +TEST(VerifierCheckTest, PassFail) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::Check"); + RecordProperty("Description", "Check returns the value passed"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.Check(true)); + EXPECT_FALSE(v.Check(false)); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyRangeTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyRangeTest, Boundary) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::Verify (range)"); + RecordProperty("Description", "range verification including boundary at buf.size() (strict less-than)"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + auto buf = BuildSimpleBuffer(); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.Verify(static_cast(0), static_cast(1))); + EXPECT_TRUE(v.Verify(static_cast(0), static_cast(buf.size() - 1))); + EXPECT_FALSE(v.Verify(static_cast(0), static_cast(buf.size()))); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyAlignmentTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyAlignmentTest, Checks) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyAlignment"); + RecordProperty("Description", "alignment checks return true for valid alignments"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.VerifyAlignment(0, 1)); + EXPECT_TRUE(v.VerifyAlignment(0, 4)); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyStringTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyStringTest, InBuffer) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyString"); + RecordProperty("Description", "string in buffer verifies successfully"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto s = fbb.CreateString("hello"); + auto start = fbb.StartTable(); + fbb.AddOffset(4, s); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* p = fbb.GetBufferPointer(); + Verifier v(p, fbb.GetSize()); + EXPECT_TRUE(v.VerifyBuffer(nullptr)); + + auto* table = GetRoot
(p); + auto* str = table->GetPointer(4); + ASSERT_NE(str, nullptr); + EXPECT_TRUE(v.VerifyString(str)); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyVectorTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyVectorTest, Scalars) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyVector"); + RecordProperty("Description", "vector of scalars in buffer verifies"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + std::vector data = {1, 2, 3}; + auto vec = fbb.CreateVector(data); + auto start = fbb.StartTable(); + fbb.AddOffset(4, vec); + auto root = fbb.EndTable(start); + fbb.Finish(Offset
(root)); + + auto* p = fbb.GetBufferPointer(); + Verifier v(p, fbb.GetSize()); + EXPECT_TRUE(v.VerifyBuffer(nullptr)); + + auto* table = GetRoot
(p); + auto* vp = table->GetPointer*>(4); + ASSERT_NE(vp, nullptr); + EXPECT_TRUE(v.VerifyVector(vp)); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyBufferValidTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyBufferValidTest, Passes) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyBuffer"); + RecordProperty("Description", "valid buffer passes VerifyBuffer"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.VerifyBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyBufferIdentifierTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyBufferIdentifierTest, MatchMismatch) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyBuffer"); + RecordProperty("Description", "identifier check: match passes, mismatch fails"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer("TEST"); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.VerifyBuffer("TEST")); + EXPECT_FALSE(v.VerifyBuffer("NOPE")); +} + +// --------------------------------------------------------------------------- +// VerifierVerifyBufferInvalidTest +// --------------------------------------------------------------------------- + +TEST(VerifierVerifyBufferInvalidTest, Truncated) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifyBuffer"); + RecordProperty("Description", "truncated buffer fails"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + std::vector buf = {0x00, 0x01, 0x02, 0x03}; + Verifier v(buf.data(), buf.size()); + EXPECT_FALSE(v.VerifyBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierDepthLimitTest +// --------------------------------------------------------------------------- + +TEST(VerifierDepthLimitTest, ZeroDepthFails) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::Options::max_depth"); + RecordProperty("Description", "depth limit of 0 causes verification to fail"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + auto buf = BuildSimpleBuffer(); + Verifier::Options opts; + opts.max_depth = 0; + Verifier v(buf.data(), buf.size(), opts); + EXPECT_FALSE(v.VerifyBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierSizePrefixedTest +// --------------------------------------------------------------------------- + +TEST(VerifierSizePrefixedTest, Works) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::VerifySizePrefixedBuffer"); + RecordProperty("Description", "size-prefixed buffer verifies"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + FlatBufferBuilder fbb; + auto start = fbb.StartTable(); + fbb.AddElement(4, 42, 0); + auto root = fbb.EndTable(start); + fbb.FinishSizePrefixed(Offset
(root)); + + auto* p = fbb.GetBufferPointer(); + Verifier v(p, fbb.GetSize()); + EXPECT_TRUE(v.VerifySizePrefixedBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierSizeVerifierTest +// --------------------------------------------------------------------------- + +TEST(VerifierSizeVerifierTest, Works) +{ + RecordProperty("FullyVerifies", "::flatbuffers::SizeVerifier::VerifyBuffer"); + RecordProperty("Description", "SizeVerifier works correctly"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + SizeVerifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.VerifyBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierDeprecatedConstructorTest +// --------------------------------------------------------------------------- + +TEST(VerifierDeprecatedConstructorTest, Works) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Verifier::Verifier(const uint8_t*, size_t)"); + RecordProperty("Description", "deprecated two-arg constructor still works"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + Verifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.VerifyBuffer(nullptr)); +} + +// --------------------------------------------------------------------------- +// VerifierSizeVerifierCheckFailTest +// --------------------------------------------------------------------------- + +TEST(VerifierSizeVerifierCheckFailTest, ResetUpperBound) +{ + RecordProperty("FullyVerifies", "::flatbuffers::SizeVerifier::Check"); + RecordProperty("Description", "Check(false) on SizeVerifier resets upper_bound_ to 0"); + RecordProperty("TestType", "unit-test"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + + auto buf = BuildSimpleBuffer(); + SizeVerifier v(buf.data(), buf.size()); + EXPECT_TRUE(v.Check(true)); + EXPECT_FALSE(v.Check(false)); +} + +// --------------------------------------------------------------------------- +// VerifierVectorLengthOverflowTest +// --------------------------------------------------------------------------- + +TEST(VerifierVectorLengthOverflowTest, OverflowProtection) +{ + RecordProperty("FullyVerifies", "::flatbuffers::SizeVerifier::VerifyVectorOrString"); + RecordProperty("Description", "vector with stored length >= max_elems triggers overflow guard"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + std::vector buf(5, 0xFF); + buf[4] = 0; + SizeVerifier::Options opts; + opts.max_size = 8; + SizeVerifier v(buf.data(), buf.size(), opts); + const auto* vec_ptr = reinterpret_cast*>(buf.data()); + EXPECT_FALSE(v.VerifyVector(vec_ptr)); +} + +} // namespace test +} // namespace flatbuffers +} // namespace score \ No newline at end of file From 1c275fdd37e76ce289b7fd72c1134df54c7dd93f Mon Sep 17 00:00:00 2001 From: Paul Quiring Date: Fri, 31 Jul 2026 13:44:54 +0200 Subject: [PATCH 2/2] Polished flatbuffers_array_test --- .../details/flatbuffers_array_test.cpp | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/score/flatbuffers/details/flatbuffers_array_test.cpp b/score/flatbuffers/details/flatbuffers_array_test.cpp index e003088507..46e3fcf152 100644 --- a/score/flatbuffers/details/flatbuffers_array_test.cpp +++ b/score/flatbuffers/details/flatbuffers_array_test.cpp @@ -49,6 +49,30 @@ struct Point } }; +// --------------------------------------------------------------------------- +// MISRA classification of the cast helpers (applies to the whole file) +// +// CastToArray / CastToArrayOfEnum from flatbuffers/array.h reinterpret_cast a +// raw T[length] into an Array. This deliberately violates: +// - MISRA C++:2023 Rule 8.2.5 / AUTOSAR C++14 A5-2-4 (use of +// reinterpret_cast). Rule 8.2.5 exempts casts whose target is a pointer to +// void, char, unsigned char or std::byte (possibly cv-qualified), or an +// integer type holding the pointer value, but this cast targets a pointer +// to an unrelated class type (Array*), so no exception applies. +// The third-party header marks these functions as risky itself ("Use with +// care.", TODO: move to `internal`) and guarantees no defined behaviour with +// respect to object lifetime / strict aliasing; it only works because +// Array is a pure layout wrapper with no data members of its own. +// +// Justification: +// +// Array isn't a real value type; it's a reinterpret-cast view onto bytes that +// already exist inside a FlatBuffer, lifespan concerns are out of scope. +// +// User facing is the flac generated header, which has measures +// for correct usage. +// --------------------------------------------------------------------------- + // --------------------------------------------------------------------------- // ArrayCastTest // Tests casting raw C arrays to flatbuffers::Array. @@ -218,6 +242,7 @@ TEST(ArrayMakeSpanTest, SpanFromArray) auto s = make_span(arr); EXPECT_EQ(s.size(), 3u); EXPECT_EQ(s[0], 100); + EXPECT_EQ(s[1], 200); EXPECT_EQ(s[2], 300); } @@ -379,6 +404,7 @@ TEST(ArrayMutableDataTest, MutableData) int32_t val = 42; std::memcpy(mutable_ptr, &val, sizeof(val)); EXPECT_EQ(arr.Get(0), 42); + EXPECT_EQ(arr.Get(1), 0); } TEST(ArrayMutableDataTest, MutableDataTyped) @@ -394,6 +420,8 @@ TEST(ArrayMutableDataTest, MutableDataTyped) EXPECT_EQ(typed_ptr, raw); typed_ptr[1] = 99; EXPECT_EQ(arr.Get(1), 99); + EXPECT_EQ(arr.Get(0), 1); + EXPECT_EQ(arr.Get(2), 3); } // --------------------------------------------------------------------------- @@ -535,6 +563,18 @@ TEST(ArrayConstSpanTest, ConstCastToArrayOfEnum) // --------------------------------------------------------------------------- // ArraySpanObservableTest // Tests is_span_observable. +// +// Only the true path is exercised. is_span_observable is false in two cases, +// neither of which is reachable in this build: +// 1. T is a pointer. Array is documented to carry only POD data +// (scalars or structs), and its public factories (CastToArray / +// CastToArrayOfEnum) cannot produce a pointer element type, so a pointer +// T cannot be instantiated here. +// 2. T is a multi-byte scalar on a big-endian platform. FlatBuffers stores +// scalars little-endian, so their raw bytes are only span-observable when +// FLATBUFFERS_LITTLEENDIAN holds (or sizeof(T) == 1). The test targets are +// little-endian, so this branch is never taken; forcing it would require a +// big-endian toolchain that is out of scope for these unit tests. // --------------------------------------------------------------------------- TEST(ArraySpanObservableTest, StaticAssertions) @@ -561,6 +601,10 @@ TEST(ArraySpanObservableTest, StaticAssertions) // Direct access helper for CopyFromSpanImpl true_type and false_type paths. // --------------------------------------------------------------------------- +// Exposes the protected CopyFromSpanImpl overloads so both paths can be tested +// regardless of platform endianness: +// observable -> memcpy path (raw bytes match native layout) +// non-observable -> element-wise Mutate path (with endian conversion) template struct ArrayTestAccess : public Array { @@ -582,7 +626,7 @@ TEST(CopyFromSpanImplTest, Observable) RecordProperty("DerivationTechnique", "equivalence-classes"); int32_t raw[3] = {0, 0, 0}; - auto& accessor = reinterpret_cast&>(raw); + auto& accessor = static_cast&>(CastToArray(raw)); const int32_t src[3] = {10, 20, 30}; span src_span(src, 3); @@ -601,7 +645,7 @@ TEST(CopyFromSpanImplTest, NonObservableScalar) RecordProperty("DerivationTechnique", "equivalence-classes"); int32_t raw[3] = {0, 0, 0}; - auto& accessor = reinterpret_cast&>(raw); + auto& accessor = static_cast&>(CastToArray(raw)); const int32_t src[3] = {100, 200, 300}; span src_span(src, 3); @@ -620,7 +664,7 @@ TEST(CopyFromSpanImplTest, NonObservableStruct) RecordProperty("DerivationTechnique", "equivalence-classes"); Point raw[2] = {{0, 0}, {0, 0}}; - auto& accessor = reinterpret_cast&>(raw); + auto& accessor = static_cast&>(CastToArray(raw)); const Point src[2] = {{7, 8}, {9, 10}}; span src_span(src, 2); @@ -746,6 +790,19 @@ TEST(ArrayFaultInjectionTest, FaultMutateStructOutOfBounds) EXPECT_DEATH({arr.Mutate(2u, p); }, ""); } +TEST(ArrayFaultInjectionTest, FaultCopyFromSpanOverlap) +{ + RecordProperty("FullyVerifies", "::flatbuffers::Array::CopyFromSpan"); + RecordProperty("Description", "CopyFromSpan with a source span overlapping the array triggers assert(false)"); + RecordProperty("TestType", "fault-test"); + RecordProperty("DerivationTechnique", "boundary-value-analysis"); + + int32_t raw[3] = {1, 2, 3}; + auto& arr = CastToArray(raw); + span overlapping(raw, 3); // shares storage with arr -> p1 == p2 + EXPECT_DEATH({arr.CopyFromSpan(overlapping); }, ""); +} + } // namespace test } // namespace flatbuffers } // namespace score \ No newline at end of file