diff --git a/score/containers/docs/architecture/index.rst b/score/containers/docs/architecture/index.rst index 7b3bac3b17..ba32bcf35b 100644 --- a/score/containers/docs/architecture/index.rst +++ b/score/containers/docs/architecture/index.rst @@ -53,7 +53,7 @@ Static Architecture :safety: ASIL_B :status: valid :version: 1 - :fulfils: comp_req__containers__dynamic_array[version==1], comp_req__containers__intrusive_list[version==1], comp_req__containers__type_safety[version==1], comp_req__containers__non_relocatable_vector[version==1], comp_req__containers__deterministic_behavior[version==1] + :fulfils: comp_req__containers__dynamic_array[version==1], comp_req__containers__intrusive_list[version==1], comp_req__containers__non_relocatable_vector[version==1], comp_req__containers__deterministic_behavior[version==1] :belongs_to: comp__baselibs_containers[version==1] .. needarch:: diff --git a/score/containers/docs/index.rst b/score/containers/docs/index.rst index 19a8f56f82..e6aa7914f1 100644 --- a/score/containers/docs/index.rst +++ b/score/containers/docs/index.rst @@ -60,7 +60,6 @@ The Containers library should provide type-safe data structures and efficient me * :need:`comp_req__containers__dynamic_array` * :need:`comp_req__containers__intrusive_list` -* :need:`comp_req__containers__type_safety` * :need:`comp_req__containers__deterministic_behavior` The component should be extensible in the future to support additional data structures and algorithms as needed. diff --git a/score/containers/docs/requirements/index.rst b/score/containers/docs/requirements/index.rst index 015bd8d70d..828233039f 100644 --- a/score/containers/docs/requirements/index.rst +++ b/score/containers/docs/requirements/index.rst @@ -51,18 +51,6 @@ Functional Requirements The Containers library shall provide an intrusive doubly-linked list based on the C++ standardization proposal P0406R1. -.. comp_req:: Type Safety - :id: comp_req__containers__type_safety - :reqtype: Functional - :security: YES - :safety: ASIL_B - :derived_from: feat_req__baselibs__containers_library[version==2] - :status: valid - :version: 1 - :satisfied_by: comp__baselibs_containers[version==1] - - The Containers library shall enforce compile-time type safety for all container operations. - .. comp_req:: Non-Relocatable Vector :id: comp_req__containers__non_relocatable_vector :reqtype: Functional diff --git a/score/containers/dynamic_array_test.cpp b/score/containers/dynamic_array_test.cpp index 04177be313..6034135e59 100644 --- a/score/containers/dynamic_array_test.cpp +++ b/score/containers/dynamic_array_test.cpp @@ -59,6 +59,14 @@ TYPED_TEST_SUITE(DynamicArrayTestFixture, AllocatorTypes, ); TYPED_TEST(DynamicArrayTestFixture, CanConstructWithTrivialType) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty( + "Description", + "Check that constructing a DynamicArray of trivial-type elements yields the requested size with " + "value-initialized elements."); + DynamicArray unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; EXPECT_EQ(unit.size(), 10); @@ -71,12 +79,24 @@ TYPED_TEST(DynamicArrayTestFixture, CanConstructWithTrivialType) TYPED_TEST(DynamicArrayTestFixture, ConstructTrivialEmpty) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that constructing a DynamicArray with size zero yields size() == 0."); + DynamicArray unit{kEmptyArraySize, GetAllocator(this->memory_resource_)}; EXPECT_EQ(unit.size(), kEmptyArraySize); } TYPED_TEST(DynamicArrayTestFixture, ConstructNonTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that constructing a DynamicArray of non-trivial-type elements value-initializes each " + "element."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); DynamicArray unit{kNonEmptyArraySize, non_trivial_type_alloc}; @@ -91,6 +111,13 @@ TYPED_TEST(DynamicArrayTestFixture, ConstructNonTrivial) TYPED_TEST(DynamicArrayTestFixture, CopyConstructTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a DynamicArray of trivial elements duplicates size and element " + "values."); + DynamicArray source_unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; @@ -111,6 +138,11 @@ TYPED_TEST(DynamicArrayTestFixture, CopyConstructTrivial) TYPED_TEST(DynamicArrayTestFixture, CopyConstructNonTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that copy construction duplicates non-trivial element values."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); DynamicArray source_unit{kNonEmptyArraySize, non_trivial_type_alloc}; @@ -134,6 +166,13 @@ TYPED_TEST(DynamicArrayTestFixture, CopyConstructNonTrivial) TYPED_TEST(DynamicArrayTestFixture, ConstructNonTrivialWithDefaultValue) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that constructing with an explicit default value initializes every element to that " + "value."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); NonTrivialType default_value{99U, 2.0f}; @@ -150,6 +189,12 @@ TYPED_TEST(DynamicArrayTestFixture, ConstructNonTrivialWithDefaultValue) TYPED_TEST(DynamicArrayTestFixture, MoveConstructTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing transfers size and element values from the source."); + DynamicArray unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; @@ -170,6 +215,13 @@ TYPED_TEST(DynamicArrayTestFixture, MoveConstructTrivial) TYPED_TEST(DynamicArrayTestFixture, MoveConstructNonTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-construction transfers non-trivial element values without invoking element " + "destructors."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); // given a unit with non-trivial element type @@ -198,6 +250,13 @@ TYPED_TEST(DynamicArrayTestFixture, MoveConstructNonTrivial) TYPED_TEST(DynamicArrayTestFixture, MoveAssignTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assignment replaces size and element values with those of the moved-from " + "array."); + const std::size_t array_size1{10U}; const std::size_t array_size2{20U}; DynamicArray unit{array_size1, @@ -223,6 +282,13 @@ TYPED_TEST(DynamicArrayTestFixture, MoveAssignTrivial) TYPED_TEST(DynamicArrayTestFixture, MoveAssignNonTrivial) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assignment of non-trivial elements transfers values and destroys only the " + "previously held elements exactly once."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); const std::size_t array_size1{10U}; const std::size_t array_size2{20U}; @@ -257,6 +323,12 @@ TYPED_TEST(DynamicArrayTestFixture, MoveAssignNonTrivial) TYPED_TEST(DynamicArrayTestFixture, SelfMoveAssign) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "error-guessing"); + this->RecordProperty("Description", + "Check that self-move-assignment leaves the array's size and element values unchanged."); + // given a DynamicArray of trivial type DynamicArray unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; @@ -276,6 +348,11 @@ TYPED_TEST(DynamicArrayTestFixture, SelfMoveAssign) TYPED_TEST(DynamicArrayTestFixture, CanSetValueOfArrayElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that elements can be written via at() and read back correctly."); + DynamicArray unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; @@ -293,6 +370,12 @@ TYPED_TEST(DynamicArrayTestFixture, CanSetValueOfArrayElements) TYPED_TEST(DynamicArrayTestFixture, CanConstructWithNonMoveableOrCopyableElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that a DynamicArray can hold an element type that is neither movable nor copyable."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); DynamicArray unit{kNonEmptyArraySize, @@ -303,6 +386,13 @@ TYPED_TEST(DynamicArrayTestFixture, CanConstructWithNonMoveableOrCopyableElement TYPED_TEST(DynamicArrayTestFixture, DestructorOfNonTrivialTypesCalled) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that destroying a DynamicArray invokes the destructor of every non-trivial element " + "exactly once."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); { @@ -315,6 +405,14 @@ TYPED_TEST(DynamicArrayTestFixture, DestructorOfNonTrivialTypesCalled) TYPED_TEST(DynamicArrayTestFixture, CanConstructWithTriviallyConstructableDestructibleElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty( + "Description", + "Check construction with a trivially-constructible/destructible element type value-initializes " + "elements."); + auto trivially_constructible_destructible_alloc = this->template getTypeSpecificAllocator(); @@ -331,6 +429,13 @@ TYPED_TEST(DynamicArrayTestFixture, CanConstructWithTriviallyConstructableDestru TYPED_TEST(DynamicArrayTestFixture, ConstructingDynamicArrayWithTrivialTypeWithTooManyElementsTerminates) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that constructing a DynamicArray whose requested size overflows allocation capacity " + "throws or terminates instead of succeeding silently."); + constexpr std::size_t array_size_exceeding_limit{std::numeric_limits::max()}; const auto initialise_dynamic_array = [this] { @@ -356,6 +461,13 @@ TYPED_TEST(DynamicArrayTestFixture, ConstructingDynamicArrayWithTrivialTypeWithT TYPED_TEST(DynamicArrayTestFixture, AccessingConstRefArrayOutOfBoundsTerminates) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that accessing a const element one past the last valid index terminates via contract " + "violation."); + DynamicArray unit(kNonEmptyArraySize); const auto access_const_ref_out_of_bounds = [&unit]() { @@ -368,6 +480,11 @@ TYPED_TEST(DynamicArrayTestFixture, AccessingConstRefArrayOutOfBoundsTerminates) TYPED_TEST(DynamicArrayTestFixture, IteratingTrivialType) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that begin()/end() iteration visits every trivial element in order."); + DynamicArray unit{kNonEmptyArraySize, GetAllocator(this->memory_resource_)}; @@ -387,6 +504,14 @@ TYPED_TEST(DynamicArrayTestFixture, IteratingTrivialType) TYPED_TEST(DynamicArrayTestFixture, IteratingNonTrivialType) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty( + "Description", + "Check that begin()/end() iteration visits and allows mutation of every non-trivial element in " + "order."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); DynamicArray unit{kNonEmptyArraySize, non_trivial_type_alloc}; @@ -409,6 +534,12 @@ TYPED_TEST(DynamicArrayTestFixture, IteratingNonTrivialType) TYPED_TEST(DynamicArrayTestFixture, ConstIteratingNonTrivialType) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that const begin()/end() iteration exposes read-only access to non-trivial elements."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); const DynamicArray unit{kNonEmptyArraySize, @@ -423,6 +554,12 @@ TYPED_TEST(DynamicArrayTestFixture, ConstIteratingNonTrivialType) TYPED_TEST(DynamicArrayTestFixture, ConstIteratingNonTrivialTypeVariation) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that cbegin()/cend() iteration visits every non-trivial element exactly once."); + auto non_trivial_type_alloc = this->template getTypeSpecificAllocator(); DynamicArray unit{kNonEmptyArraySize, non_trivial_type_alloc}; @@ -439,6 +576,11 @@ TYPED_TEST(DynamicArrayTestFixture, ConstIteratingNonTrivialTypeVariation) TYPED_TEST(DynamicArrayTestFixture, BracketOperatorAllowsSettingDataAtIndex) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that operator[] allows writing element values at a given index."); + DynamicArray unit{kNonEmptyArraySize}; for (TrivialType i = 0; i < unit.size(); ++i) { @@ -453,6 +595,11 @@ TYPED_TEST(DynamicArrayTestFixture, BracketOperatorAllowsSettingDataAtIndex) TYPED_TEST(DynamicArrayTestFixture, BracketOperatorAllowsGettingDataAtIndex) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that operator[] allows reading back previously written element values."); + DynamicArray unit{kNonEmptyArraySize}; for (TrivialType i = 0; i < unit.size(); ++i) { @@ -467,6 +614,11 @@ TYPED_TEST(DynamicArrayTestFixture, BracketOperatorAllowsGettingDataAtIndex) TYPED_TEST(DynamicArrayTestFixture, ConstBracketOperatorAllowsGettingDataAtIndex) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that the const operator[] returns previously written element values."); + DynamicArray unit{kNonEmptyArraySize}; for (TrivialType i = 0; i < unit.size(); ++i) { @@ -484,18 +636,33 @@ TYPED_TEST(DynamicArrayTestFixture, ConstBracketOperatorAllowsGettingDataAtIndex TYPED_TEST(DynamicArrayTestFixture, DataShouldReturnPointerToFirstElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that data() returns a pointer to the first element."); + DynamicArray unit{kNonEmptyArraySize}; EXPECT_EQ(unit.data(), &unit.at(0)); } TYPED_TEST(DynamicArrayTestFixture, ConstDataShouldReturnPointerToFirstElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that the const data() returns a pointer to the first element."); + const DynamicArray unit{kNonEmptyArraySize}; EXPECT_EQ(unit.data(), &unit.at(0)); } TYPED_TEST(DynamicArrayTestFixture, BeginIsEqualToEndWhenArrayIsEmpty) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that begin() equals end() for an empty DynamicArray."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -508,6 +675,11 @@ TYPED_TEST(DynamicArrayTestFixture, BeginIsEqualToEndWhenArrayIsEmpty) TYPED_TEST(DynamicArrayTestFixture, CBeginIsEqualToCEndWhenArrayIsEmpty) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that cbegin() equals cend() for an empty DynamicArray."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -520,6 +692,11 @@ TYPED_TEST(DynamicArrayTestFixture, CBeginIsEqualToCEndWhenArrayIsEmpty) TYPED_TEST(DynamicArrayTestFixture, DataReturnsNullptrWhenArrayIsEmpty) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that data() returns nullptr for an empty DynamicArray."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -532,6 +709,11 @@ TYPED_TEST(DynamicArrayTestFixture, DataReturnsNullptrWhenArrayIsEmpty) TYPED_TEST(DynamicArrayTestFixture, SizeReturnsZeroWhenArrayIsEmpty) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that size() is 0 for a DynamicArray constructed with zero elements."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -544,6 +726,13 @@ TYPED_TEST(DynamicArrayTestFixture, SizeReturnsZeroWhenArrayIsEmpty) TYPED_TEST(DynamicArrayTestFixture, SizeReturnsZeroWhenArrayIsEmptyWithValue) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that size() is 0 for a zero-size DynamicArray constructed with an explicit initial " + "value."); + // Given an empty DynamicArray which takes an initial value constexpr std::size_t kNumberOfElements{0U}; constexpr TrivialType kInitialValue{1}; @@ -558,6 +747,13 @@ TYPED_TEST(DynamicArrayTestFixture, SizeReturnsZeroWhenArrayIsEmptyWithValue) TYPED_TEST(DynamicArrayTestFixture, AccessingElementWithAtWhenArrayIsEmptyTerminates) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that at() on an empty DynamicArray terminates via contract violation instead of " + "returning."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -568,6 +764,13 @@ TYPED_TEST(DynamicArrayTestFixture, AccessingElementWithAtWhenArrayIsEmptyTermin TYPED_TEST(DynamicArrayTestFixture, AccessingElementWithIndexOperatorWhenArrayIsEmptyTerminates) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that operator[] on an empty DynamicArray terminates via contract violation instead of " + "returning."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -578,6 +781,11 @@ TYPED_TEST(DynamicArrayTestFixture, AccessingElementWithIndexOperatorWhenArrayIs TYPED_TEST(DynamicArrayTestFixture, IteratingOverEmptyArrayIteratesZeroTimes) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", "Check that iterating an empty DynamicArray performs zero loop iterations."); + // Given an empty DynamicArray const DynamicArray unit{0U}; @@ -595,6 +803,14 @@ TYPED_TEST(DynamicArrayTestFixture, IteratingOverEmptyArrayIteratesZeroTimes) TEST(EmptyDynamicArrayOfNonTrivialElementTypeMemoryTest, TestNeverFailsButMemcheckDoesIfEmptyArrayIsNotCleanedUpCorrectly) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check under external memory-checking tooling that constructing and destroying an empty " + "DynamicArray of a non-trivial element type does not leak memory; this test has no gtest " + "assertion and relies on valgrind/ASan."); + std::size_t array_size{0}; DynamicArray da(array_size); EXPECT_TRUE(true); @@ -602,6 +818,15 @@ TEST(EmptyDynamicArrayOfNonTrivialElementTypeMemoryTest, TEST(EmptyDynamicArrayOfTrivialElementTypeMemoryTest, TestNeverFailsButMemcheckDoesIfEmptyArrayIsNotCleanedUpCorrectly) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty( + "Description", + "Check under external memory-checking tooling that constructing and destroying an empty " + "DynamicArray of a trivial element type does not leak memory; this test has no gtest assertion " + "and relies on valgrind/ASan."); + std::size_t array_size{0}; DynamicArray da(array_size); EXPECT_TRUE(true); @@ -611,6 +836,14 @@ TEST(EmptyDynamicArrayOfTrivialElementTypeMemoryTest, TestNeverFailsButMemcheckD // but leave dynamic_array_ as nullptr TEST(DynamicArrayCopyConstructorMemoryTest, CopyConstructorWithZeroSizeArrayDoesNotLeakMemory) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty( + "Description", + "Check that copy-constructing from a zero-size DynamicArray yields a valid empty array (nullptr " + "data, equal begin/end) instead of leaking memory."); + // Given an empty source array DynamicArray source_array{0U}; EXPECT_EQ(source_array.size(), 0U); @@ -629,6 +862,13 @@ TEST(DynamicArrayCopyConstructorMemoryTest, CopyConstructorWithZeroSizeArrayDoes // Test the same scenario with non-trivial types to ensure the fix works for both code paths TEST(DynamicArrayCopyConstructorMemoryTest, CopyConstructorWithNonTrivialZeroSizeArrayDoesNotLeakMemory) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__dynamic_array"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that copy-constructing from a zero-size DynamicArray of a non-trivial element type " + "yields a valid empty array instead of leaking memory."); + // Given an empty source array of non-trivial type DynamicArray source_array{0U}; EXPECT_EQ(source_array.size(), 0U); diff --git a/score/containers/intrusive_list_test.cpp b/score/containers/intrusive_list_test.cpp index 9244d57562..e778d84509 100644 --- a/score/containers/intrusive_list_test.cpp +++ b/score/containers/intrusive_list_test.cpp @@ -108,6 +108,13 @@ void CheckNonEmpty(ListType& list, TEST(IntrusiveList, NotLinkedListElement) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check that constructing, copying, and moving a list element that is not linked into any list " + "does not trigger any assertion."); + ListElement element; ListElement copied_element{element}; ListElement moved_element{std::move(element)}; @@ -116,6 +123,13 @@ TEST(IntrusiveList, NotLinkedListElement) TEST(IntrusiveList, EmptyIterator) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check that default-constructed (unlinked) iterators of all four iterator kinds compare equal " + "to themselves and to each other across const/non-const variants."); + const List::iterator iterator; const List::const_iterator const_iterator; EXPECT_TRUE(iterator == iterator); @@ -137,6 +151,13 @@ TEST(IntrusiveList, EmptyIterator) TEST(IntrusiveList, EmptyList) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check that a default-constructed intrusive_list, and a list moved-from an empty list, are " + "empty and their const view reports the same."); + List list; const List& const_list = list; @@ -151,6 +172,13 @@ TEST(IntrusiveList, EmptyList) TEST(IntrusiveList, SingleElementMinimalChecks) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check that a list constructed from a single-range element is non-empty and becomes empty " + "after clear()."); + std::array elements; List list{elements.begin(), elements.end()}; EXPECT_FALSE(list.empty()); @@ -173,6 +201,15 @@ static_assert(refers_to_const_v elements{kMagic}; List list{elements.begin(), elements.end()}; @@ -360,6 +397,14 @@ TEST(IntrusiveList, SingleElementBasedIteratorChecks) TEST(IntrusiveList, SingleElementInsertRemoveChecks) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check that push_back/pop_back, push_front/pop_front, move construction, insert/remove, and " + "insert/remove_if on a single element correctly transition the list between empty and " + "non-empty."); + List list; const List& const_list = list; ListElement front_back; @@ -407,6 +452,12 @@ TEST(IntrusiveList, SingleElementInsertRemoveChecks) TEST(IntrusiveList, TwoElementsInsertRemoveChecks) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check push/pop/insert/remove/move-construction ordering (front/back) for a two-element list."); + List list; const List& const_list = list; ListElement front; @@ -474,6 +525,13 @@ TEST(IntrusiveList, TwoElementsInsertRemoveChecks) TEST(IntrusiveList, SixElementsInsertRemoveChecks) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check range-construct, assign, insert-range (at begin/end/middle), move-construction, remove, " + "and remove_if for a six-element list preserve order and 'no auto-unlink' semantics."); + constexpr std::size_t num_elements = 6; std::array elements; List list{elements.begin(), elements.end()}; @@ -549,6 +607,13 @@ DISABLE_WARNING_SELF_MOVE // testing correctness of implementation TEST(IntrusiveList, MoveAssignmentTest) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "error-guessing"); + RecordProperty("Description", + "Check move-assignment, including self-move-assignment, correctly empties the source and " + "transfers elements for 0-, 1-, 2-, and 6-element lists."); + // NOLINTBEGIN(bugprone-use-after-move): testing correctness of implementation List list; @@ -594,6 +659,13 @@ DISABLE_WARNING_POP // "-Wself-move" TEST(IntrusiveList, EraseTest) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "boundary-values"); + RecordProperty("Description", + "Check erase() of a single iterator, a range, an empty range, and a full-range erase update " + "size, the returned iterator, and the remaining elements correctly."); + constexpr std::size_t num_elements = 6; std::array elements; List list{elements.begin(), elements.end()}; @@ -622,6 +694,13 @@ TEST(IntrusiveList, EraseTest) TEST(IntrusiveList, SwapTest) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check member swap() and free-function swap(), including self-swap, correctly exchange " + "contents between empty and non-empty lists of varying sizes."); + List list1; list1.swap(list1); @@ -675,6 +754,14 @@ TEST(IntrusiveList, SwapTest) TEST(IntrusiveList, DisposeTest) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check pop_back_and_dispose/pop_front_and_dispose/erase_and_dispose/dispose_and_assign/" + "remove_and_dispose/remove_and_dispose_if/clear_and_dispose invoke the disposer exactly once " + "per removed element in the expected order."); + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): "Magic numbers" here are the test labels by themselves constexpr std::size_t num_elements = 6; @@ -734,6 +821,14 @@ class multi_element : public score::containers::intrusive_list_element<>, TEST(IntrusiveList, MultiTagTest) { + RecordProperty("PartiallyVerifies", "comp_req__containers__intrusive_list"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check that the same element type can simultaneously belong to independent intrusive_list " + "instances distinguished by tag, and that operations on one tagged list do not affect " + "membership in another."); + constexpr std::size_t num_elements = 6; std::array elements; score::containers::intrusive_list no_tag_list{elements.begin(), elements.end()}; diff --git a/score/containers/non_relocatable_vector_emplace_back_test.cpp b/score/containers/non_relocatable_vector_emplace_back_test.cpp index bca92fcc5d..39063d4a5b 100644 --- a/score/containers/non_relocatable_vector_emplace_back_test.cpp +++ b/score/containers/non_relocatable_vector_emplace_back_test.cpp @@ -86,6 +86,11 @@ TYPED_TEST_SUITE(NonRelocatableVectorPolymorphicAllocatorFixture, PolymorphicAll TYPED_TEST(NonRelocatableVectorFixture, EmplaceBackUpdatesSize) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", "Check that each call to emplace_back() increments size() by one."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -100,6 +105,13 @@ TYPED_TEST(NonRelocatableVectorFixture, EmplaceBackUpdatesSize) TYPED_TEST(NonRelocatableVectorTrivialFixture, EmplaceBackAllocatesAndReturnsElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that emplace_back() on trivial elements constructs the element in place at the " + "correct index and returns a reference to it."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -118,6 +130,13 @@ TYPED_TEST(NonRelocatableVectorTrivialFixture, EmplaceBackAllocatesAndReturnsEle TYPED_TEST(NonRelocatableVectorNonTrivialFixture, EmplaceBackAllocatesAndReturnsElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that emplace_back() on non-trivial elements constructs the element in place at " + "the correct index and returns a reference to it."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -137,6 +156,13 @@ TYPED_TEST(NonRelocatableVectorNonTrivialFixture, EmplaceBackAllocatesAndReturns TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, EmplaceBackAllocatesAndReturnsElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that emplace_back() on trivially-constructible/destructible elements constructs " + "the element in place at the correct index and returns a reference to it."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -156,6 +182,13 @@ TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, Em TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, EmplaceBackAllocatesAndReturnsElement) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that emplace_back() on non-moveable, non-copyable elements constructs the " + "element in place at the correct index and returns a reference to it."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -174,6 +207,13 @@ TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, Emplace TYPED_TEST(NonRelocatableVectorFixture, CallingEmplaceBackMoreTimesThanWereReservedTerminates) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "fault-injection"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that calling emplace_back() more times than the vector's reserved capacity " + "terminates via contract violation instead of silently overflowing."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); // and given that emplace_back was called size() - 1 times @@ -189,6 +229,13 @@ TYPED_TEST(NonRelocatableVectorFixture, CallingEmplaceBackMoreTimesThanWereReser TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, EmplaceBackDoesNotAllocate) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "requirements-analysis"); + this->RecordProperty("Description", + "Check that repeated emplace_back() calls up to the reserved capacity do not trigger " + "any additional memory allocation beyond what was allocated at construction."); + // Given a NonRelocatableVector which has allocated n bytes on construction this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); const auto allocated_bytes_after_construction = this->memory_resource_.GetUserAllocatedBytes(); diff --git a/score/containers/non_relocatable_vector_special_member_funcs_test.cpp b/score/containers/non_relocatable_vector_special_member_funcs_test.cpp index 56bde71e11..572563cfe9 100644 --- a/score/containers/non_relocatable_vector_special_member_funcs_test.cpp +++ b/score/containers/non_relocatable_vector_special_member_funcs_test.cpp @@ -95,6 +95,13 @@ using NonRelocatableVectorSpecialMemberFunctionRecorderFixture = TYPED_TEST(NonRelocatableVectorFixture, ConstructingWithZeroElementsSetsSizeAndCapacityToZero) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that constructing a NonRelocatableVector with zero elements yields size() == 0 " + "and capacity() == 0."); + // When constructing a NonRelocatableVector with zero elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(0U); @@ -105,6 +112,13 @@ TYPED_TEST(NonRelocatableVectorFixture, ConstructingWithZeroElementsSetsSizeAndC TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, ConstructingWithZeroElementsDoesNotAllocate) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that constructing a NonRelocatableVector with zero elements does not allocate " + "any memory."); + // When constructing a NonRelocatableVector with zero elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(0U); @@ -114,6 +128,13 @@ TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, ConstructingWithZero TYPED_TEST(NonRelocatableVectorFixture, ConstructingWithNonZeroElementsSetsCapacity) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that constructing a NonRelocatableVector with a non-zero element count sets " + "capacity() to that count while size() remains 0."); + // When constructing a NonRelocatableVector with kNonZeroNumberElements elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -124,6 +145,12 @@ TYPED_TEST(NonRelocatableVectorFixture, ConstructingWithNonZeroElementsSetsCapac TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, ConstructingWithNonZeroElementsAllocatesAllElements) { + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that constructing a NonRelocatableVector with a non-zero element count allocates " + "exactly capacity() * sizeof(element) bytes up front."); + // When constructing a NonRelocatableVector with kNonZeroNumberElements elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -137,6 +164,13 @@ TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, ConstructingWithNonZ TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, ConstructingWithNonZeroElementsDoesNotCallElementConstructors) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check that constructing a NonRelocatableVector reserves storage without invoking any " + "element constructors."); + // When constructing a NonRelocatableVector with kNonZeroNumberElements elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -146,6 +180,13 @@ TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, TYPED_TEST(NonRelocatableVectorFixture, DestructingWithZeroElementsDoesNotDeallocate) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that destroying a zero-capacity NonRelocatableVector does not deallocate any " + "memory."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(0U); // When destructing the NonRelocatableVector with zero elements @@ -157,6 +198,13 @@ TYPED_TEST(NonRelocatableVectorFixture, DestructingWithZeroElementsDoesNotDeallo TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, DestructingWithNonZeroElementsDeallocatesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that destroying a NonRelocatableVector deallocates exactly the memory that was " + "allocated for its capacity."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); // When destructing the NonRelocatableVector with non-zero elements @@ -172,6 +220,13 @@ TYPED_TEST(NonRelocatableVectorPolymorphicAllocatorFixture, DestructingWithNonZe TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, DestructingWithNonZeroElementsDoesNotCallAnyDestructors) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check that destroying a NonRelocatableVector with reserved but un-emplaced capacity does " + "not invoke any element destructors."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); // When destructing the NonRelocatableVector with non-zero elements (although no emplaced elements) @@ -184,6 +239,13 @@ TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, DestructingWithNonZeroEmplacedElementsCallsDestructorAllElements) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "requirements-based"); + RecordProperty("DerivationTechnique", "equivalence-classes"); + RecordProperty("Description", + "Check that destroying a NonRelocatableVector invokes the destructor of every emplaced " + "element exactly once."); + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); // and given that kNonZeroNumberElements have been emplaced @@ -201,6 +263,13 @@ TEST_F(NonRelocatableVectorSpecialMemberFunctionRecorderFixture, TYPED_TEST(NonRelocatableVectorTrivialFixture, CopyConstructingCopiesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a NonRelocatableVector of trivial elements duplicates " + "every element's value."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -223,6 +292,13 @@ TYPED_TEST(NonRelocatableVectorTrivialFixture, CopyConstructingCopiesAllElements TYPED_TEST(NonRelocatableVectorNonTrivialFixture, CopyConstructingCopiesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a NonRelocatableVector of non-trivial elements " + "duplicates every element's value."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -247,6 +323,13 @@ TYPED_TEST(NonRelocatableVectorNonTrivialFixture, CopyConstructingCopiesAllEleme TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, CopyConstructingCopiesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a NonRelocatableVector of trivially-constructible/" + "destructible elements duplicates every element's value."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -286,6 +369,12 @@ TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, CannotC TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, CopyConstructingAllocatesBasedOnCapacity) { + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a NonRelocatableVector allocates memory based on the " + "source's capacity, not its current size."); + // Given a NonRelocatableVector which has been filled with less elements than its capacity this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); const auto memory_allocated_for_first_vector = this->memory_resource_.GetUserAllocatedBytes(); @@ -313,6 +402,12 @@ TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, C TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, CopyConstructingDoesNotDeallocateMemory) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that copy-constructing a NonRelocatableVector does not deallocate any memory."); + // Given a NonRelocatableVector which has been filled this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -328,6 +423,13 @@ TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, C TYPED_TEST(NonRelocatableVectorTrivialFixture, MoveConstructingMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing a NonRelocatableVector of trivial elements transfers " + "every element's value to the new vector."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -350,6 +452,13 @@ TYPED_TEST(NonRelocatableVectorTrivialFixture, MoveConstructingMovesAllElements) TYPED_TEST(NonRelocatableVectorNonTrivialFixture, MoveConstructingMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing a NonRelocatableVector of non-trivial elements transfers " + "every element's value to the new vector."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -374,6 +483,13 @@ TYPED_TEST(NonRelocatableVectorNonTrivialFixture, MoveConstructingMovesAllElemen TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, MoveConstructingMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing a NonRelocatableVector of trivially-constructible/" + "destructible elements transfers every element's value to the new vector."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -413,6 +529,13 @@ TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, MoveCon TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, MoveConstructingDoesNotAllocateNewMemory) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing a NonRelocatableVector does not allocate any additional " + "memory."); + // Given a NonRelocatableVector which has been filled with less elements than its capacity this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); const auto memory_allocated_for_first_vector = this->memory_resource_.GetUserAllocatedBytes(); @@ -437,6 +560,12 @@ TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, M TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, MoveConstructingDoesNotDeallocateMemory) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-constructing a NonRelocatableVector does not deallocate any memory."); + // Given a NonRelocatableVector which has been filled this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); @@ -452,6 +581,13 @@ TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, M TYPED_TEST(NonRelocatableVectorTrivialFixture, MoveAssigningMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assigning a NonRelocatableVector of trivial elements replaces the " + "target's elements with the source's."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -481,6 +617,13 @@ TYPED_TEST(NonRelocatableVectorTrivialFixture, MoveAssigningMovesAllElements) TYPED_TEST(NonRelocatableVectorNonTrivialFixture, MoveAssigningMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assigning a NonRelocatableVector of non-trivial elements replaces the " + "target's elements with the source's."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -512,6 +655,13 @@ TYPED_TEST(NonRelocatableVectorNonTrivialFixture, MoveAssigningMovesAllElements) TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, MoveAssigningMovesAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assigning a NonRelocatableVector of trivially-constructible/" + "destructible elements replaces the target's elements with the source's."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -560,6 +710,13 @@ TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, MoveAss TYPED_TEST(NonRelocatableVectorCopyableAndMoveablePolymorphicAllocatorFixture, MoveAssigningAllocatesBasedOnCapacity) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__deterministic_behavior"); + this->RecordProperty("TestType", "resource-usage"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that move-assigning a NonRelocatableVector whose target already has sufficient " + "capacity does not allocate additional memory."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); diff --git a/score/containers/non_relocatable_vector_test.cpp b/score/containers/non_relocatable_vector_test.cpp index 0f91232238..13912365c7 100644 --- a/score/containers/non_relocatable_vector_test.cpp +++ b/score/containers/non_relocatable_vector_test.cpp @@ -88,6 +88,13 @@ TYPED_TEST_SUITE(NonRelocatableVectorPolymorphicAllocatorFixture, PolymorphicAll TYPED_TEST(NonRelocatableVectorTrivialFixture, SwapSwapsAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that swapping two NonRelocatableVectors of trivial elements exchanges their " + "contents."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -122,6 +129,13 @@ TYPED_TEST(NonRelocatableVectorTrivialFixture, SwapSwapsAllElements) TYPED_TEST(NonRelocatableVectorNonTrivialFixture, SwapSwapsAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that swapping two NonRelocatableVectors of non-trivial elements exchanges their " + "contents."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -160,6 +174,13 @@ TYPED_TEST(NonRelocatableVectorNonTrivialFixture, SwapSwapsAllElements) TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, SwapSwapsAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that swapping two NonRelocatableVectors of trivially-constructible/destructible " + "elements exchanges their contents."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -203,6 +224,13 @@ TYPED_TEST(NonRelocatableVectorTriviallyConstructibleDestructibleTypeFixture, Sw TYPED_TEST(NonRelocatableVectorNonMoveableAndCopyableElementTypeFixture, SwapSwapsAllElements) { + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "equivalence-classes"); + this->RecordProperty("Description", + "Check that swapping two NonRelocatableVectors of non-moveable, non-copyable elements " + "exchanges their contents."); + // Given a NonRelocatableVector which has been filled with elements this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); for (std::size_t i = 0; i < kNonZeroNumberElements; ++i) @@ -295,6 +323,13 @@ using testing::_; TEST_F(NonRelocatableVectorPointerInteractionFixture, DataDereferencesBeginAndEnd) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "design-analysis"); + RecordProperty("Description", + "Check that data() internally dereferences the element pointer exactly for the first and " + "last elements, matching the internal pointer-arithmetic implementation."); + // Given a NonRelocatableVector which has been filled with elements GivenANonRelocatableVectorContainingNumberOfElements(kNonZeroNumberElements); @@ -313,6 +348,13 @@ TEST_F(NonRelocatableVectorPointerInteractionFixture, DataDereferencesBeginAndEn TEST_F(NonRelocatableVectorPointerInteractionFixture, BeginDereferencesBeginAndEnd) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "design-analysis"); + RecordProperty("Description", + "Check that begin() internally dereferences the element pointer exactly for the first and " + "last elements, matching the internal pointer-arithmetic implementation."); + // Given a NonRelocatableVector which has been filled with elements GivenANonRelocatableVectorContainingNumberOfElements(kNonZeroNumberElements); @@ -331,6 +373,13 @@ TEST_F(NonRelocatableVectorPointerInteractionFixture, BeginDereferencesBeginAndE TEST_F(NonRelocatableVectorPointerInteractionFixture, EndDereferencesBeginAndEnd) { + RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "design-analysis"); + RecordProperty("Description", + "Check that end() internally dereferences the element pointer exactly for the first and last " + "elements, matching the internal pointer-arithmetic implementation."); + // Given a NonRelocatableVector which has been filled with elements GivenANonRelocatableVectorContainingNumberOfElements(kNonZeroNumberElements); @@ -347,4 +396,25 @@ TEST_F(NonRelocatableVectorPointerInteractionFixture, EndDereferencesBeginAndEnd EXPECT_EQ(arrow_args[1], end_it - 1); } +TYPED_TEST(NonRelocatableVectorTrivialFixture, EmplaceBackPreservesExistingElementAddress) +{ + this->RecordProperty("PartiallyVerifies", "comp_req__containers__non_relocatable_vector"); + this->RecordProperty("TestType", "requirements-based"); + this->RecordProperty("DerivationTechnique", "boundary-values"); + this->RecordProperty("Description", + "Check that an existing element address remains stable after subsequent emplace_back() " + "operations."); + + this->GivenANonRelocatableVectorConstructedWithNumberOfElements(kNonZeroNumberElements); + auto& first_element = this->unit_->emplace_back(); + const auto* first_element_address = &first_element; + + for (std::size_t i = 1U; i < kNonZeroNumberElements; ++i) + { + score::cpp::ignore = this->unit_->emplace_back(); + } + + EXPECT_EQ(first_element_address, &this->unit_->at(0U)); +} + } // namespace score::containers