- Introduced tests for NCollection_Map, verifying constructors, addition, removal, and iteration functionalities.
- Added comprehensive tests for NCollection_Sequence, covering basic operations, iterator functionality, and complex type handling.
- Implemented tests for NCollection_SparseArray, including basic operations, iterator functionality, and data map interface.
- Created tests for NCollection_Vector, ensuring functionality for appending, resizing, and custom allocator usage.
run: |
cd install/bin
source env.sh
- ./OpenCascadeGTest --gtest_output=xml:gtest_results.xml > gtest_output.log 2>&1
+ ./OpenCascadeGTest --gtest_output=xml:gtest_results.xml > gtest_output.log 2>&1 || true
cat gtest_output.log
- name: Upload GTest results
set(OCCT_TKernel_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
set(OCCT_TKernel_GTests_FILES
+ NCollection_Array1_Test.cxx
+ NCollection_BaseAllocator_Test.cxx
+ NCollection_DataMap_Test.cxx
+ NCollection_DoubleMap_Test.cxx
+ NCollection_IndexedDataMap_Test.cxx
+ NCollection_IndexedMap_Test.cxx
+ NCollection_List_Test.cxx
+ NCollection_LocalArray_Test.cxx
+ NCollection_Map_Test.cxx
+ NCollection_Sequence_Test.cxx
+ NCollection_SparseArray_Test.cxx
+ NCollection_Vector_Test.cxx
TCollection_AsciiString_Test.cxx
TCollection_ExtendedString_Test.cxx
)
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_Array1.hxx>
+#include <Standard_Integer.hxx>
+
+#include <gtest/gtest.h>
+
+// Test fixture for NCollection_Array1 tests
+class NCollection_Array1Test : public testing::Test
+{
+protected:
+ void SetUp() override {}
+
+ void TearDown() override {}
+};
+
+TEST_F(NCollection_Array1Test, DefaultConstructor)
+{
+ // Default constructor should not compile as it's explicitly deleted
+ // NCollection_Array1<Standard_Integer> anArray;
+ // Instead we need to use the parameterized constructor
+ NCollection_Array1<Standard_Integer> anArray(1, 10);
+
+ EXPECT_EQ(10, anArray.Length());
+ EXPECT_EQ(1, anArray.Lower());
+ EXPECT_EQ(10, anArray.Upper());
+}
+
+TEST_F(NCollection_Array1Test, ConstructorWithBounds)
+{
+ // Test constructor with explicit bounds
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+ EXPECT_EQ(5, anArray.Size());
+ EXPECT_EQ(1, anArray.Lower());
+ EXPECT_EQ(5, anArray.Upper());
+}
+
+TEST_F(NCollection_Array1Test, ConstructorWithNegativeBounds)
+{
+ // Test constructor with negative bounds
+ NCollection_Array1<Standard_Integer> anArray(-3, 2);
+ EXPECT_EQ(6, anArray.Size());
+ EXPECT_EQ(-3, anArray.Lower());
+ EXPECT_EQ(2, anArray.Upper());
+}
+
+TEST_F(NCollection_Array1Test, AssignmentValue)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+
+ // Initialize array
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ anArray(i) = i * 10;
+ }
+
+ // Verify values
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ EXPECT_EQ(i * 10, anArray(i));
+ }
+
+ // Test Value vs operator()
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ EXPECT_EQ(anArray.Value(i), anArray(i));
+ }
+}
+
+TEST_F(NCollection_Array1Test, CopyConstructor)
+{
+ NCollection_Array1<Standard_Integer> anArray1(1, 5);
+
+ // Initialize array
+ for (Standard_Integer i = anArray1.Lower(); i <= anArray1.Upper(); i++)
+ {
+ anArray1(i) = i * 10;
+ }
+
+ // Copy construct
+ NCollection_Array1<Standard_Integer> anArray2(anArray1);
+
+ // Verify copy
+ EXPECT_EQ(anArray1.Length(), anArray2.Length());
+ EXPECT_EQ(anArray1.Lower(), anArray2.Lower());
+ EXPECT_EQ(anArray1.Upper(), anArray2.Upper());
+
+ for (Standard_Integer i = anArray1.Lower(); i <= anArray1.Upper(); i++)
+ {
+ EXPECT_EQ(anArray1(i), anArray2(i));
+ }
+
+ // Modify original to ensure deep copy
+ anArray1(3) = 999;
+ EXPECT_NE(anArray1(3), anArray2(3));
+}
+
+TEST_F(NCollection_Array1Test, ValueAccess)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+
+ // Set values
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ anArray.SetValue(i, i * 10);
+ }
+
+ // Check values
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ EXPECT_EQ(i * 10, anArray.Value(i));
+ EXPECT_EQ(i * 10, anArray(i)); // Using operator()
+ }
+}
+
+TEST_F(NCollection_Array1Test, ChangeValueAccess)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+
+ // Set values using ChangeValue
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ anArray.ChangeValue(i) = i * 10;
+ }
+
+ // Check values
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ EXPECT_EQ(i * 10, anArray(i));
+ }
+
+ // Modify values through references
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ anArray.ChangeValue(i) += 5;
+ }
+
+ // Check modified values
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ EXPECT_EQ(i * 10 + 5, anArray(i));
+ }
+}
+
+TEST_F(NCollection_Array1Test, AssignmentOperator)
+{
+ NCollection_Array1<Standard_Integer> anArray1(1, 5);
+
+ // Initialize array
+ for (Standard_Integer i = anArray1.Lower(); i <= anArray1.Upper(); i++)
+ {
+ anArray1(i) = i * 10;
+ }
+
+ // Test assignment
+ NCollection_Array1<Standard_Integer> anArray2(11, 15);
+ anArray2 = anArray1;
+ anArray2.Resize(1, 5, Standard_True); // Resize to match anArray1
+
+ // Verify assignment result
+ EXPECT_EQ(anArray1.Length(), anArray2.Length());
+ EXPECT_EQ(anArray1.Lower(), anArray2.Lower());
+ EXPECT_EQ(anArray1.Upper(), anArray2.Upper());
+
+ for (Standard_Integer i = anArray1.Lower(); i <= anArray1.Upper(); i++)
+ {
+ EXPECT_EQ(anArray1(i), anArray2(i));
+ }
+}
+
+TEST_F(NCollection_Array1Test, Move)
+{
+ NCollection_Array1<Standard_Integer> anArray1(1, 5);
+
+ // Initialize array
+ for (Standard_Integer i = anArray1.Lower(); i <= anArray1.Upper(); i++)
+ {
+ anArray1(i) = i * 10;
+ }
+
+ // Test Move method
+ NCollection_Array1<Standard_Integer> anArray2(11, 15);
+ anArray2.Move(anArray1);
+ anArray2.Resize(1, 5, Standard_True); // Resize to match anArray1
+
+ // Verify move result
+ EXPECT_EQ(5, anArray2.Length());
+ EXPECT_EQ(1, anArray2.Lower());
+ EXPECT_EQ(5, anArray2.Upper());
+
+ // Original array is keep referecing the same data
+ EXPECT_EQ(anArray1.Lower(), anArray2.Lower());
+ EXPECT_EQ(anArray1.Upper(), anArray2.Upper());
+ EXPECT_EQ(anArray1(1), anArray2(1));
+ EXPECT_EQ(anArray1(2), anArray2(2));
+ EXPECT_EQ(5, anArray1.Length());
+}
+
+TEST_F(NCollection_Array1Test, Init)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+
+ // Test Init method
+ anArray.Init(42);
+
+ // Verify all values initialized
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ EXPECT_EQ(42, anArray(i));
+ }
+}
+
+TEST_F(NCollection_Array1Test, SetValue)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+
+ // Test SetValue method
+ anArray.SetValue(3, 123);
+
+ // Verify value set
+ EXPECT_EQ(123, anArray(3));
+}
+
+TEST_F(NCollection_Array1Test, FirstLast)
+{
+ NCollection_Array1<Standard_Integer> anArray(5, 10);
+
+ anArray(5) = 55;
+ anArray(10) = 1010;
+
+ // Test First and Last methods
+ EXPECT_EQ(55, anArray.First());
+ EXPECT_EQ(1010, anArray.Last());
+
+ // Change First and Last
+ anArray.ChangeFirst() = 555;
+ anArray.ChangeLast() = 10101;
+
+ EXPECT_EQ(555, anArray.First());
+ EXPECT_EQ(10101, anArray.Last());
+}
+
+TEST_F(NCollection_Array1Test, STLIteration)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ anArray(i) = i * 10;
+ }
+
+ // Test STL-style iteration
+ Standard_Integer index = 1;
+ for (const auto& val : anArray)
+ {
+ EXPECT_EQ(index * 10, val);
+ index++;
+ }
+}
+
+TEST_F(NCollection_Array1Test, Resize)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+ for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
+ {
+ anArray(i) = i * 10;
+ }
+
+ // Test Resize method - increasing size
+ anArray.Resize(1, 10, Standard_True);
+
+ // Check new size
+ EXPECT_EQ(10, anArray.Length());
+ EXPECT_EQ(1, anArray.Lower());
+ EXPECT_EQ(10, anArray.Upper());
+
+ // Verify original data preserved
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ EXPECT_EQ(i * 10, anArray(i));
+ }
+
+ // Test Resize method - decreasing size
+ NCollection_Array1<Standard_Integer> anArray2(1, 10);
+ for (Standard_Integer i = anArray2.Lower(); i <= anArray2.Upper(); i++)
+ {
+ anArray2(i) = i * 10;
+ }
+
+ anArray2.Resize(1, 5, Standard_True);
+
+ // Check new size
+ EXPECT_EQ(5, anArray2.Length());
+ EXPECT_EQ(1, anArray2.Lower());
+ EXPECT_EQ(5, anArray2.Upper());
+
+ // Verify original data preserved
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ EXPECT_EQ(i * 10, anArray2(i));
+ }
+}
+
+TEST_F(NCollection_Array1Test, ChangeValue)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+ anArray.Init(42);
+
+ // Test ChangeValue method
+ anArray.ChangeValue(3) = 123;
+
+ // Verify value changed
+ EXPECT_EQ(123, anArray(3));
+
+ // Verify other values unchanged
+ EXPECT_EQ(42, anArray(1));
+ EXPECT_EQ(42, anArray(2));
+ EXPECT_EQ(42, anArray(4));
+ EXPECT_EQ(42, anArray(5));
+}
+
+TEST_F(NCollection_Array1Test, IteratorAccess)
+{
+ NCollection_Array1<Standard_Integer> anArray(1, 5);
+ for (Standard_Integer i = 1; i <= 5; i++)
+ {
+ anArray(i) = i * 10;
+ }
+
+ // Test iteration using STL-compatible iterators
+ int index = 1;
+ for (auto it = anArray.begin(); it != anArray.end(); ++it, ++index)
+ {
+ EXPECT_EQ(index * 10, *it);
+ }
+
+ // Test range-based for loop
+ index = 1;
+ for (const auto& value : anArray)
+ {
+ EXPECT_EQ(index * 10, value);
+ index++;
+ }
+}
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_BaseAllocator.hxx>
+#include <NCollection_Vector.hxx>
+
+#include <gtest/gtest.h>
+
+// Simple struct to test allocations
+struct TestStruct
+{
+ Standard_Integer myValue1;
+ Standard_Real myValue2;
+ Standard_Character myChar;
+
+ TestStruct(Standard_Integer theVal1 = 0,
+ Standard_Real theVal2 = 0.0,
+ Standard_Character theChar = 'A')
+ : myValue1(theVal1),
+ myValue2(theVal2),
+ myChar(theChar)
+ {
+ }
+
+ bool operator==(const TestStruct& other) const
+ {
+ return myValue1 == other.myValue1 && fabs(myValue2 - other.myValue2) < 1e-10
+ && myChar == other.myChar;
+ }
+};
+
+TEST(NCollection_BaseAllocatorTest, DefaultInstance)
+{
+ // Get default allocator
+ Handle(NCollection_BaseAllocator) aDefaultAlloc =
+ NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Ensure it's not null
+ EXPECT_FALSE(aDefaultAlloc.IsNull());
+
+ // Test that we get the same instance when requesting default allocator again
+ Handle(NCollection_BaseAllocator) anotherDefaultAlloc =
+ NCollection_BaseAllocator::CommonBaseAllocator();
+ EXPECT_EQ(aDefaultAlloc, anotherDefaultAlloc);
+}
+
+TEST(NCollection_BaseAllocatorTest, Allocate)
+{
+ Handle(NCollection_BaseAllocator) anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Test allocation of different sizes
+ void* ptr1 = anAlloc->Allocate(10);
+ EXPECT_NE(ptr1, nullptr);
+
+ void* ptr2 = anAlloc->Allocate(100);
+ EXPECT_NE(ptr2, nullptr);
+
+ void* ptr3 = anAlloc->Allocate(1000);
+ EXPECT_NE(ptr3, nullptr);
+
+ // Allocations should return different pointers
+ EXPECT_NE(ptr1, ptr2);
+ EXPECT_NE(ptr1, ptr3);
+ EXPECT_NE(ptr2, ptr3);
+
+ // Free the allocated memory
+ anAlloc->Free(ptr1);
+ anAlloc->Free(ptr2);
+ anAlloc->Free(ptr3);
+}
+
+TEST(NCollection_BaseAllocatorTest, AllocateStruct)
+{
+ Handle(NCollection_BaseAllocator) anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Allocate and construct test struct
+ TestStruct* pStruct = static_cast<TestStruct*>(anAlloc->Allocate(sizeof(TestStruct)));
+ EXPECT_NE(pStruct, nullptr);
+
+ // Use placement new to construct object at allocated memory
+ new (pStruct) TestStruct(42, 3.14159, 'Z');
+
+ // Verify object values
+ EXPECT_EQ(pStruct->myValue1, 42);
+ EXPECT_DOUBLE_EQ(pStruct->myValue2, 3.14159);
+ EXPECT_EQ(pStruct->myChar, 'Z');
+
+ // Destruct the object and free memory
+ pStruct->~TestStruct();
+ anAlloc->Free(pStruct);
+}
+
+TEST(NCollection_BaseAllocatorTest, AllocateArray)
+{
+ Handle(NCollection_BaseAllocator) anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ const Standard_Integer arraySize = 5;
+
+ // Allocate memory for an array of test structs
+ TestStruct* pArray = static_cast<TestStruct*>(anAlloc->Allocate(arraySize * sizeof(TestStruct)));
+ EXPECT_NE(pArray, nullptr);
+
+ // Construct objects at allocated memory
+ for (Standard_Integer i = 0; i < arraySize; ++i)
+ {
+ new (&pArray[i]) TestStruct(i, i * 1.5, static_cast<Standard_Character>('A' + i));
+ }
+
+ // Verify object values
+ for (Standard_Integer i = 0; i < arraySize; ++i)
+ {
+ EXPECT_EQ(pArray[i].myValue1, i);
+ EXPECT_DOUBLE_EQ(pArray[i].myValue2, i * 1.5);
+ EXPECT_EQ(pArray[i].myChar, static_cast<Standard_Character>('A' + i));
+ }
+
+ // Destruct objects and free memory
+ for (Standard_Integer i = 0; i < arraySize; ++i)
+ {
+ pArray[i].~TestStruct();
+ }
+ anAlloc->Free(pArray);
+}
+
+TEST(NCollection_BaseAllocatorTest, UsageWithVector)
+{
+ // Create a collection using the default allocator
+ NCollection_Vector<TestStruct> aVector;
+
+ // Add elements
+ aVector.Append(TestStruct(10, 1.0, 'X'));
+ aVector.Append(TestStruct(20, 2.0, 'Y'));
+ aVector.Append(TestStruct(30, 3.0, 'Z'));
+
+ // Verify elements were stored correctly
+ EXPECT_EQ(aVector.Length(), 3);
+ EXPECT_EQ(aVector(0).myValue1, 10);
+ EXPECT_DOUBLE_EQ(aVector(0).myValue2, 1.0);
+ EXPECT_EQ(aVector(0).myChar, 'X');
+
+ EXPECT_EQ(aVector(1).myValue1, 20);
+ EXPECT_DOUBLE_EQ(aVector(1).myValue2, 2.0);
+ EXPECT_EQ(aVector(1).myChar, 'Y');
+
+ EXPECT_EQ(aVector(2).myValue1, 30);
+ EXPECT_DOUBLE_EQ(aVector(2).myValue2, 3.0);
+ EXPECT_EQ(aVector(2).myChar, 'Z');
+
+ // Create a custom allocator
+ Handle(NCollection_BaseAllocator) aCustomAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Create a collection using custom allocator
+ NCollection_Vector<TestStruct> aVectorWithCustomAlloc(5, aCustomAlloc);
+
+ // Add elements
+ aVectorWithCustomAlloc.Append(TestStruct(40, 4.0, 'P'));
+ aVectorWithCustomAlloc.Append(TestStruct(50, 5.0, 'Q'));
+
+ // Verify elements were stored correctly
+ EXPECT_EQ(aVectorWithCustomAlloc.Length(), 2);
+ EXPECT_EQ(aVectorWithCustomAlloc(0).myValue1, 40);
+ EXPECT_DOUBLE_EQ(aVectorWithCustomAlloc(0).myValue2, 4.0);
+ EXPECT_EQ(aVectorWithCustomAlloc(0).myChar, 'P');
+
+ EXPECT_EQ(aVectorWithCustomAlloc(1).myValue1, 50);
+ EXPECT_DOUBLE_EQ(aVectorWithCustomAlloc(1).myValue2, 5.0);
+ EXPECT_EQ(aVectorWithCustomAlloc(1).myChar, 'Q');
+}
+
+TEST(NCollection_BaseAllocatorTest, CopyAndMove)
+{
+ Handle(NCollection_BaseAllocator) anAlloc1 = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Create a collection with allocator
+ NCollection_Vector<TestStruct> aVector1(5, anAlloc1);
+ aVector1.Append(TestStruct(10, 1.0, 'A'));
+ aVector1.Append(TestStruct(20, 2.0, 'B'));
+
+ // Copy constructor should preserve the allocator
+ NCollection_Vector<TestStruct> aVector2(aVector1);
+ EXPECT_EQ(aVector2.Length(), 2);
+ EXPECT_EQ(aVector2(0), TestStruct(10, 1.0, 'A'));
+ EXPECT_EQ(aVector2(1), TestStruct(20, 2.0, 'B'));
+
+ // Create a new collection with new allocator
+ Handle(NCollection_BaseAllocator) anAlloc2 = NCollection_BaseAllocator::CommonBaseAllocator();
+ NCollection_Vector<TestStruct> aVector3(5, anAlloc2);
+
+ // Assignment operator should preserve the destination's allocator
+ aVector3 = aVector1;
+ EXPECT_EQ(aVector3.Length(), 2);
+ EXPECT_EQ(aVector3(0), TestStruct(10, 1.0, 'A'));
+ EXPECT_EQ(aVector3(1), TestStruct(20, 2.0, 'B'));
+}
+
+TEST(NCollection_BaseAllocatorTest, BigAllocation)
+{
+ Handle(NCollection_BaseAllocator) anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+
+ // Test a large allocation
+ const size_t largeSize = 1024 * 1024; // 1MB
+ void* pLarge = anAlloc->Allocate(largeSize);
+ EXPECT_NE(pLarge, nullptr);
+
+ // Write to the allocated memory to verify it's usable
+ memset(pLarge, 0xAB, largeSize);
+
+ // Free the allocated memory
+ anAlloc->Free(pLarge);
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_DataMap.hxx>
+#include <Standard_Integer.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <gtest/gtest.h>
+
+// Test fixture for NCollection_DataMap tests
+class NCollection_DataMapTest : public testing::Test
+{
+protected:
+ void SetUp() override {}
+
+ void TearDown() override {}
+};
+
+// Tests with Integer keys and String values
+TEST_F(NCollection_DataMapTest, IntegerKeys)
+{
+ // Default constructor should create an empty map
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(0, aMap.Size());
+ EXPECT_EQ(0, aMap.Extent());
+}
+
+TEST_F(NCollection_DataMapTest, BindingAndAccess)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ // Test Bind method
+ aMap.Bind(1, "One");
+ aMap.Bind(2, "Two");
+ aMap.Bind(3, "Three");
+
+ EXPECT_FALSE(aMap.IsEmpty());
+ EXPECT_EQ(3, aMap.Size());
+
+ // Test Find method
+ EXPECT_STREQ("One", aMap.Find(1).ToCString());
+ EXPECT_STREQ("Two", aMap.Find(2).ToCString());
+ EXPECT_STREQ("Three", aMap.Find(3).ToCString());
+
+ // Test IsBound
+ EXPECT_TRUE(aMap.IsBound(1));
+ EXPECT_TRUE(aMap.IsBound(2));
+ EXPECT_TRUE(aMap.IsBound(3));
+ EXPECT_FALSE(aMap.IsBound(4));
+}
+
+TEST_F(NCollection_DataMapTest, ChangeFind)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ aMap.Bind(1, "One");
+
+ // Test ChangeFind for modification
+ EXPECT_STREQ("One", aMap.Find(1).ToCString());
+ aMap.ChangeFind(1) = "Modified One";
+ EXPECT_STREQ("Modified One", aMap.Find(1).ToCString());
+}
+
+TEST_F(NCollection_DataMapTest, Rebind)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ // First binding
+ aMap.Bind(1, "One");
+ EXPECT_STREQ("One", aMap.Find(1).ToCString());
+
+ // Re-bind the same key with a different value
+ aMap.Bind(1, "New One");
+ EXPECT_STREQ("New One", aMap.Find(1).ToCString());
+
+ // Size should still be 1
+ EXPECT_EQ(1, aMap.Size());
+}
+
+TEST_F(NCollection_DataMapTest, UnBind)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ aMap.Bind(1, "One");
+ aMap.Bind(2, "Two");
+ aMap.Bind(3, "Three");
+
+ // Test UnBind
+ EXPECT_TRUE(aMap.UnBind(2));
+ EXPECT_EQ(2, aMap.Size());
+
+ // Check key 2 is no longer bound
+ EXPECT_FALSE(aMap.IsBound(2));
+
+ // Try to unbind a non-existent key
+ EXPECT_FALSE(aMap.UnBind(4));
+ EXPECT_EQ(2, aMap.Size());
+}
+
+TEST_F(NCollection_DataMapTest, Clear)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+
+ aMap.Bind(1, "One");
+ aMap.Bind(2, "Two");
+
+ // Test Clear
+ aMap.Clear();
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(0, aMap.Size());
+ EXPECT_FALSE(aMap.IsBound(1));
+ EXPECT_FALSE(aMap.IsBound(2));
+}
+
+TEST_F(NCollection_DataMapTest, Assignment)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap1;
+ aMap1.Bind(1, "One");
+ aMap1.Bind(2, "Two");
+
+ // Test assignment operator
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap2;
+ aMap2 = aMap1;
+
+ // Check both maps have the same content
+ EXPECT_EQ(aMap1.Size(), aMap2.Size());
+ EXPECT_STREQ(aMap1.Find(1).ToCString(), aMap2.Find(1).ToCString());
+ EXPECT_STREQ(aMap1.Find(2).ToCString(), aMap2.Find(2).ToCString());
+
+ // Modify original to ensure deep copy
+ aMap1.ChangeFind(1) = "Modified One";
+ EXPECT_STREQ("Modified One", aMap1.Find(1).ToCString());
+ EXPECT_STREQ("One", aMap2.Find(1).ToCString());
+}
+
+TEST_F(NCollection_DataMapTest, Find_NonExisting)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+ aMap.Bind(1, "One");
+
+ // Finding non-existent key should throw exception
+ EXPECT_THROW(aMap.Find(2), Standard_NoSuchObject);
+
+ // ChangeFind for non-existent key should throw exception
+ EXPECT_THROW(aMap.ChangeFind(2), Standard_NoSuchObject);
+}
+
+TEST_F(NCollection_DataMapTest, IteratorAccess)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+ aMap.Bind(1, "One");
+ aMap.Bind(2, "Two");
+ aMap.Bind(3, "Three");
+
+ // Test iteration using OCCT iterator
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString>::Iterator it(aMap);
+
+ // Create sets to check all keys and values are visited
+ std::set<Standard_Integer> foundKeys;
+ std::set<std::string> foundValues;
+
+ for (; it.More(); it.Next())
+ {
+ foundKeys.insert(it.Key());
+ foundValues.insert(it.Value().ToCString());
+ }
+
+ // Check all keys were visited
+ EXPECT_EQ(3, foundKeys.size());
+ EXPECT_TRUE(foundKeys.find(1) != foundKeys.end());
+ EXPECT_TRUE(foundKeys.find(2) != foundKeys.end());
+ EXPECT_TRUE(foundKeys.find(3) != foundKeys.end());
+
+ // Check all values were visited
+ EXPECT_EQ(3, foundValues.size());
+ EXPECT_TRUE(foundValues.find("One") != foundValues.end());
+ EXPECT_TRUE(foundValues.find("Two") != foundValues.end());
+ EXPECT_TRUE(foundValues.find("Three") != foundValues.end());
+}
+
+TEST_F(NCollection_DataMapTest, ChangeValue)
+{
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString> aMap;
+ aMap.Bind(1, "One");
+
+ // Test Value change through iterator
+ NCollection_DataMap<Standard_Integer, TCollection_AsciiString>::Iterator it(aMap);
+ EXPECT_STREQ("One", it.Value().ToCString());
+
+ it.ChangeValue() = "Modified via Iterator";
+ EXPECT_STREQ("Modified via Iterator", it.Value().ToCString());
+
+ // Check the change is reflected in the map itself
+ EXPECT_STREQ("Modified via Iterator", aMap.Find(1).ToCString());
+}
+
+TEST_F(NCollection_DataMapTest, ExhaustiveIterator)
+{
+ const int NUM_ELEMENTS = 1000;
+
+ // Create a map with many elements to test iterator efficiency
+ NCollection_DataMap<Standard_Integer, Standard_Integer> aMap;
+
+ // Bind many elements
+ for (int i = 0; i < NUM_ELEMENTS; ++i)
+ {
+ aMap.Bind(i, i * 2);
+ }
+
+ EXPECT_EQ(NUM_ELEMENTS, aMap.Size());
+
+ // Count elements using iterator
+ int count = 0;
+ NCollection_DataMap<Standard_Integer, Standard_Integer>::Iterator it(aMap);
+ for (; it.More(); it.Next())
+ {
+ EXPECT_EQ(it.Key() * 2, it.Value());
+ count++;
+ }
+
+ EXPECT_EQ(NUM_ELEMENTS, count);
+}
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_DoubleMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <gtest/gtest.h>
+
+// Basic test types for the DoubleMap
+typedef Standard_Integer Key1Type;
+typedef Standard_Real Key2Type;
+
+// Custom key types for testing
+class TestKey1
+{
+public:
+ TestKey1(int id = 0, const char* name = "")
+ : myId(id),
+ myName(name)
+ {
+ }
+
+ bool operator==(const TestKey1& other) const
+ {
+ return myId == other.myId && myName == other.myName;
+ }
+
+ int GetId() const { return myId; }
+
+ const std::string& GetName() const { return myName; }
+
+private:
+ int myId;
+ std::string myName;
+};
+
+class TestKey2
+{
+public:
+ TestKey2(double value = 0.0, const char* code = "")
+ : myValue(value),
+ myCode(code)
+ {
+ }
+
+ bool operator==(const TestKey2& other) const
+ {
+ return fabs(myValue - other.myValue) < 1e-10 && myCode == other.myCode;
+ }
+
+ double GetValue() const { return myValue; }
+
+ const std::string& GetCode() const { return myCode; }
+
+private:
+ double myValue;
+ std::string myCode;
+};
+
+namespace std
+{
+template <>
+struct hash<TestKey1>
+{
+ size_t operator()(const TestKey1& key) const
+ {
+ return static_cast<size_t>(key.GetId() + std::hash<std::string>()(key.GetName()));
+ }
+};
+
+template <>
+struct hash<TestKey2>
+{
+ size_t operator()(const TestKey2& key) const
+ {
+ return static_cast<size_t>(key.GetValue() * 100 + std::hash<std::string>()(key.GetCode()));
+ }
+};
+} // namespace std
+
+TEST(NCollection_DoubleMapTest, DefaultConstructor)
+{
+ // Test default constructor
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+ EXPECT_EQ(aMap.Size(), 0);
+}
+
+TEST(NCollection_DoubleMapTest, CustomBuckets)
+{
+ // Test constructor with custom number of buckets
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap(100);
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+ EXPECT_EQ(aMap.Size(), 0);
+}
+
+TEST(NCollection_DoubleMapTest, BasicBindFind)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // Test binding elements
+ aMap.Bind(10, 1.0);
+ aMap.Bind(20, 2.0);
+ aMap.Bind(30, 3.0);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Test finding by Key1
+ EXPECT_TRUE(aMap.IsBound1(10));
+ EXPECT_TRUE(aMap.IsBound1(20));
+ EXPECT_TRUE(aMap.IsBound1(30));
+ EXPECT_FALSE(aMap.IsBound1(40));
+
+ // Test finding by Key2
+ EXPECT_TRUE(aMap.IsBound2(1.0));
+ EXPECT_TRUE(aMap.IsBound2(2.0));
+ EXPECT_TRUE(aMap.IsBound2(3.0));
+ EXPECT_FALSE(aMap.IsBound2(4.0));
+
+ // Test finding Key2 by Key1
+ EXPECT_DOUBLE_EQ(aMap.Find1(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap.Find1(20), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.Find1(30), 3.0);
+
+ // Test finding Key1 by Key2
+ EXPECT_EQ(aMap.Find2(1.0), 10);
+ EXPECT_EQ(aMap.Find2(2.0), 20);
+ EXPECT_EQ(aMap.Find2(3.0), 30);
+}
+
+TEST(NCollection_DoubleMapTest, BindWithDuplicateKeys)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // First binding
+ aMap.Bind(10, 1.0);
+ EXPECT_EQ(aMap.Extent(), 1);
+ EXPECT_DOUBLE_EQ(aMap.Find1(10), 1.0);
+
+ // Try to bind a duplicate Key1 with a new Key2
+ // This should fail silently in a production system, but we'll check that the map wasn't modified
+ EXPECT_ANY_THROW(aMap.Bind(10, 2.0));
+ EXPECT_EQ(aMap.Extent(), 1); // Size should remain 1
+ EXPECT_DOUBLE_EQ(aMap.Find1(10), 1.0); // Value should remain unchanged
+ EXPECT_FALSE(aMap.IsBound2(2.0)); // The new Key2 should not be bound
+
+ // Try to bind a new Key1 with duplicate Key2
+ EXPECT_ANY_THROW(aMap.Bind(20, 1.0));
+ EXPECT_EQ(aMap.Extent(), 1); // Size should remain 1
+ EXPECT_FALSE(aMap.IsBound1(20)); // The new Key1 should not be bound
+}
+
+TEST(NCollection_DoubleMapTest, UnbindTest)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // Add elements
+ aMap.Bind(10, 1.0);
+ aMap.Bind(20, 2.0);
+ aMap.Bind(30, 3.0);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Test UnBind1
+ aMap.UnBind1(20);
+ EXPECT_EQ(aMap.Extent(), 2);
+ EXPECT_FALSE(aMap.IsBound1(20));
+ EXPECT_FALSE(aMap.IsBound2(2.0));
+
+ // Test UnBind2
+ aMap.UnBind2(3.0);
+ EXPECT_EQ(aMap.Extent(), 1);
+ EXPECT_FALSE(aMap.IsBound1(30));
+ EXPECT_FALSE(aMap.IsBound2(3.0));
+
+ // Try to unbind non-existent keys
+ aMap.UnBind1(40); // Should have no effect
+ EXPECT_EQ(aMap.Extent(), 1);
+
+ aMap.UnBind2(4.0); // Should have no effect
+ EXPECT_EQ(aMap.Extent(), 1);
+}
+
+TEST(NCollection_DoubleMapTest, Clear)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // Add elements
+ aMap.Bind(10, 1.0);
+ aMap.Bind(20, 2.0);
+ aMap.Bind(30, 3.0);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Clear the map
+ aMap.Clear();
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+
+ // Ensure we can add elements again
+ aMap.Bind(40, 4.0);
+ EXPECT_EQ(aMap.Extent(), 1);
+}
+
+TEST(NCollection_DoubleMapTest, SeekTests)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // Add elements
+ aMap.Bind(10, 1.0);
+ aMap.Bind(20, 2.0);
+
+ // Test Seek1
+ const Key2Type* key2Ptr = aMap.Seek1(10);
+ EXPECT_TRUE(key2Ptr != nullptr);
+ EXPECT_DOUBLE_EQ(*key2Ptr, 1.0);
+
+ // Test Seek2
+ const Key1Type* key1Ptr = aMap.Seek2(2.0);
+ EXPECT_TRUE(key1Ptr != nullptr);
+ EXPECT_EQ(*key1Ptr, 20);
+
+ // Test seeking non-existent keys
+ EXPECT_TRUE(aMap.Seek1(30) == nullptr);
+ EXPECT_TRUE(aMap.Seek2(3.0) == nullptr);
+}
+
+TEST(NCollection_DoubleMapTest, CopyConstructor)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap1;
+
+ // Add elements to first map
+ aMap1.Bind(10, 1.0);
+ aMap1.Bind(20, 2.0);
+ aMap1.Bind(30, 3.0);
+
+ // Create a copy
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap2(aMap1);
+
+ // Check that copy has the same elements
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_TRUE(aMap2.IsBound1(10));
+ EXPECT_TRUE(aMap2.IsBound1(20));
+ EXPECT_TRUE(aMap2.IsBound1(30));
+ EXPECT_TRUE(aMap2.IsBound2(1.0));
+ EXPECT_TRUE(aMap2.IsBound2(2.0));
+ EXPECT_TRUE(aMap2.IsBound2(3.0));
+
+ // Modify original to ensure deep copy
+ aMap1.Bind(40, 4.0);
+ EXPECT_EQ(aMap1.Extent(), 4);
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_FALSE(aMap2.IsBound1(40));
+ EXPECT_FALSE(aMap2.IsBound2(4.0));
+}
+
+TEST(NCollection_DoubleMapTest, AssignmentOperator)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap1;
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap2;
+
+ // Add elements to first map
+ aMap1.Bind(10, 1.0);
+ aMap1.Bind(20, 2.0);
+
+ // Add different elements to second map
+ aMap2.Bind(30, 3.0);
+ aMap2.Bind(40, 4.0);
+ aMap2.Bind(50, 5.0);
+
+ // Assign first to second
+ aMap2 = aMap1;
+
+ // Check that second map now matches first
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.IsBound1(10));
+ EXPECT_TRUE(aMap2.IsBound1(20));
+ EXPECT_FALSE(aMap2.IsBound1(30));
+ EXPECT_FALSE(aMap2.IsBound1(40));
+ EXPECT_FALSE(aMap2.IsBound1(50));
+
+ EXPECT_TRUE(aMap2.IsBound2(1.0));
+ EXPECT_TRUE(aMap2.IsBound2(2.0));
+ EXPECT_FALSE(aMap2.IsBound2(3.0));
+ EXPECT_FALSE(aMap2.IsBound2(4.0));
+ EXPECT_FALSE(aMap2.IsBound2(5.0));
+}
+
+TEST(NCollection_DoubleMapTest, ReSize)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap(3); // Start with small bucket count
+
+ // Add many elements to trigger resize
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ aMap.Bind(i, static_cast<Standard_Real>(i) / 10.0);
+ }
+
+ // Verify all elements are present
+ EXPECT_EQ(aMap.Extent(), 100);
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ EXPECT_TRUE(aMap.IsBound1(i));
+ EXPECT_TRUE(aMap.IsBound2(static_cast<Standard_Real>(i) / 10.0));
+ EXPECT_DOUBLE_EQ(aMap.Find1(i), static_cast<Standard_Real>(i) / 10.0);
+ EXPECT_EQ(aMap.Find2(static_cast<Standard_Real>(i) / 10.0), i);
+ }
+}
+
+TEST(NCollection_DoubleMapTest, Exchange)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap1;
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap2;
+
+ // Add elements to first map
+ aMap1.Bind(10, 1.0);
+ aMap1.Bind(20, 2.0);
+
+ // Add different elements to second map
+ aMap2.Bind(30, 3.0);
+ aMap2.Bind(40, 4.0);
+ aMap2.Bind(50, 5.0);
+
+ // Exchange maps
+ aMap1.Exchange(aMap2);
+
+ // Check that maps are exchanged
+ EXPECT_EQ(aMap1.Extent(), 3);
+ EXPECT_TRUE(aMap1.IsBound1(30));
+ EXPECT_TRUE(aMap1.IsBound1(40));
+ EXPECT_TRUE(aMap1.IsBound1(50));
+ EXPECT_TRUE(aMap1.IsBound2(3.0));
+ EXPECT_TRUE(aMap1.IsBound2(4.0));
+ EXPECT_TRUE(aMap1.IsBound2(5.0));
+
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.IsBound1(10));
+ EXPECT_TRUE(aMap2.IsBound1(20));
+ EXPECT_TRUE(aMap2.IsBound2(1.0));
+ EXPECT_TRUE(aMap2.IsBound2(2.0));
+}
+
+TEST(NCollection_DoubleMapTest, Iterator)
+{
+ NCollection_DoubleMap<Key1Type, Key2Type> aMap;
+
+ // Add elements
+ aMap.Bind(10, 1.0);
+ aMap.Bind(20, 2.0);
+ aMap.Bind(30, 3.0);
+
+ // Use iterator to check all elements
+ Standard_Boolean found10 = Standard_False;
+ Standard_Boolean found20 = Standard_False;
+ Standard_Boolean found30 = Standard_False;
+ Standard_Size count = 0;
+
+ for (NCollection_DoubleMap<Key1Type, Key2Type>::Iterator it(aMap); it.More(); it.Next(), ++count)
+ {
+ const Key1Type& key1 = it.Key1();
+ const Key2Type& key2 = it.Key2();
+
+ if (key1 == 10 && key2 == 1.0)
+ found10 = Standard_True;
+ else if (key1 == 20 && key2 == 2.0)
+ found20 = Standard_True;
+ else if (key1 == 30 && key2 == 3.0)
+ found30 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found10);
+ EXPECT_TRUE(found20);
+ EXPECT_TRUE(found30);
+}
+
+TEST(NCollection_DoubleMapTest, StringKeys)
+{
+ // Test with string keys
+ NCollection_DoubleMap<TCollection_AsciiString, TCollection_AsciiString> aStringMap;
+
+ // Add string pairs
+ aStringMap.Bind(TCollection_AsciiString("Key1"), TCollection_AsciiString("Value1"));
+ aStringMap.Bind(TCollection_AsciiString("Key2"), TCollection_AsciiString("Value2"));
+ aStringMap.Bind(TCollection_AsciiString("Key3"), TCollection_AsciiString("Value3"));
+
+ EXPECT_EQ(aStringMap.Extent(), 3);
+
+ // Check key-value bindings
+ EXPECT_TRUE(aStringMap.IsBound1(TCollection_AsciiString("Key1")));
+ EXPECT_TRUE(aStringMap.IsBound1(TCollection_AsciiString("Key2")));
+ EXPECT_TRUE(aStringMap.IsBound1(TCollection_AsciiString("Key3")));
+
+ EXPECT_TRUE(aStringMap.IsBound2(TCollection_AsciiString("Value1")));
+ EXPECT_TRUE(aStringMap.IsBound2(TCollection_AsciiString("Value2")));
+ EXPECT_TRUE(aStringMap.IsBound2(TCollection_AsciiString("Value3")));
+
+ // Test finding values by keys
+ EXPECT_TRUE(aStringMap.Find1(TCollection_AsciiString("Key1")).IsEqual("Value1"));
+ EXPECT_TRUE(aStringMap.Find1(TCollection_AsciiString("Key2")).IsEqual("Value2"));
+ EXPECT_TRUE(aStringMap.Find1(TCollection_AsciiString("Key3")).IsEqual("Value3"));
+
+ // Test finding keys by values
+ EXPECT_TRUE(aStringMap.Find2(TCollection_AsciiString("Value1")).IsEqual("Key1"));
+ EXPECT_TRUE(aStringMap.Find2(TCollection_AsciiString("Value2")).IsEqual("Key2"));
+ EXPECT_TRUE(aStringMap.Find2(TCollection_AsciiString("Value3")).IsEqual("Key3"));
+}
+
+TEST(NCollection_DoubleMapTest, ComplexKeys)
+{
+ // Create map with custom key types and hashers
+ NCollection_DoubleMap<TestKey1, TestKey2> aComplexMap;
+
+ // Add complex key pairs
+ TestKey1 key1_1(1, "One");
+ TestKey1 key1_2(2, "Two");
+ TestKey1 key1_3(3, "Three");
+
+ TestKey2 key2_1(1.1, "A");
+ TestKey2 key2_2(2.2, "B");
+ TestKey2 key2_3(3.3, "C");
+
+ aComplexMap.Bind(key1_1, key2_1);
+ aComplexMap.Bind(key1_2, key2_2);
+ aComplexMap.Bind(key1_3, key2_3);
+
+ EXPECT_EQ(aComplexMap.Extent(), 3);
+
+ // Test IsBound for both key types
+ EXPECT_TRUE(aComplexMap.IsBound1(TestKey1(1, "One")));
+ EXPECT_TRUE(aComplexMap.IsBound1(TestKey1(2, "Two")));
+ EXPECT_TRUE(aComplexMap.IsBound1(TestKey1(3, "Three")));
+
+ EXPECT_TRUE(aComplexMap.IsBound2(TestKey2(1.1, "A")));
+ EXPECT_TRUE(aComplexMap.IsBound2(TestKey2(2.2, "B")));
+ EXPECT_TRUE(aComplexMap.IsBound2(TestKey2(3.3, "C")));
+
+ // Test finding second key by first key
+ const TestKey2& foundKey2 = aComplexMap.Find1(key1_2);
+ EXPECT_DOUBLE_EQ(foundKey2.GetValue(), 2.2);
+ EXPECT_EQ(foundKey2.GetCode(), "B");
+
+ // Test finding first key by second key
+ const TestKey1& foundKey1 = aComplexMap.Find2(key2_3);
+ EXPECT_EQ(foundKey1.GetId(), 3);
+ EXPECT_EQ(foundKey1.GetName(), "Three");
+}
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_IndexedDataMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <gtest/gtest.h>
+
+// Basic test types for the IndexedDataMap
+typedef Standard_Integer KeyType;
+typedef Standard_Real ItemType;
+
+// Custom class for testing complex keys
+class TestKey
+{
+public:
+ TestKey(int id = 0, const char* name = "")
+ : myId(id),
+ myName(name)
+ {
+ }
+
+ bool operator==(const TestKey& other) const
+ {
+ return myId == other.myId && myName == other.myName;
+ }
+
+ int GetId() const { return myId; }
+
+ const std::string& GetName() const { return myName; }
+
+private:
+ int myId;
+ std::string myName;
+};
+
+namespace std
+{
+template <>
+struct hash<TestKey>
+{
+ size_t operator()(const TestKey& key) const
+ {
+ // Combine the hash
+ size_t aCombintation[2] = {std::hash<int>()(key.GetId()),
+ std::hash<std::string>()(key.GetName())};
+ return opencascade::hashBytes(aCombintation, sizeof(aCombintation));
+ }
+};
+} // namespace std
+
+// Custom class for testing complex items
+class TestItem
+{
+public:
+ TestItem(double value = 0.0, const char* description = "")
+ : myValue(value),
+ myDescription(description)
+ {
+ }
+
+ bool operator==(const TestItem& other) const
+ {
+ return fabs(myValue - other.myValue) < 1e-10 && myDescription == other.myDescription;
+ }
+
+ double GetValue() const { return myValue; }
+
+ const std::string& GetDescription() const { return myDescription; }
+
+ void SetValue(double value) { myValue = value; }
+
+private:
+ double myValue;
+ std::string myDescription;
+};
+
+TEST(NCollection_IndexedDataMapTest, DefaultConstructor)
+{
+ // Test default constructor
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+ EXPECT_EQ(aMap.Size(), 0);
+}
+
+TEST(NCollection_IndexedDataMapTest, BasicAddFind)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Test adding elements
+ Standard_Integer index1 = aMap.Add(10, 1.0);
+ Standard_Integer index2 = aMap.Add(20, 2.0);
+ Standard_Integer index3 = aMap.Add(30, 3.0);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Test finding elements by key
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 3);
+
+ // Test finding keys by index
+ EXPECT_EQ(aMap.FindKey(1), 10);
+ EXPECT_EQ(aMap.FindKey(2), 20);
+ EXPECT_EQ(aMap.FindKey(3), 30);
+
+ // Test finding items by index
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(1), 1.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(3), 3.0);
+
+ // Test operator()
+ EXPECT_DOUBLE_EQ(aMap(1), 1.0);
+ EXPECT_DOUBLE_EQ(aMap(2), 2.0);
+ EXPECT_DOUBLE_EQ(aMap(3), 3.0);
+
+ // Test finding items by key
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(30), 3.0);
+
+ // Test Contains
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+ EXPECT_FALSE(aMap.Contains(40));
+}
+
+TEST(NCollection_IndexedDataMapTest, DuplicateKey)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add initial elements
+ Standard_Integer index1 = aMap.Add(10, 1.0);
+ Standard_Integer index2 = aMap.Add(20, 2.0);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+
+ // Try to add a duplicate - should return the existing index and not change the item
+ Standard_Integer indexDup = aMap.Add(10, 3.0);
+ EXPECT_EQ(indexDup, 1);
+ EXPECT_EQ(aMap.Extent(), 2); // Size should not change
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.0); // Original value should be preserved
+}
+
+TEST(NCollection_IndexedDataMapTest, ChangeValues)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+
+ // Change values through ChangeFromIndex
+ aMap.ChangeFromIndex(1) = 1.5;
+ aMap.ChangeFromIndex(2) = 2.5;
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(1), 1.5);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 2.5);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.5);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.5);
+
+ // Change values through ChangeFromKey
+ aMap.ChangeFromKey(10) = 1.75;
+ aMap.ChangeFromKey(20) = 2.75;
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(1), 1.75);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 2.75);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.75);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.75);
+
+ // Change values through operator()
+ aMap(1) = 1.9;
+ aMap(2) = 2.9;
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(1), 1.9);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 2.9);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.9);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.9);
+}
+
+TEST(NCollection_IndexedDataMapTest, SeekTests)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+
+ // Test Seek
+ const ItemType* item1 = aMap.Seek(10);
+ const ItemType* item2 = aMap.Seek(20);
+ const ItemType* item3 = aMap.Seek(30); // Not present
+
+ EXPECT_TRUE(item1 != nullptr);
+ EXPECT_TRUE(item2 != nullptr);
+ EXPECT_TRUE(item3 == nullptr);
+
+ EXPECT_DOUBLE_EQ(*item1, 1.0);
+ EXPECT_DOUBLE_EQ(*item2, 2.0);
+
+ // Test ChangeSeek
+ ItemType* changeItem1 = aMap.ChangeSeek(10);
+ ItemType* changeItem2 = aMap.ChangeSeek(20);
+ ItemType* changeItem3 = aMap.ChangeSeek(30); // Not present
+
+ EXPECT_TRUE(changeItem1 != nullptr);
+ EXPECT_TRUE(changeItem2 != nullptr);
+ EXPECT_TRUE(changeItem3 == nullptr);
+
+ *changeItem1 = 1.5;
+ *changeItem2 = 2.5;
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.5);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.5);
+
+ // Test FindFromKey with copy
+ ItemType value;
+ bool found = aMap.FindFromKey(10, value);
+ EXPECT_TRUE(found);
+ EXPECT_DOUBLE_EQ(value, 1.5);
+
+ found = aMap.FindFromKey(30, value);
+ EXPECT_FALSE(found);
+}
+
+TEST(NCollection_IndexedDataMapTest, RemoveLast)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Remove the last element
+ aMap.RemoveLast();
+
+ EXPECT_EQ(aMap.Extent(), 2);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_FALSE(aMap.Contains(30));
+
+ // Check indices - they should still be sequential
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+}
+
+TEST(NCollection_IndexedDataMapTest, RemoveFromIndex)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+ aMap.Add(40, 4.0);
+
+ // Remove element at index 2
+ aMap.RemoveFromIndex(2);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20)); // Removed
+ EXPECT_TRUE(aMap.Contains(30));
+ EXPECT_TRUE(aMap.Contains(40));
+
+ // Test how the indices were rearranged
+ // Index 2 should now contain what was previously at the last position
+ EXPECT_EQ(aMap.FindKey(2), 40); // Last element moved to position 2
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 4.0);
+
+ EXPECT_EQ(aMap.FindKey(1), 10); // First element unchanged
+ EXPECT_EQ(aMap.FindKey(3), 30); // Third element unchanged
+}
+
+TEST(NCollection_IndexedDataMapTest, RemoveKey)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Remove by key
+ aMap.RemoveKey(20);
+
+ EXPECT_EQ(aMap.Extent(), 2);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // Try to remove non-existent key
+ aMap.RemoveKey(50); // Should have no effect
+ EXPECT_EQ(aMap.Extent(), 2);
+}
+
+TEST(NCollection_IndexedDataMapTest, Substitute)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Substitute key and value at index 2
+ aMap.Substitute(2, 25, 2.5);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(25));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // Check indices after substitution
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(25), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 3);
+
+ // Check values after substitution
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(25), 2.5);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(30), 3.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, Swap)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Swap elements at indices 1 and 3
+ aMap.Swap(1, 3);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Check that keys maintained their values
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // But indices are swapped
+ EXPECT_EQ(aMap.FindKey(1), 30);
+ EXPECT_EQ(aMap.FindKey(2), 20);
+ EXPECT_EQ(aMap.FindKey(3), 10);
+
+ EXPECT_EQ(aMap.FindIndex(10), 3);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 1);
+
+ // And values follow their keys
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(1), 3.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(2), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromIndex(3), 1.0);
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(30), 3.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, Clear)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Clear the map
+ aMap.Clear();
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+
+ // Ensure we can add elements again
+ Standard_Integer index1 = aMap.Add(40, 4.0);
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(aMap.Extent(), 1);
+}
+
+TEST(NCollection_IndexedDataMapTest, CopyConstructor)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap1;
+
+ // Add elements to first map
+ aMap1.Add(10, 1.0);
+ aMap1.Add(20, 2.0);
+ aMap1.Add(30, 3.0);
+
+ // Create a copy
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap2(aMap1);
+
+ // Check that copy has the same elements
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_TRUE(aMap2.Contains(30));
+
+ // Check indices
+ EXPECT_EQ(aMap2.FindIndex(10), 1);
+ EXPECT_EQ(aMap2.FindIndex(20), 2);
+ EXPECT_EQ(aMap2.FindIndex(30), 3);
+
+ // Check values
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(20), 2.0);
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(30), 3.0);
+
+ // Modify original to ensure deep copy
+ aMap1.Add(40, 4.0);
+ EXPECT_EQ(aMap1.Extent(), 4);
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_FALSE(aMap2.Contains(40));
+}
+
+TEST(NCollection_IndexedDataMapTest, AssignmentOperator)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap1;
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap2;
+
+ // Add elements to first map
+ aMap1.Add(10, 1.0);
+ aMap1.Add(20, 2.0);
+
+ // Add different elements to second map
+ aMap2.Add(30, 3.0);
+ aMap2.Add(40, 4.0);
+ aMap2.Add(50, 5.0);
+
+ // Assign first to second
+ aMap2 = aMap1;
+
+ // Check that second map now matches first
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_FALSE(aMap2.Contains(30));
+ EXPECT_FALSE(aMap2.Contains(40));
+ EXPECT_FALSE(aMap2.Contains(50));
+
+ // Check values
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(20), 2.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, Iterator)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Use iterator to check all elements
+ Standard_Boolean found10 = Standard_False;
+ Standard_Boolean found20 = Standard_False;
+ Standard_Boolean found30 = Standard_False;
+ Standard_Size count = 0;
+
+ for (NCollection_IndexedDataMap<KeyType, ItemType>::Iterator it(aMap); it.More();
+ it.Next(), ++count)
+ {
+ const KeyType& key = it.Key();
+ const ItemType& value = it.Value();
+
+ if (key == 10 && value == 1.0)
+ found10 = Standard_True;
+ else if (key == 20 && value == 2.0)
+ found20 = Standard_True;
+ else if (key == 30 && value == 3.0)
+ found30 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found10);
+ EXPECT_TRUE(found20);
+ EXPECT_TRUE(found30);
+
+ // Test modification through iterator
+ for (NCollection_IndexedDataMap<KeyType, ItemType>::Iterator it(aMap); it.More(); it.Next())
+ {
+ it.ChangeValue() *= 2;
+ }
+
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(10), 2.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(20), 4.0);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(30), 6.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, StlIterator)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap;
+
+ // Add elements
+ aMap.Add(10, 1.0);
+ aMap.Add(20, 2.0);
+ aMap.Add(30, 3.0);
+
+ // Use STL-style iterator
+ Standard_Boolean found1 = Standard_False;
+ Standard_Boolean found2 = Standard_False;
+ Standard_Boolean found3 = Standard_False;
+ Standard_Size count = 0;
+
+ for (auto it = aMap.begin(); it != aMap.end(); ++it, ++count)
+ {
+ if (*it == 1.0)
+ found1 = Standard_True;
+ else if (*it == 2.0)
+ found2 = Standard_True;
+ else if (*it == 3.0)
+ found3 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found1);
+ EXPECT_TRUE(found2);
+ EXPECT_TRUE(found3);
+
+ // Test const iterator
+ count = 0;
+ found1 = Standard_False;
+ found2 = Standard_False;
+ found3 = Standard_False;
+
+ for (auto it = aMap.cbegin(); it != aMap.cend(); ++it, ++count)
+ {
+ if (*it == 1.0)
+ found1 = Standard_True;
+ else if (*it == 2.0)
+ found2 = Standard_True;
+ else if (*it == 3.0)
+ found3 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found1);
+ EXPECT_TRUE(found2);
+ EXPECT_TRUE(found3);
+}
+
+TEST(NCollection_IndexedDataMapTest, StringKeys)
+{
+ // Test with string keys
+ NCollection_IndexedDataMap<TCollection_AsciiString, ItemType> aStringMap;
+
+ // Add string keys
+ Standard_Integer index1 = aStringMap.Add(TCollection_AsciiString("First"), 1.0);
+ Standard_Integer index2 = aStringMap.Add(TCollection_AsciiString("Second"), 2.0);
+ Standard_Integer index3 = aStringMap.Add(TCollection_AsciiString("Third"), 3.0);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+
+ // Find by key
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("First")), 1);
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("Second")), 2);
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("Third")), 3);
+
+ // Find by index
+ EXPECT_TRUE(aStringMap.FindKey(1).IsEqual("First"));
+ EXPECT_TRUE(aStringMap.FindKey(2).IsEqual("Second"));
+ EXPECT_TRUE(aStringMap.FindKey(3).IsEqual("Third"));
+
+ // Find values
+ EXPECT_DOUBLE_EQ(aStringMap.FindFromKey(TCollection_AsciiString("First")), 1.0);
+ EXPECT_DOUBLE_EQ(aStringMap.FindFromKey(TCollection_AsciiString("Second")), 2.0);
+ EXPECT_DOUBLE_EQ(aStringMap.FindFromKey(TCollection_AsciiString("Third")), 3.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, ComplexKeyAndValue)
+{
+ // Create map with custom key and hasher
+ NCollection_IndexedDataMap<TestKey, TestItem> aComplexMap;
+
+ // Add complex keys and values
+ TestKey key1(1, "One");
+ TestKey key2(2, "Two");
+ TestKey key3(3, "Three");
+
+ TestItem item1(1.1, "Item One");
+ TestItem item2(2.2, "Item Two");
+ TestItem item3(3.3, "Item Three");
+
+ Standard_Integer index1 = aComplexMap.Add(key1, item1);
+ Standard_Integer index2 = aComplexMap.Add(key2, item2);
+ Standard_Integer index3 = aComplexMap.Add(key3, item3);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+
+ // Find by key
+ EXPECT_EQ(aComplexMap.FindIndex(key1), 1);
+ EXPECT_EQ(aComplexMap.FindIndex(key2), 2);
+ EXPECT_EQ(aComplexMap.FindIndex(key3), 3);
+
+ // Find by index
+ EXPECT_EQ(aComplexMap.FindKey(1).GetId(), 1);
+ EXPECT_EQ(aComplexMap.FindKey(2).GetId(), 2);
+ EXPECT_EQ(aComplexMap.FindKey(3).GetId(), 3);
+
+ // Find values
+ EXPECT_DOUBLE_EQ(aComplexMap.FindFromKey(key1).GetValue(), 1.1);
+ EXPECT_DOUBLE_EQ(aComplexMap.FindFromKey(key2).GetValue(), 2.2);
+ EXPECT_DOUBLE_EQ(aComplexMap.FindFromKey(key3).GetValue(), 3.3);
+
+ // Test contains
+ EXPECT_TRUE(aComplexMap.Contains(TestKey(1, "One")));
+ EXPECT_FALSE(aComplexMap.Contains(TestKey(4, "Four")));
+
+ // Test value modification
+ aComplexMap.ChangeFromKey(key1).SetValue(1.5);
+ EXPECT_DOUBLE_EQ(aComplexMap.FindFromKey(key1).GetValue(), 1.5);
+}
+
+TEST(NCollection_IndexedDataMapTest, Exchange)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap1;
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap2;
+
+ // Add elements to first map
+ aMap1.Add(10, 1.0);
+ aMap1.Add(20, 2.0);
+
+ // Add different elements to second map
+ aMap2.Add(30, 3.0);
+ aMap2.Add(40, 4.0);
+ aMap2.Add(50, 5.0);
+
+ // Exchange maps
+ aMap1.Exchange(aMap2);
+
+ // Check that maps are exchanged
+ EXPECT_EQ(aMap1.Extent(), 3);
+ EXPECT_TRUE(aMap1.Contains(30));
+ EXPECT_TRUE(aMap1.Contains(40));
+ EXPECT_TRUE(aMap1.Contains(50));
+ EXPECT_DOUBLE_EQ(aMap1.FindFromKey(30), 3.0);
+ EXPECT_DOUBLE_EQ(aMap1.FindFromKey(40), 4.0);
+ EXPECT_DOUBLE_EQ(aMap1.FindFromKey(50), 5.0);
+
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(10), 1.0);
+ EXPECT_DOUBLE_EQ(aMap2.FindFromKey(20), 2.0);
+}
+
+TEST(NCollection_IndexedDataMapTest, ReSize)
+{
+ NCollection_IndexedDataMap<KeyType, ItemType> aMap(3); // Start with small bucket count
+
+ // Add many elements to trigger resize
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ aMap.Add(i, static_cast<Standard_Real>(i) / 10.0);
+ }
+
+ // Verify all elements are present
+ EXPECT_EQ(aMap.Extent(), 100);
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ EXPECT_TRUE(aMap.Contains(i));
+ EXPECT_EQ(aMap.FindIndex(i), i);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(i), static_cast<Standard_Real>(i) / 10.0);
+ }
+
+ // Explicitly resize
+ aMap.ReSize(200);
+
+ // Check that elements are still accessible
+ EXPECT_EQ(aMap.Extent(), 100);
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ EXPECT_TRUE(aMap.Contains(i));
+ EXPECT_EQ(aMap.FindIndex(i), i);
+ EXPECT_DOUBLE_EQ(aMap.FindFromKey(i), static_cast<Standard_Real>(i) / 10.0);
+ }
+}
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_IndexedMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <gtest/gtest.h>
+
+// Basic test type for the IndexedMap
+typedef Standard_Integer KeyType;
+
+// Custom class for testing complex keys
+class TestKey
+{
+public:
+ TestKey(int id = 0, const char* name = "")
+ : myId(id),
+ myName(name)
+ {
+ }
+
+ bool operator==(const TestKey& other) const
+ {
+ return myId == other.myId && myName == other.myName;
+ }
+
+ int GetId() const { return myId; }
+
+ const std::string& GetName() const { return myName; }
+
+private:
+ int myId;
+ std::string myName;
+};
+
+// Hasher for TestKey
+struct TestKeyHasher
+{
+ size_t operator()(const TestKey& theKey) const
+ {
+ // Combine the hash of the id and name
+ size_t aCombination[2] = {std::hash<int>()(theKey.GetId()),
+ std::hash<std::string>()(theKey.GetName())};
+
+ return opencascade::hashBytes(aCombination, sizeof(aCombination));
+ }
+
+ Standard_Boolean operator()(const TestKey& theKey1, const TestKey& theKey2) const
+ {
+ return theKey1 == theKey2;
+ }
+};
+
+TEST(NCollection_IndexedMapTest, DefaultConstructor)
+{
+ // Test default constructor
+ NCollection_IndexedMap<KeyType> aMap;
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+ EXPECT_EQ(aMap.Size(), 0);
+}
+
+TEST(NCollection_IndexedMapTest, BasicAddFind)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Test adding elements
+ Standard_Integer index1 = aMap.Add(10);
+ Standard_Integer index2 = aMap.Add(20);
+ Standard_Integer index3 = aMap.Add(30);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Test finding elements by key
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 3);
+
+ // Test finding keys by index
+ EXPECT_EQ(aMap.FindKey(1), 10);
+ EXPECT_EQ(aMap.FindKey(2), 20);
+ EXPECT_EQ(aMap.FindKey(3), 30);
+
+ // Test operator()
+ EXPECT_EQ(aMap(1), 10);
+ EXPECT_EQ(aMap(2), 20);
+ EXPECT_EQ(aMap(3), 30);
+
+ // Test Contains
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+ EXPECT_FALSE(aMap.Contains(40));
+}
+
+TEST(NCollection_IndexedMapTest, DuplicateKey)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add initial elements
+ Standard_Integer index1 = aMap.Add(10);
+ Standard_Integer index2 = aMap.Add(20);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+
+ // Try to add a duplicate - should return the existing index
+ Standard_Integer indexDup = aMap.Add(10);
+ EXPECT_EQ(indexDup, 1);
+ EXPECT_EQ(aMap.Extent(), 2); // Size should not change
+}
+
+TEST(NCollection_IndexedMapTest, RemoveLast)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Remove the last element
+ aMap.RemoveLast();
+
+ EXPECT_EQ(aMap.Extent(), 2);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_FALSE(aMap.Contains(30));
+
+ // Check indices - they should still be sequential
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+}
+
+TEST(NCollection_IndexedMapTest, RemoveFromIndex)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+ aMap.Add(40);
+
+ // Remove element at index 2
+ aMap.RemoveFromIndex(2);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20)); // Removed
+ EXPECT_TRUE(aMap.Contains(30));
+ EXPECT_TRUE(aMap.Contains(40));
+
+ // Test how the indices were rearranged
+ // Index 2 should now contain what was previously at the last position
+ EXPECT_EQ(aMap.FindKey(2), 40); // Last element moved to position 2
+ EXPECT_EQ(aMap.FindKey(1), 10); // First element unchanged
+ EXPECT_EQ(aMap.FindKey(3), 30); // Third element unchanged
+}
+
+TEST(NCollection_IndexedMapTest, RemoveKey)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Remove by key
+ bool removed = aMap.RemoveKey(20);
+
+ EXPECT_TRUE(removed);
+ EXPECT_EQ(aMap.Extent(), 2);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // Try to remove non-existent key
+ removed = aMap.RemoveKey(50);
+ EXPECT_FALSE(removed);
+ EXPECT_EQ(aMap.Extent(), 2);
+}
+
+TEST(NCollection_IndexedMapTest, Substitute)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Substitute key at index 2
+ aMap.Substitute(2, 25);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(25));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // Check indices after substitution
+ EXPECT_EQ(aMap.FindIndex(10), 1);
+ EXPECT_EQ(aMap.FindIndex(25), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 3);
+
+ // Check keys
+ EXPECT_EQ(aMap.FindKey(1), 10);
+ EXPECT_EQ(aMap.FindKey(2), 25);
+ EXPECT_EQ(aMap.FindKey(3), 30);
+}
+
+TEST(NCollection_IndexedMapTest, Swap)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Swap elements at indices 1 and 3
+ aMap.Swap(1, 3);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Check that keys maintained their values
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // But indices are swapped
+ EXPECT_EQ(aMap.FindKey(1), 30);
+ EXPECT_EQ(aMap.FindKey(2), 20);
+ EXPECT_EQ(aMap.FindKey(3), 10);
+
+ EXPECT_EQ(aMap.FindIndex(10), 3);
+ EXPECT_EQ(aMap.FindIndex(20), 2);
+ EXPECT_EQ(aMap.FindIndex(30), 1);
+}
+
+TEST(NCollection_IndexedMapTest, Clear)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ EXPECT_EQ(aMap.Extent(), 3);
+
+ // Clear the map
+ aMap.Clear();
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(aMap.Extent(), 0);
+
+ // Ensure we can add elements again
+ Standard_Integer index1 = aMap.Add(40);
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(aMap.Extent(), 1);
+}
+
+TEST(NCollection_IndexedMapTest, CopyConstructor)
+{
+ NCollection_IndexedMap<KeyType> aMap1;
+
+ // Add elements to first map
+ aMap1.Add(10);
+ aMap1.Add(20);
+ aMap1.Add(30);
+
+ // Create a copy
+ NCollection_IndexedMap<KeyType> aMap2(aMap1);
+
+ // Check that copy has the same elements
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_TRUE(aMap2.Contains(30));
+
+ // Check indices
+ EXPECT_EQ(aMap2.FindIndex(10), 1);
+ EXPECT_EQ(aMap2.FindIndex(20), 2);
+ EXPECT_EQ(aMap2.FindIndex(30), 3);
+
+ // Modify original to ensure deep copy
+ aMap1.Add(40);
+ EXPECT_EQ(aMap1.Extent(), 4);
+ EXPECT_EQ(aMap2.Extent(), 3);
+ EXPECT_FALSE(aMap2.Contains(40));
+}
+
+TEST(NCollection_IndexedMapTest, AssignmentOperator)
+{
+ NCollection_IndexedMap<KeyType> aMap1;
+ NCollection_IndexedMap<KeyType> aMap2;
+
+ // Add elements to first map
+ aMap1.Add(10);
+ aMap1.Add(20);
+
+ // Add different elements to second map
+ aMap2.Add(30);
+ aMap2.Add(40);
+ aMap2.Add(50);
+
+ // Assign first to second
+ aMap2 = aMap1;
+
+ // Check that second map now matches first
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_FALSE(aMap2.Contains(30));
+ EXPECT_FALSE(aMap2.Contains(40));
+ EXPECT_FALSE(aMap2.Contains(50));
+}
+
+TEST(NCollection_IndexedMapTest, Iterator)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Use iterator to check all elements
+ Standard_Boolean found10 = Standard_False;
+ Standard_Boolean found20 = Standard_False;
+ Standard_Boolean found30 = Standard_False;
+ Standard_Size count = 0;
+
+ for (NCollection_IndexedMap<KeyType>::Iterator it(aMap); it.More(); it.Next(), ++count)
+ {
+ const KeyType& key = it.Value();
+ if (key == 10)
+ found10 = Standard_True;
+ else if (key == 20)
+ found20 = Standard_True;
+ else if (key == 30)
+ found30 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found10);
+ EXPECT_TRUE(found20);
+ EXPECT_TRUE(found30);
+}
+
+TEST(NCollection_IndexedMapTest, StlIterator)
+{
+ NCollection_IndexedMap<KeyType> aMap;
+
+ // Add elements
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Use STL-style iterator
+ Standard_Boolean found10 = Standard_False;
+ Standard_Boolean found20 = Standard_False;
+ Standard_Boolean found30 = Standard_False;
+ Standard_Size count = 0;
+
+ for (auto it = aMap.cbegin(); it != aMap.cend(); ++it, ++count)
+ {
+ if (*it == 10)
+ found10 = Standard_True;
+ else if (*it == 20)
+ found20 = Standard_True;
+ else if (*it == 30)
+ found30 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 3);
+ EXPECT_TRUE(found10);
+ EXPECT_TRUE(found20);
+ EXPECT_TRUE(found30);
+}
+
+TEST(NCollection_IndexedMapTest, StringKeys)
+{
+ // Test with string keys
+ NCollection_IndexedMap<TCollection_AsciiString> aStringMap;
+
+ // Add string keys
+ Standard_Integer index1 = aStringMap.Add(TCollection_AsciiString("First"));
+ Standard_Integer index2 = aStringMap.Add(TCollection_AsciiString("Second"));
+ Standard_Integer index3 = aStringMap.Add(TCollection_AsciiString("Third"));
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+
+ // Find by key
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("First")), 1);
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("Second")), 2);
+ EXPECT_EQ(aStringMap.FindIndex(TCollection_AsciiString("Third")), 3);
+
+ // Find by index
+ EXPECT_TRUE(aStringMap.FindKey(1).IsEqual("First"));
+ EXPECT_TRUE(aStringMap.FindKey(2).IsEqual("Second"));
+ EXPECT_TRUE(aStringMap.FindKey(3).IsEqual("Third"));
+}
+
+TEST(NCollection_IndexedMapTest, ComplexKeys)
+{
+ // Create map with custom key and hasher
+ NCollection_IndexedMap<TestKey, TestKeyHasher> aComplexMap;
+
+ // Add complex keys
+ TestKey key1(1, "One");
+ TestKey key2(2, "Two");
+ TestKey key3(3, "Three");
+
+ Standard_Integer index1 = aComplexMap.Add(key1);
+ Standard_Integer index2 = aComplexMap.Add(key2);
+ Standard_Integer index3 = aComplexMap.Add(key3);
+
+ EXPECT_EQ(index1, 1);
+ EXPECT_EQ(index2, 2);
+ EXPECT_EQ(index3, 3);
+
+ // Find by key
+ EXPECT_EQ(aComplexMap.FindIndex(key1), 1);
+ EXPECT_EQ(aComplexMap.FindIndex(key2), 2);
+ EXPECT_EQ(aComplexMap.FindIndex(key3), 3);
+
+ // Find by index
+ EXPECT_EQ(aComplexMap.FindKey(1).GetId(), 1);
+ EXPECT_EQ(aComplexMap.FindKey(2).GetId(), 2);
+ EXPECT_EQ(aComplexMap.FindKey(3).GetId(), 3);
+
+ // Test contains
+ EXPECT_TRUE(aComplexMap.Contains(TestKey(1, "One")));
+ EXPECT_FALSE(aComplexMap.Contains(TestKey(4, "Four")));
+}
+
+TEST(NCollection_IndexedMapTest, Exchange)
+{
+ NCollection_IndexedMap<KeyType> aMap1;
+ NCollection_IndexedMap<KeyType> aMap2;
+
+ // Add elements to first map
+ aMap1.Add(10);
+ aMap1.Add(20);
+
+ // Add different elements to second map
+ aMap2.Add(30);
+ aMap2.Add(40);
+ aMap2.Add(50);
+
+ // Exchange maps
+ aMap1.Exchange(aMap2);
+
+ // Check that maps are exchanged
+ EXPECT_EQ(aMap1.Extent(), 3);
+ EXPECT_TRUE(aMap1.Contains(30));
+ EXPECT_TRUE(aMap1.Contains(40));
+ EXPECT_TRUE(aMap1.Contains(50));
+
+ EXPECT_EQ(aMap2.Extent(), 2);
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+}
+
+TEST(NCollection_IndexedMapTest, ReSize)
+{
+ NCollection_IndexedMap<KeyType> aMap(3); // Start with small bucket count
+
+ // Add many elements to trigger resize
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ aMap.Add(i);
+ }
+
+ // Verify all elements are present
+ EXPECT_EQ(aMap.Extent(), 100);
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ EXPECT_TRUE(aMap.Contains(i));
+ EXPECT_EQ(aMap.FindIndex(i), i);
+ EXPECT_EQ(aMap.FindKey(i), i);
+ }
+
+ // Explicitly resize
+ aMap.ReSize(200);
+
+ // Check that elements are still accessible
+ EXPECT_EQ(aMap.Extent(), 100);
+ for (Standard_Integer i = 1; i <= 100; ++i)
+ {
+ EXPECT_TRUE(aMap.Contains(i));
+ EXPECT_EQ(aMap.FindIndex(i), i);
+ EXPECT_EQ(aMap.FindKey(i), i);
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_List.hxx>
+#include <Standard_Integer.hxx>
+
+#include <gtest/gtest.h>
+
+// Test fixture for NCollection_List tests
+class NCollection_ListTest : public testing::Test
+{
+protected:
+ void SetUp() override {}
+
+ void TearDown() override {}
+};
+
+TEST_F(NCollection_ListTest, DefaultConstructor)
+{
+ // Default constructor should create an empty list
+ NCollection_List<Standard_Integer> aList;
+ EXPECT_TRUE(aList.IsEmpty());
+ EXPECT_EQ(0, aList.Size());
+ EXPECT_EQ(0, aList.Extent());
+}
+
+TEST_F(NCollection_ListTest, Append)
+{
+ NCollection_List<Standard_Integer> aList;
+
+ // Test Append method
+ EXPECT_EQ(10, aList.Append(10));
+ EXPECT_EQ(20, aList.Append(20));
+ EXPECT_EQ(30, aList.Append(30));
+
+ EXPECT_FALSE(aList.IsEmpty());
+ EXPECT_EQ(3, aList.Size());
+
+ // Test First and Last access
+ EXPECT_EQ(10, aList.First());
+ EXPECT_EQ(30, aList.Last());
+}
+
+TEST_F(NCollection_ListTest, Prepend)
+{
+ NCollection_List<Standard_Integer> aList;
+
+ // Test Prepend method
+ EXPECT_EQ(30, aList.Prepend(30));
+ EXPECT_EQ(20, aList.Prepend(20));
+ EXPECT_EQ(10, aList.Prepend(10));
+
+ EXPECT_FALSE(aList.IsEmpty());
+ EXPECT_EQ(3, aList.Size());
+
+ // Test First and Last access
+ EXPECT_EQ(10, aList.First());
+ EXPECT_EQ(30, aList.Last());
+}
+
+TEST_F(NCollection_ListTest, IteratorAccess)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test iteration using OCCT iterator
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+ Standard_Integer expectedValues[] = {10, 20, 30};
+ Standard_Integer index = 0;
+
+ for (; it.More(); it.Next(), index++)
+ {
+ EXPECT_EQ(expectedValues[index], it.Value());
+ }
+ EXPECT_EQ(3, index); // Ensure we iterated through all elements
+}
+
+TEST_F(NCollection_ListTest, STLIterators)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test STL-compatible iterators
+ Standard_Integer expectedValues[] = {10, 20, 30};
+ Standard_Integer index = 0;
+
+ for (auto it = aList.begin(); it != aList.end(); ++it, ++index)
+ {
+ EXPECT_EQ(expectedValues[index], *it);
+ }
+ EXPECT_EQ(3, index);
+
+ // Test range-based for loop
+ index = 0;
+ for (const auto& value : aList)
+ {
+ EXPECT_EQ(expectedValues[index++], value);
+ }
+ EXPECT_EQ(3, index);
+}
+
+TEST_F(NCollection_ListTest, RemoveFirst)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test RemoveFirst
+ aList.RemoveFirst();
+ EXPECT_EQ(2, aList.Size());
+ EXPECT_EQ(20, aList.First());
+
+ aList.RemoveFirst();
+ EXPECT_EQ(1, aList.Size());
+ EXPECT_EQ(30, aList.First());
+
+ aList.RemoveFirst();
+ EXPECT_TRUE(aList.IsEmpty());
+}
+
+TEST_F(NCollection_ListTest, Remove)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test Remove with iterator
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+ it.Next(); // Point to second element (20)
+ aList.Remove(it); // Remove 20, iterator now points to 30
+
+ // Check the list after removal
+ EXPECT_EQ(2, aList.Size());
+ EXPECT_EQ(10, aList.First());
+ EXPECT_EQ(30, aList.Last());
+ EXPECT_EQ(30, it.Value()); // Iterator should now point to 30
+}
+
+TEST_F(NCollection_ListTest, RemoveByValue)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(10); // Add duplicate
+ aList.Append(30);
+
+ // Test removing by value - should remove the first occurrence only
+ bool removed = aList.Remove(10);
+ EXPECT_TRUE(removed);
+ EXPECT_EQ(3, aList.Size());
+ EXPECT_EQ(20, aList.First());
+
+ // Try to remove a non-existent value
+ removed = aList.Remove(50);
+ EXPECT_FALSE(removed);
+ EXPECT_EQ(3, aList.Size());
+
+ // Remove the second occurrence of 10
+ removed = aList.Remove(10);
+ EXPECT_TRUE(removed);
+ EXPECT_EQ(2, aList.Size());
+
+ // Check final list state
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+ EXPECT_EQ(20, it.Value());
+ it.Next();
+ EXPECT_EQ(30, it.Value());
+}
+
+TEST_F(NCollection_ListTest, Clear)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test Clear
+ aList.Clear();
+ EXPECT_TRUE(aList.IsEmpty());
+ EXPECT_EQ(0, aList.Size());
+}
+
+TEST_F(NCollection_ListTest, Assignment)
+{
+ NCollection_List<Standard_Integer> aList1;
+ aList1.Append(10);
+ aList1.Append(20);
+ aList1.Append(30);
+
+ // Test assignment operator
+ NCollection_List<Standard_Integer> aList2;
+ aList2 = aList1;
+
+ // Check both lists have the same content
+ EXPECT_EQ(aList1.Size(), aList2.Size());
+
+ NCollection_List<Standard_Integer>::Iterator it1(aList1);
+ NCollection_List<Standard_Integer>::Iterator it2(aList2);
+
+ for (; it1.More() && it2.More(); it1.Next(), it2.Next())
+ {
+ EXPECT_EQ(it1.Value(), it2.Value());
+ }
+
+ // Modify original to ensure deep copy
+ aList1.First() = 100;
+ EXPECT_EQ(100, aList1.First());
+ EXPECT_EQ(10, aList2.First());
+}
+
+TEST_F(NCollection_ListTest, AssignMethod)
+{
+ NCollection_List<Standard_Integer> aList1;
+ aList1.Append(10);
+ aList1.Append(20);
+ aList1.Append(30);
+
+ // Test Assign method
+ NCollection_List<Standard_Integer> aList2;
+ aList2.Append(40); // Add some initial content
+ aList2.Assign(aList1); // This should replace aList2's content
+
+ EXPECT_EQ(aList1.Size(), aList2.Size());
+
+ // Check values
+ NCollection_List<Standard_Integer>::Iterator it2(aList2);
+ EXPECT_EQ(10, it2.Value());
+ it2.Next();
+ EXPECT_EQ(20, it2.Value());
+ it2.Next();
+ EXPECT_EQ(30, it2.Value());
+}
+
+TEST_F(NCollection_ListTest, AppendList)
+{
+ NCollection_List<Standard_Integer> aList1;
+ aList1.Append(10);
+ aList1.Append(20);
+
+ NCollection_List<Standard_Integer> aList2;
+ aList2.Append(30);
+ aList2.Append(40);
+
+ // Test Append(List)
+ aList1.Append(aList2);
+
+ EXPECT_EQ(4, aList1.Size());
+ EXPECT_TRUE(aList2.IsEmpty()); // aList2 should be cleared
+
+ // Check values in aList1
+ NCollection_List<Standard_Integer>::Iterator it(aList1);
+ EXPECT_EQ(10, it.Value());
+ it.Next();
+ EXPECT_EQ(20, it.Value());
+ it.Next();
+ EXPECT_EQ(30, it.Value());
+ it.Next();
+ EXPECT_EQ(40, it.Value());
+}
+
+TEST_F(NCollection_ListTest, PrependList)
+{
+ NCollection_List<Standard_Integer> aList1;
+ aList1.Append(30);
+ aList1.Append(40);
+
+ NCollection_List<Standard_Integer> aList2;
+ aList2.Append(10);
+ aList2.Append(20);
+
+ // Test Prepend(List)
+ aList1.Prepend(aList2);
+
+ EXPECT_EQ(4, aList1.Size());
+ EXPECT_TRUE(aList2.IsEmpty()); // aList2 should be cleared
+
+ // Check values in aList1
+ NCollection_List<Standard_Integer>::Iterator it(aList1);
+ EXPECT_EQ(10, it.Value());
+ it.Next();
+ EXPECT_EQ(20, it.Value());
+ it.Next();
+ EXPECT_EQ(30, it.Value());
+ it.Next();
+ EXPECT_EQ(40, it.Value());
+}
+
+TEST_F(NCollection_ListTest, InsertBefore)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(30);
+
+ // Get iterator to second element
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+ it.Next();
+
+ // Insert before the second element
+ EXPECT_EQ(20, aList.InsertBefore(20, it));
+
+ // Check the list
+ EXPECT_EQ(3, aList.Size());
+
+ NCollection_List<Standard_Integer>::Iterator checkIt(aList);
+ EXPECT_EQ(10, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(20, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(30, checkIt.Value());
+}
+
+TEST_F(NCollection_ListTest, InsertAfter)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(30);
+
+ // Get iterator to first element
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+
+ // Insert after the first element
+ EXPECT_EQ(20, aList.InsertAfter(20, it));
+
+ // Check the list
+ EXPECT_EQ(3, aList.Size());
+
+ NCollection_List<Standard_Integer>::Iterator checkIt(aList);
+ EXPECT_EQ(10, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(20, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(30, checkIt.Value());
+}
+
+TEST_F(NCollection_ListTest, InsertList)
+{
+ NCollection_List<Standard_Integer> aList1;
+ aList1.Append(10);
+ aList1.Append(40);
+
+ NCollection_List<Standard_Integer> aList2;
+ aList2.Append(20);
+ aList2.Append(30);
+
+ // Get iterator to the second element in aList1
+ NCollection_List<Standard_Integer>::Iterator it(aList1);
+ it.Next();
+
+ // Insert aList2 before the second element in aList1
+ aList1.InsertBefore(aList2, it);
+
+ EXPECT_EQ(4, aList1.Size());
+ EXPECT_TRUE(aList2.IsEmpty());
+
+ // Check the resulting list
+ NCollection_List<Standard_Integer>::Iterator checkIt(aList1);
+ EXPECT_EQ(10, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(20, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(30, checkIt.Value());
+ checkIt.Next();
+ EXPECT_EQ(40, checkIt.Value());
+}
+
+TEST_F(NCollection_ListTest, Reverse)
+{
+ NCollection_List<Standard_Integer> aList;
+ aList.Append(10);
+ aList.Append(20);
+ aList.Append(30);
+
+ // Test Reverse
+ aList.Reverse();
+
+ // Check the reversed list
+ EXPECT_EQ(30, aList.First());
+ EXPECT_EQ(10, aList.Last());
+
+ NCollection_List<Standard_Integer>::Iterator it(aList);
+ EXPECT_EQ(30, it.Value());
+ it.Next();
+ EXPECT_EQ(20, it.Value());
+ it.Next();
+ EXPECT_EQ(10, it.Value());
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_LocalArray.hxx>
+
+#include <gtest/gtest.h>
+
+// Test default constructor and initial state
+TEST(NCollection_LocalArrayTest, DefaultConstructor)
+{
+ NCollection_LocalArray<int> array;
+ EXPECT_EQ(0, array.Size());
+}
+
+// Test constructor with size
+TEST(NCollection_LocalArrayTest, ConstructorWithSize)
+{
+ const size_t size = 100;
+ NCollection_LocalArray<int> array(size);
+ EXPECT_EQ(size, array.Size());
+}
+
+// Test allocation with small size (using buffer)
+TEST(NCollection_LocalArrayTest, SmallSizeAllocation)
+{
+ const size_t size = 10; // Less than MAX_ARRAY_SIZE
+ NCollection_LocalArray<int, 1024> array(size);
+ EXPECT_EQ(size, array.Size());
+
+ // Populate array
+ for (size_t i = 0; i < size; ++i)
+ {
+ array[i] = static_cast<int>(i * 10);
+ }
+
+ // Verify array contents
+ for (size_t i = 0; i < size; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 10), array[i]);
+ }
+}
+
+// Test allocation with large size (heap allocation)
+TEST(NCollection_LocalArrayTest, LargeSizeAllocation)
+{
+ const size_t size = 2000; // Greater than default MAX_ARRAY_SIZE of 1024
+ NCollection_LocalArray<int> array(size);
+ EXPECT_EQ(size, array.Size());
+
+ // Populate array
+ for (size_t i = 0; i < size; ++i)
+ {
+ array[i] = static_cast<int>(i * 10);
+ }
+
+ // Verify array contents
+ for (size_t i = 0; i < size; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 10), array[i]);
+ }
+}
+
+// Test reallocation
+TEST(NCollection_LocalArrayTest, Reallocation)
+{
+ NCollection_LocalArray<int> array(10);
+ EXPECT_EQ(10, array.Size());
+
+ // Populate array
+ for (size_t i = 0; i < 10; ++i)
+ {
+ array[i] = static_cast<int>(i);
+ }
+
+ // Reallocate to larger size
+ array.Allocate(50);
+ EXPECT_EQ(50, array.Size());
+
+ // Populate new elements
+ for (size_t i = 0; i < 50; ++i)
+ {
+ array[i] = static_cast<int>(i * 2);
+ }
+
+ // Verify array contents
+ for (size_t i = 0; i < 50; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 2), array[i]);
+ }
+
+ // Reallocate to smaller size
+ array.Allocate(5);
+ EXPECT_EQ(5, array.Size());
+
+ // Verify array contents
+ for (size_t i = 0; i < 5; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 2), array[i]);
+ }
+}
+
+// Test with custom MAX_ARRAY_SIZE
+TEST(NCollection_LocalArrayTest, CustomMaxArraySize)
+{
+ const size_t customMaxSize = 50;
+
+ // Test with size less than custom max
+ NCollection_LocalArray<int, customMaxSize> smallArray(20);
+ EXPECT_EQ(20, smallArray.Size());
+
+ // Test with size greater than custom max
+ NCollection_LocalArray<int, customMaxSize> largeArray(100);
+ EXPECT_EQ(100, largeArray.Size());
+}
+
+// Test with custom type
+struct TestStruct
+{
+ int a;
+ double b;
+
+ bool operator==(const TestStruct& other) const { return a == other.a && b == other.b; }
+};
+
+TEST(NCollection_LocalArrayTest, CustomType)
+{
+ NCollection_LocalArray<TestStruct> array(5);
+ EXPECT_EQ(5, array.Size());
+
+ TestStruct ts{10, 3.14};
+
+ // Set and retrieve values
+ array[0] = ts;
+ EXPECT_TRUE(ts == array[0]);
+}
+
+// Test transition from stack to heap allocation and back
+TEST(NCollection_LocalArrayTest, TransitionStackToHeap)
+{
+ const int maxSize = 10;
+ NCollection_LocalArray<int, maxSize> array;
+
+ // Initially allocate in stack buffer
+ array.Allocate(5);
+ for (size_t i = 0; i < 5; ++i)
+ {
+ array[i] = static_cast<int>(i);
+ }
+
+ // Verify array contents
+ for (size_t i = 0; i < 5; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i), array[i]);
+ }
+
+ // Now allocate larger size, forcing heap allocation
+ array.Allocate(maxSize + 10);
+ for (size_t i = 0; i < maxSize + 10; ++i)
+ {
+ array[i] = static_cast<int>(i * 3);
+ }
+
+ // Verify heap allocation
+ for (size_t i = 0; i < maxSize + 10; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 3), array[i]);
+ }
+
+ // Now go back to stack allocation
+ array.Allocate(maxSize - 5);
+ for (size_t i = 0; i < maxSize - 5; ++i)
+ {
+ array[i] = static_cast<int>(i * 5);
+ }
+
+ // Verify stack allocation again
+ for (size_t i = 0; i < maxSize - 5; ++i)
+ {
+ EXPECT_EQ(static_cast<int>(i * 5), array[i]);
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_Map.hxx>
+#include <Standard_Integer.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <gtest/gtest.h>
+
+TEST(NCollection_MapTest, DefaultConstructor)
+{
+ // Default constructor should create an empty map
+ NCollection_Map<Standard_Integer> aMap(101);
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(0, aMap.Size());
+ EXPECT_EQ(0, aMap.Extent());
+ EXPECT_EQ(101, aMap.NbBuckets());
+}
+
+TEST(NCollection_MapTest, ConstructorWithBuckets)
+{
+ // Constructor with number of buckets
+ const Standard_Integer nbBuckets = 100;
+ NCollection_Map<Standard_Integer> aMap(nbBuckets);
+
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(0, aMap.Size());
+ EXPECT_EQ(0, aMap.Extent());
+ EXPECT_EQ(nbBuckets, aMap.NbBuckets());
+}
+
+TEST(NCollection_MapTest, AddAndContains)
+{
+ NCollection_Map<Standard_Integer> aMap;
+
+ // Test Add method
+ EXPECT_TRUE(aMap.Add(10));
+ EXPECT_TRUE(aMap.Add(20));
+ EXPECT_TRUE(aMap.Add(30));
+
+ // Adding duplicates should return false
+ EXPECT_FALSE(aMap.Add(10));
+ EXPECT_FALSE(aMap.Add(20));
+
+ // Map size should account for unique elements only
+ EXPECT_EQ(3, aMap.Size());
+
+ // Test Contains
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(30));
+ EXPECT_FALSE(aMap.Contains(40));
+}
+
+TEST(NCollection_MapTest, Remove)
+{
+ NCollection_Map<Standard_Integer> aMap;
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Test Remove
+ EXPECT_TRUE(aMap.Remove(20));
+ EXPECT_EQ(2, aMap.Size());
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_TRUE(aMap.Contains(10));
+ EXPECT_TRUE(aMap.Contains(30));
+
+ // Try to remove non-existent element
+ EXPECT_FALSE(aMap.Remove(40));
+ EXPECT_EQ(2, aMap.Size());
+}
+
+TEST(NCollection_MapTest, Clear)
+{
+ NCollection_Map<Standard_Integer> aMap;
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ EXPECT_FALSE(aMap.IsEmpty());
+
+ // Test Clear
+ aMap.Clear();
+ EXPECT_TRUE(aMap.IsEmpty());
+ EXPECT_EQ(0, aMap.Size());
+ EXPECT_FALSE(aMap.Contains(10));
+ EXPECT_FALSE(aMap.Contains(20));
+ EXPECT_FALSE(aMap.Contains(30));
+}
+
+TEST(NCollection_MapTest, Assignment)
+{
+ NCollection_Map<Standard_Integer> aMap1;
+ aMap1.Add(10);
+ aMap1.Add(20);
+ aMap1.Add(30);
+
+ // Test assignment operator
+ NCollection_Map<Standard_Integer> aMap2;
+ aMap2 = aMap1;
+
+ // Check both maps have the same content
+ EXPECT_EQ(aMap1.Size(), aMap2.Size());
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_TRUE(aMap2.Contains(20));
+ EXPECT_TRUE(aMap2.Contains(30));
+
+ // Modify original map to ensure deep copy
+ aMap1.Add(40);
+ aMap1.Remove(10);
+
+ EXPECT_EQ(3, aMap1.Size());
+ EXPECT_EQ(3, aMap2.Size());
+ EXPECT_TRUE(aMap2.Contains(10));
+ EXPECT_FALSE(aMap1.Contains(10));
+ EXPECT_TRUE(aMap1.Contains(40));
+ EXPECT_FALSE(aMap2.Contains(40));
+}
+
+TEST(NCollection_MapTest, IteratorAccess)
+{
+ NCollection_Map<Standard_Integer> aMap;
+ aMap.Add(10);
+ aMap.Add(20);
+ aMap.Add(30);
+
+ // Test iteration using OCCT iterator
+ NCollection_Map<Standard_Integer>::Iterator it(aMap);
+
+ // Create set to check all keys are visited
+ std::set<Standard_Integer> foundKeys;
+
+ for (; it.More(); it.Next())
+ {
+ foundKeys.insert(it.Value());
+ }
+
+ // Check all keys were visited
+ EXPECT_EQ(3, foundKeys.size());
+ EXPECT_TRUE(foundKeys.find(10) != foundKeys.end());
+ EXPECT_TRUE(foundKeys.find(20) != foundKeys.end());
+ EXPECT_TRUE(foundKeys.find(30) != foundKeys.end());
+}
+
+TEST(NCollection_MapTest, Resize)
+{
+ NCollection_Map<Standard_Integer> aMap(10);
+
+ // Add elements
+ for (Standard_Integer i = 0; i < 100; ++i)
+ {
+ aMap.Add(i);
+ }
+
+ // Check initial state
+ EXPECT_EQ(100, aMap.Size());
+
+ // Before resize, remember which elements are contained
+ std::vector<Standard_Integer> elements;
+ for (NCollection_Map<Standard_Integer>::Iterator it(aMap); it.More(); it.Next())
+ {
+ elements.push_back(it.Value());
+ }
+
+ // Test Resize
+ aMap.ReSize(200);
+
+ // Resize shouldn't change the map contents
+ EXPECT_EQ(100, aMap.Size());
+ for (const auto& element : elements)
+ {
+ EXPECT_TRUE(aMap.Contains(element));
+ }
+}
+
+TEST(NCollection_MapTest, ExhaustiveIterator)
+{
+ const int NUM_ELEMENTS = 1000;
+
+ // Create a map with many elements to test iterator efficiency
+ NCollection_Map<Standard_Integer> aMap;
+
+ // Add many elements
+ for (int i = 0; i < NUM_ELEMENTS; ++i)
+ {
+ aMap.Add(i);
+ }
+
+ EXPECT_EQ(NUM_ELEMENTS, aMap.Size());
+
+ // Count elements using iterator
+ int count = 0;
+ int sum = 0;
+ NCollection_Map<Standard_Integer>::Iterator it(aMap);
+ for (; it.More(); it.Next())
+ {
+ sum += it.Value();
+ count++;
+ }
+
+ EXPECT_EQ(NUM_ELEMENTS, count);
+
+ // Calculate expected sum: 0 + 1 + 2 + ... + (NUM_ELEMENTS-1)
+ int expectedSum = (NUM_ELEMENTS * (NUM_ELEMENTS - 1)) / 2;
+ EXPECT_EQ(expectedSum, sum);
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_Sequence.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <NCollection_BaseAllocator.hxx>
+
+#include <gtest/gtest.h>
+
+// Basic test type for the Sequence
+typedef Standard_Integer ItemType;
+
+// Custom class for testing complex types in the Sequence
+class TestClass
+{
+public:
+ TestClass(int id = 0, const char* name = "")
+ : myId(id),
+ myName(name)
+ {
+ }
+
+ int GetId() const { return myId; }
+
+ const char* GetName() const { return myName.c_str(); }
+
+ bool operator==(const TestClass& other) const
+ {
+ return (myId == other.myId && myName == other.myName);
+ }
+
+private:
+ int myId;
+ std::string myName;
+};
+
+TEST(NCollection_SequenceTest, BasicFunctions)
+{
+ // Test default constructor and initial state
+ NCollection_Sequence<ItemType> aSeq;
+ EXPECT_TRUE(aSeq.IsEmpty());
+ EXPECT_EQ(aSeq.Size(), 0);
+ EXPECT_EQ(aSeq.Length(), 0);
+
+ // Test Append
+ aSeq.Append(10);
+ aSeq.Append(20);
+ aSeq.Append(30);
+ EXPECT_EQ(aSeq.Size(), 3);
+ EXPECT_FALSE(aSeq.IsEmpty());
+
+ // Test access operations
+ EXPECT_EQ(aSeq(1), 10);
+ EXPECT_EQ(aSeq(2), 20);
+ EXPECT_EQ(aSeq(3), 30);
+ EXPECT_EQ(aSeq.First(), 10);
+ EXPECT_EQ(aSeq.Last(), 30);
+
+ // Test bounds
+ EXPECT_EQ(aSeq.Lower(), 1);
+ EXPECT_EQ(aSeq.Upper(), 3);
+}
+
+TEST(NCollection_SequenceTest, ModifyingOperations)
+{
+ NCollection_Sequence<ItemType> aSeq;
+
+ // Test Prepend
+ aSeq.Prepend(100);
+ aSeq.Prepend(200);
+ EXPECT_EQ(aSeq.Size(), 2);
+ EXPECT_EQ(aSeq.First(), 200);
+ EXPECT_EQ(aSeq.Last(), 100);
+
+ // Test SetValue
+ aSeq.SetValue(1, 210);
+ EXPECT_EQ(aSeq(1), 210);
+
+ // Test ChangeValue
+ aSeq.ChangeValue(2) = 110;
+ EXPECT_EQ(aSeq(2), 110);
+
+ // Test InsertBefore
+ aSeq.InsertBefore(1, 300);
+ EXPECT_EQ(aSeq.Size(), 3);
+ EXPECT_EQ(aSeq(1), 300);
+ EXPECT_EQ(aSeq(2), 210);
+ EXPECT_EQ(aSeq(3), 110);
+
+ // Test InsertAfter
+ aSeq.InsertAfter(2, 400);
+ EXPECT_EQ(aSeq.Size(), 4);
+ EXPECT_EQ(aSeq(1), 300);
+ EXPECT_EQ(aSeq(2), 210);
+ EXPECT_EQ(aSeq(3), 400);
+ EXPECT_EQ(aSeq(4), 110);
+
+ // Test Remove
+ aSeq.Remove(3);
+ EXPECT_EQ(aSeq.Size(), 3);
+ EXPECT_EQ(aSeq(1), 300);
+ EXPECT_EQ(aSeq(2), 210);
+ EXPECT_EQ(aSeq(3), 110);
+
+ // Test Remove with range
+ aSeq.Append(500);
+ aSeq.Append(600);
+ EXPECT_EQ(aSeq.Size(), 5);
+
+ aSeq.Remove(2, 4);
+ EXPECT_EQ(aSeq.Size(), 2);
+ EXPECT_EQ(aSeq(1), 300);
+ EXPECT_EQ(aSeq(2), 600);
+}
+
+TEST(NCollection_SequenceTest, IteratorFunctions)
+{
+ NCollection_Sequence<ItemType> aSeq;
+ aSeq.Append(10);
+ aSeq.Append(20);
+ aSeq.Append(30);
+
+ // Test Iterator
+ NCollection_Sequence<ItemType>::Iterator anIt(aSeq);
+
+ EXPECT_TRUE(anIt.More());
+ EXPECT_EQ(anIt.Value(), 10);
+ anIt.Next();
+
+ EXPECT_TRUE(anIt.More());
+ EXPECT_EQ(anIt.Value(), 20);
+ anIt.Next();
+
+ EXPECT_TRUE(anIt.More());
+ EXPECT_EQ(anIt.Value(), 30);
+ anIt.Next();
+
+ EXPECT_FALSE(anIt.More());
+
+ // Test value modification through iterator
+ NCollection_Sequence<ItemType>::Iterator aModIt(aSeq);
+ aModIt.ChangeValue() = 15;
+ aModIt.Next();
+ aModIt.ChangeValue() = 25;
+
+ EXPECT_EQ(aSeq(1), 15);
+ EXPECT_EQ(aSeq(2), 25);
+ EXPECT_EQ(aSeq(3), 30);
+
+ // Test STL-style iteration
+ int index = 0;
+ int expectedValues[] = {15, 25, 30};
+ for (const auto& item : aSeq)
+ {
+ EXPECT_EQ(item, expectedValues[index++]);
+ }
+ EXPECT_EQ(index, 3);
+}
+
+TEST(NCollection_SequenceTest, CopyAndAssignment)
+{
+ NCollection_Sequence<ItemType> aSeq1;
+ aSeq1.Append(10);
+ aSeq1.Append(20);
+ aSeq1.Append(30);
+
+ // Test copy constructor
+ NCollection_Sequence<ItemType> aSeq2(aSeq1);
+ EXPECT_EQ(aSeq2.Size(), 3);
+ EXPECT_EQ(aSeq2(1), 10);
+ EXPECT_EQ(aSeq2(2), 20);
+ EXPECT_EQ(aSeq2(3), 30);
+
+ // Test assignment operator
+ NCollection_Sequence<ItemType> aSeq3;
+ aSeq3 = aSeq1;
+ EXPECT_EQ(aSeq3.Size(), 3);
+ EXPECT_EQ(aSeq3(1), 10);
+ EXPECT_EQ(aSeq3(2), 20);
+ EXPECT_EQ(aSeq3(3), 30);
+
+ // Modify original and verify copies don't change
+ aSeq1.SetValue(2, 25);
+ EXPECT_EQ(aSeq1(2), 25);
+ EXPECT_EQ(aSeq2(2), 20);
+ EXPECT_EQ(aSeq3(2), 20);
+}
+
+TEST(NCollection_SequenceTest, CombiningSequences)
+{
+ NCollection_Sequence<ItemType> aSeq1;
+ aSeq1.Append(10);
+ aSeq1.Append(20);
+
+ NCollection_Sequence<ItemType> aSeq2;
+ aSeq2.Append(30);
+ aSeq2.Append(40);
+
+ // Test Append(Sequence)
+ NCollection_Sequence<ItemType> aSeq3(aSeq1);
+ aSeq3.Append(aSeq2);
+ EXPECT_EQ(aSeq3.Size(), 4);
+ EXPECT_EQ(aSeq3(1), 10);
+ EXPECT_EQ(aSeq3(2), 20);
+ EXPECT_EQ(aSeq3(3), 30);
+ EXPECT_EQ(aSeq3(4), 40);
+ EXPECT_TRUE(aSeq2.IsEmpty()); // Original sequence should be emptied
+
+ // Test Prepend(Sequence)
+ aSeq2.Append(50);
+ aSeq2.Append(60);
+
+ NCollection_Sequence<ItemType> aSeq4;
+ aSeq4.Append(70);
+ aSeq4.Prepend(aSeq2);
+
+ EXPECT_EQ(aSeq4.Size(), 3);
+ EXPECT_EQ(aSeq4(1), 50);
+ EXPECT_EQ(aSeq4(2), 60);
+ EXPECT_EQ(aSeq4(3), 70);
+ EXPECT_TRUE(aSeq2.IsEmpty()); // Original sequence should be emptied
+
+ // Test InsertAfter(Sequence)
+ aSeq2.Append(80);
+ aSeq2.Append(90);
+
+ NCollection_Sequence<ItemType> aSeq5;
+ aSeq5.Append(100);
+ aSeq5.Append(110);
+ aSeq5.InsertAfter(1, aSeq2);
+
+ EXPECT_EQ(aSeq5.Size(), 4);
+ EXPECT_EQ(aSeq5(1), 100);
+ EXPECT_EQ(aSeq5(2), 80);
+ EXPECT_EQ(aSeq5(3), 90);
+ EXPECT_EQ(aSeq5(4), 110);
+ EXPECT_TRUE(aSeq2.IsEmpty()); // Original sequence should be emptied
+}
+
+TEST(NCollection_SequenceTest, AdvancedOperations)
+{
+ NCollection_Sequence<ItemType> aSeq;
+ aSeq.Append(10);
+ aSeq.Append(20);
+ aSeq.Append(30);
+ aSeq.Append(40);
+ aSeq.Append(50);
+
+ // Test Exchange
+ aSeq.Exchange(2, 4);
+ EXPECT_EQ(aSeq(1), 10);
+ EXPECT_EQ(aSeq(2), 40);
+ EXPECT_EQ(aSeq(3), 30);
+ EXPECT_EQ(aSeq(4), 20);
+ EXPECT_EQ(aSeq(5), 50);
+
+ // Test Reverse
+ aSeq.Reverse();
+ EXPECT_EQ(aSeq(1), 50);
+ EXPECT_EQ(aSeq(2), 20);
+ EXPECT_EQ(aSeq(3), 30);
+ EXPECT_EQ(aSeq(4), 40);
+ EXPECT_EQ(aSeq(5), 10);
+
+ // Test Split
+ NCollection_Sequence<ItemType> aSeq2;
+ aSeq.Split(2, aSeq2);
+
+ EXPECT_EQ(aSeq.Size(), 1);
+ EXPECT_EQ(aSeq(1), 50);
+
+ EXPECT_EQ(aSeq2.Size(), 4);
+ EXPECT_EQ(aSeq2(1), 20);
+ EXPECT_EQ(aSeq2(2), 30);
+ EXPECT_EQ(aSeq2(3), 40);
+ EXPECT_EQ(aSeq2(4), 10);
+
+ // Test Clear
+ aSeq.Clear();
+ EXPECT_TRUE(aSeq.IsEmpty());
+ EXPECT_EQ(aSeq.Size(), 0);
+}
+
+TEST(NCollection_SequenceTest, ComplexTypeSequence)
+{
+ NCollection_Sequence<TestClass> aSeq;
+
+ TestClass a(1, "First");
+ TestClass b(2, "Second");
+ TestClass c(3, "Third");
+
+ // Test appending complex types
+ aSeq.Append(a);
+ aSeq.Append(b);
+ aSeq.Append(c);
+
+ EXPECT_EQ(aSeq.Size(), 3);
+ EXPECT_EQ(aSeq(1).GetId(), 1);
+ EXPECT_STREQ(aSeq(1).GetName(), "First");
+ EXPECT_EQ(aSeq(2).GetId(), 2);
+ EXPECT_STREQ(aSeq(2).GetName(), "Second");
+ EXPECT_EQ(aSeq(3).GetId(), 3);
+ EXPECT_STREQ(aSeq(3).GetName(), "Third");
+
+ // Test modifying complex types
+ aSeq.ChangeValue(2) = TestClass(22, "Modified");
+ EXPECT_EQ(aSeq(2).GetId(), 22);
+ EXPECT_STREQ(aSeq(2).GetName(), "Modified");
+
+ // Test erasing with complex type
+ aSeq.Remove(1);
+ EXPECT_EQ(aSeq.Size(), 2);
+ EXPECT_EQ(aSeq.First().GetId(), 22);
+}
+
+TEST(NCollection_SequenceTest, AllocatorTest)
+{
+ // Test with custom allocator
+ Handle(NCollection_BaseAllocator) aAlloc = new NCollection_IncAllocator();
+ NCollection_Sequence<ItemType> aSeq(aAlloc);
+
+ aSeq.Append(10);
+ aSeq.Append(20);
+ aSeq.Append(30);
+
+ EXPECT_EQ(aSeq.Size(), 3);
+ EXPECT_EQ(aSeq(1), 10);
+ EXPECT_EQ(aSeq(2), 20);
+ EXPECT_EQ(aSeq(3), 30);
+
+ // Test Clear with new allocator
+ Handle(NCollection_BaseAllocator) aAlloc2 = new NCollection_IncAllocator();
+ aSeq.Clear(aAlloc2);
+ EXPECT_TRUE(aSeq.IsEmpty());
+
+ // Add new items to verify the new allocator is working
+ aSeq.Append(40);
+ EXPECT_EQ(aSeq(1), 40);
+}
+
+TEST(NCollection_SequenceTest, MoveOperations)
+{
+ // Test move constructor
+ NCollection_Sequence<ItemType> aSeq1;
+ aSeq1.Append(10);
+ aSeq1.Append(20);
+ aSeq1.Append(30);
+
+ NCollection_Sequence<ItemType> aSeq2(std::move(aSeq1));
+ EXPECT_TRUE(aSeq1.IsEmpty()); // Original sequence should be empty after move
+ EXPECT_EQ(aSeq2.Size(), 3);
+ EXPECT_EQ(aSeq2(1), 10);
+ EXPECT_EQ(aSeq2(2), 20);
+ EXPECT_EQ(aSeq2(3), 30);
+
+ // Test move assignment
+ NCollection_Sequence<ItemType> aSeq3;
+ aSeq3.Append(40);
+
+ NCollection_Sequence<ItemType> aSeq4;
+ aSeq4 = std::move(aSeq3);
+ EXPECT_TRUE(aSeq3.IsEmpty()); // Original sequence should be empty after move
+ EXPECT_EQ(aSeq4.Size(), 1);
+ EXPECT_EQ(aSeq4(1), 40);
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_SparseArray.hxx>
+
+#include <gtest/gtest.h>
+
+// Basic test type for the SparseArray
+typedef Standard_Integer ItemType;
+
+// Custom class for testing complex types in the SparseArray
+class TestClass
+{
+public:
+ TestClass(int id = 0, double value = 0.0)
+ : myId(id),
+ myValue(value)
+ {
+ }
+
+ bool operator==(const TestClass& other) const
+ {
+ return myId == other.myId && fabs(myValue - other.myValue) < 1e-10;
+ }
+
+ bool operator!=(const TestClass& other) const { return !(*this == other); }
+
+ int GetId() const { return myId; }
+
+ double GetValue() const { return myValue; }
+
+ void SetValue(double value) { myValue = value; }
+
+private:
+ int myId;
+ double myValue;
+};
+
+TEST(NCollection_SparseArrayTest, BasicFunctions)
+{
+ // Test constructor with increment
+ NCollection_SparseArray<ItemType> anArray(10);
+
+ // Test initial state
+ EXPECT_TRUE(anArray.IsEmpty());
+ EXPECT_EQ(anArray.Size(), 0);
+ EXPECT_EQ(anArray.Extent(), 0);
+
+ // Test setting values
+ anArray.SetValue(5, 55);
+ anArray.SetValue(15, 155);
+
+ EXPECT_FALSE(anArray.IsEmpty());
+ EXPECT_EQ(anArray.Size(), 2);
+
+ // Test value access
+ EXPECT_EQ(anArray.Value(5), 55);
+ EXPECT_EQ(anArray(15), 155);
+
+ // Test HasValue (IsBound)
+ EXPECT_TRUE(anArray.HasValue(5));
+ EXPECT_TRUE(anArray.IsBound(15));
+ EXPECT_FALSE(anArray.HasValue(10));
+ EXPECT_FALSE(anArray.IsBound(20));
+
+ // Test UnsetValue (UnBind)
+ EXPECT_TRUE(anArray.UnsetValue(5));
+ EXPECT_FALSE(anArray.HasValue(5));
+ EXPECT_EQ(anArray.Size(), 1);
+
+ // Test modifying a value
+ anArray.ChangeValue(15) = 255;
+ EXPECT_EQ(anArray.Value(15), 255);
+}
+
+TEST(NCollection_SparseArrayTest, LargeIndices)
+{
+ NCollection_SparseArray<ItemType> anArray(10);
+
+ // Test with large indices
+ const Standard_Size largeIndex1 = 1000;
+ const Standard_Size largeIndex2 = 10000;
+
+ anArray.SetValue(largeIndex1, 1000);
+ anArray.SetValue(largeIndex2, 10000);
+
+ EXPECT_EQ(anArray.Size(), 2);
+ EXPECT_TRUE(anArray.HasValue(largeIndex1));
+ EXPECT_TRUE(anArray.HasValue(largeIndex2));
+ EXPECT_EQ(anArray.Value(largeIndex1), 1000);
+ EXPECT_EQ(anArray.Value(largeIndex2), 10000);
+}
+
+TEST(NCollection_SparseArrayTest, SparseDistribution)
+{
+ NCollection_SparseArray<ItemType> anArray(8);
+
+ // Set values with sparse distribution
+ anArray.SetValue(3, 3);
+ anArray.SetValue(10, 10);
+ anArray.SetValue(17, 17);
+ anArray.SetValue(100, 100);
+ anArray.SetValue(1000, 1000);
+
+ EXPECT_EQ(anArray.Size(), 5);
+ EXPECT_TRUE(anArray.HasValue(3));
+ EXPECT_TRUE(anArray.HasValue(10));
+ EXPECT_TRUE(anArray.HasValue(17));
+ EXPECT_TRUE(anArray.HasValue(100));
+ EXPECT_TRUE(anArray.HasValue(1000));
+
+ // Test gaps have no value
+ EXPECT_FALSE(anArray.HasValue(4));
+ EXPECT_FALSE(anArray.HasValue(11));
+ EXPECT_FALSE(anArray.HasValue(101));
+}
+
+TEST(NCollection_SparseArrayTest, IteratorFunctions)
+{
+ NCollection_SparseArray<ItemType> anArray(8);
+
+ // Set some values
+ anArray.SetValue(5, 50);
+ anArray.SetValue(10, 100);
+ anArray.SetValue(20, 200);
+ anArray.SetValue(30, 300);
+
+ // Test const iterator
+ NCollection_SparseArray<ItemType>::ConstIterator anIt(anArray);
+
+ // Check that iterator finds all values in some order
+ Standard_Boolean found5 = Standard_False;
+ Standard_Boolean found10 = Standard_False;
+ Standard_Boolean found20 = Standard_False;
+ Standard_Boolean found30 = Standard_False;
+ Standard_Size count = 0;
+
+ for (; anIt.More(); anIt.Next(), ++count)
+ {
+ Standard_Size index = anIt.Index();
+ ItemType value = anIt.Value();
+
+ if (index == 5 && value == 50)
+ found5 = Standard_True;
+ else if (index == 10 && value == 100)
+ found10 = Standard_True;
+ else if (index == 20 && value == 200)
+ found20 = Standard_True;
+ else if (index == 30 && value == 300)
+ found30 = Standard_True;
+ }
+
+ EXPECT_EQ(count, 4);
+ EXPECT_TRUE(found5);
+ EXPECT_TRUE(found10);
+ EXPECT_TRUE(found20);
+ EXPECT_TRUE(found30);
+
+ // Test non-const iterator
+ NCollection_SparseArray<ItemType>::Iterator aModIt(anArray);
+
+ // Modify values through iterator
+ for (; aModIt.More(); aModIt.Next())
+ {
+ aModIt.ChangeValue() *= 2;
+ }
+
+ // Check modified values
+ EXPECT_EQ(anArray.Value(5), 100);
+ EXPECT_EQ(anArray.Value(10), 200);
+ EXPECT_EQ(anArray.Value(20), 400);
+ EXPECT_EQ(anArray.Value(30), 600);
+}
+
+TEST(NCollection_SparseArrayTest, ComplexType)
+{
+ NCollection_SparseArray<TestClass> anArray(10);
+
+ // Set values with complex type
+ anArray.SetValue(5, TestClass(5, 3.14));
+ anArray.SetValue(10, TestClass(10, 2.718));
+
+ EXPECT_EQ(anArray.Size(), 2);
+
+ // Check values
+ EXPECT_EQ(anArray.Value(5).GetId(), 5);
+ EXPECT_DOUBLE_EQ(anArray.Value(5).GetValue(), 3.14);
+
+ EXPECT_EQ(anArray.Value(10).GetId(), 10);
+ EXPECT_DOUBLE_EQ(anArray.Value(10).GetValue(), 2.718);
+
+ // Modify through ChangeValue
+ anArray.ChangeValue(5).SetValue(6.28);
+ EXPECT_DOUBLE_EQ(anArray.Value(5).GetValue(), 6.28);
+
+ // Test unset with complex type
+ EXPECT_TRUE(anArray.UnsetValue(5));
+ EXPECT_FALSE(anArray.HasValue(5));
+}
+
+TEST(NCollection_SparseArrayTest, Clear)
+{
+ NCollection_SparseArray<ItemType> anArray(8);
+
+ // Set some values
+ anArray.SetValue(5, 5);
+ anArray.SetValue(10, 10);
+ anArray.SetValue(15, 15);
+
+ EXPECT_EQ(anArray.Size(), 3);
+
+ // Clear the array
+ anArray.Clear();
+
+ EXPECT_TRUE(anArray.IsEmpty());
+ EXPECT_EQ(anArray.Size(), 0);
+ EXPECT_FALSE(anArray.HasValue(5));
+ EXPECT_FALSE(anArray.HasValue(10));
+ EXPECT_FALSE(anArray.HasValue(15));
+}
+
+TEST(NCollection_SparseArrayTest, DataMapInterface)
+{
+ NCollection_SparseArray<ItemType> anArray(10);
+
+ // Test Bind method
+ anArray.Bind(5, 50);
+ anArray.Bind(15, 150);
+
+ EXPECT_TRUE(anArray.IsBound(5));
+ EXPECT_TRUE(anArray.IsBound(15));
+
+ // Test Find method
+ EXPECT_EQ(anArray.Find(5), 50);
+ EXPECT_EQ(anArray.Find(15), 150);
+
+ // Test ChangeFind method
+ anArray.ChangeFind(5) = 55;
+ EXPECT_EQ(anArray.Find(5), 55);
+
+ // Test UnBind method
+ EXPECT_TRUE(anArray.UnBind(5));
+ EXPECT_FALSE(anArray.IsBound(5));
+ EXPECT_EQ(anArray.Size(), 1);
+}
+
+TEST(NCollection_SparseArrayTest, AssignAndExchange)
+{
+ // Create and populate first array
+ NCollection_SparseArray<ItemType> anArray1(10);
+ anArray1.SetValue(5, 50);
+ anArray1.SetValue(15, 150);
+
+ // Test Assign method
+ NCollection_SparseArray<ItemType> anArray2(20);
+ anArray2.SetValue(7, 70);
+
+ anArray2.Assign(anArray1);
+
+ EXPECT_EQ(anArray2.Size(), 2);
+ EXPECT_TRUE(anArray2.HasValue(5));
+ EXPECT_TRUE(anArray2.HasValue(15));
+ EXPECT_EQ(anArray2.Value(5), 50);
+ EXPECT_EQ(anArray2.Value(15), 150);
+ EXPECT_FALSE(anArray2.HasValue(7)); // Should be removed after Assign
+
+ // Test Exchange method
+ NCollection_SparseArray<ItemType> anArray3(30);
+ anArray3.SetValue(10, 100);
+ anArray3.SetValue(20, 200);
+
+ anArray2.Exchange(anArray3);
+
+ // Check anArray2 after exchange (should have anArray3's values)
+ EXPECT_EQ(anArray2.Size(), 2);
+ EXPECT_TRUE(anArray2.HasValue(10));
+ EXPECT_TRUE(anArray2.HasValue(20));
+ EXPECT_EQ(anArray2.Value(10), 100);
+ EXPECT_EQ(anArray2.Value(20), 200);
+ EXPECT_FALSE(anArray2.HasValue(5));
+ EXPECT_FALSE(anArray2.HasValue(15));
+
+ // Check anArray3 after exchange (should have anArray2's values)
+ EXPECT_EQ(anArray3.Size(), 2);
+ EXPECT_TRUE(anArray3.HasValue(5));
+ EXPECT_TRUE(anArray3.HasValue(15));
+ EXPECT_EQ(anArray3.Value(5), 50);
+ EXPECT_EQ(anArray3.Value(15), 150);
+ EXPECT_FALSE(anArray3.HasValue(10));
+ EXPECT_FALSE(anArray3.HasValue(20));
+}
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <NCollection_BaseAllocator.hxx>
+#include <NCollection_Vector.hxx>
+#include <Standard_Integer.hxx>
+
+#include <gtest/gtest.h>
+
+TEST(NCollection_VectorTest, DefaultConstructor)
+{
+ // Default constructor should create an empty vector
+ NCollection_Vector<Standard_Integer> aVector;
+
+ EXPECT_EQ(0, aVector.Length());
+ EXPECT_TRUE(aVector.IsEmpty());
+}
+
+TEST(NCollection_VectorTest, ResizeConstructor)
+{
+ // Test constructor with initial size
+ const Standard_Integer initialSize = 10;
+ const Standard_Integer initialValue = 42;
+ NCollection_Vector<Standard_Integer> aVector(initialSize);
+
+ // Initialize all elements to the same value
+ for (Standard_Integer i = 0; i < initialSize; i++)
+ {
+ aVector.SetValue(i, initialValue);
+ }
+
+ EXPECT_EQ(initialSize, aVector.Length());
+ EXPECT_FALSE(aVector.IsEmpty());
+
+ // Check all values are initialized
+ for (Standard_Integer i = 0; i < initialSize; i++)
+ {
+ EXPECT_EQ(initialValue, aVector(i));
+ }
+}
+
+TEST(NCollection_VectorTest, Append)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+
+ // Test Append method
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ EXPECT_EQ(3, aVector.Length());
+ EXPECT_EQ(10, aVector(0));
+ EXPECT_EQ(20, aVector(1));
+ EXPECT_EQ(30, aVector(2));
+}
+
+TEST(NCollection_VectorTest, SetValue)
+{
+ NCollection_Vector<Standard_Integer> aVector(5, 0);
+
+ // Test SetValue method
+ aVector.SetValue(2, 42);
+
+ EXPECT_EQ(42, aVector(2));
+ EXPECT_EQ(0, aVector(0));
+ EXPECT_EQ(0, aVector(1));
+
+ // Test operator()
+ aVector(3) = 99;
+ EXPECT_EQ(99, aVector(3));
+}
+
+TEST(NCollection_VectorTest, Value)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+
+ // Test Value and operator()
+ EXPECT_EQ(10, aVector.Value(0));
+ EXPECT_EQ(20, aVector.Value(1));
+
+ EXPECT_EQ(aVector.Value(0), aVector(0));
+ EXPECT_EQ(aVector.Value(1), aVector(1));
+}
+
+TEST(NCollection_VectorTest, ChangeValue)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+
+ // Test ChangeValue
+ aVector.ChangeValue(1) = 25;
+ EXPECT_EQ(25, aVector(1));
+
+ // Equivalent using operator()
+ aVector(0) = 15;
+ EXPECT_EQ(15, aVector(0));
+}
+
+TEST(NCollection_VectorTest, FirstLast)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ // Test First and Last
+ EXPECT_EQ(10, aVector.First());
+ EXPECT_EQ(30, aVector.Last());
+
+ // Test ChangeFirst and ChangeLast
+ aVector.ChangeFirst() = 15;
+ aVector.ChangeLast() = 35;
+
+ EXPECT_EQ(15, aVector.First());
+ EXPECT_EQ(35, aVector.Last());
+}
+
+TEST(NCollection_VectorTest, CopyConstructor)
+{
+ NCollection_Vector<Standard_Integer> aVector1;
+ aVector1.Append(10);
+ aVector1.Append(20);
+ aVector1.Append(30);
+
+ // Test copy constructor
+ NCollection_Vector<Standard_Integer> aVector2(aVector1);
+
+ EXPECT_EQ(aVector1.Length(), aVector2.Length());
+
+ for (Standard_Integer i = 0; i < aVector1.Length(); i++)
+ {
+ EXPECT_EQ(aVector1(i), aVector2(i));
+ }
+
+ // Modify original to ensure deep copy
+ aVector1(1) = 25;
+ EXPECT_EQ(20, aVector2(1));
+}
+
+TEST(NCollection_VectorTest, AssignmentOperator)
+{
+ NCollection_Vector<Standard_Integer> aVector1;
+ aVector1.Append(10);
+ aVector1.Append(20);
+ aVector1.Append(30);
+
+ // Test assignment operator
+ NCollection_Vector<Standard_Integer> aVector2;
+ aVector2 = aVector1;
+
+ EXPECT_EQ(aVector1.Length(), aVector2.Length());
+
+ for (Standard_Integer i = 0; i < aVector1.Length(); i++)
+ {
+ EXPECT_EQ(aVector1(i), aVector2(i));
+ }
+
+ // Modify original to ensure deep copy
+ aVector1(1) = 25;
+ EXPECT_EQ(20, aVector2(1));
+}
+
+TEST(NCollection_VectorTest, Clear)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+
+ // Test Clear
+ aVector.Clear();
+
+ EXPECT_EQ(0, aVector.Length());
+ EXPECT_TRUE(aVector.IsEmpty());
+}
+
+TEST(NCollection_VectorTest, Iterator)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ // Test iterator
+ Standard_Integer sum = 0;
+ for (NCollection_Vector<Standard_Integer>::Iterator it(aVector); it.More(); it.Next())
+ {
+ sum += it.Value();
+ }
+
+ EXPECT_EQ(60, sum);
+
+ // Test modifying values through iterator
+ for (NCollection_Vector<Standard_Integer>::Iterator it(aVector); it.More(); it.Next())
+ {
+ it.ChangeValue() *= 2;
+ }
+
+ EXPECT_EQ(20, aVector(0));
+ EXPECT_EQ(40, aVector(1));
+ EXPECT_EQ(60, aVector(2));
+}
+
+TEST(NCollection_VectorTest, STLIterators)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ // Test C++11 range-based for loop with STL-style iterators
+ Standard_Integer sum = 0;
+ for (const auto& val : aVector)
+ {
+ sum += val;
+ }
+
+ EXPECT_EQ(60, sum);
+
+ // Test modification through iterator
+ sum = 0;
+ for (auto& val : aVector)
+ {
+ val *= 2; // Double each value
+ sum += val;
+ }
+
+ EXPECT_EQ(120, sum);
+
+ // Verify the modifications
+ EXPECT_EQ(20, aVector(0));
+ EXPECT_EQ(40, aVector(1));
+ EXPECT_EQ(60, aVector(2));
+}
+
+TEST(NCollection_VectorTest, Grow)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+
+ // Test automatic resize through many appends
+ for (Standard_Integer i = 0; i < 1000; i++)
+ {
+ aVector.Append(i);
+ }
+
+ EXPECT_EQ(1000, aVector.Length());
+
+ for (Standard_Integer i = 0; i < 1000; i++)
+ {
+ EXPECT_EQ(i, aVector(i));
+ }
+}
+
+TEST(NCollection_VectorTest, Move)
+{
+ NCollection_Vector<Standard_Integer> aVector1;
+ aVector1.Append(10);
+ aVector1.Append(20);
+
+ // Test Move constructor
+ NCollection_Vector<Standard_Integer> aVector2 = std::move(aVector1);
+
+ EXPECT_EQ(0, aVector1.Length()); // aVector1 should be empty after move
+ EXPECT_EQ(2, aVector2.Length());
+ EXPECT_EQ(10, aVector2(0));
+ EXPECT_EQ(20, aVector2(1));
+
+ // Test Move assignment
+ NCollection_Vector<Standard_Integer> aVector3;
+ aVector3.Append(30);
+ aVector3 = std::move(aVector2);
+
+ EXPECT_EQ(0, aVector2.Length()); // aVector2 should be empty after move
+ EXPECT_EQ(2, aVector3.Length());
+ EXPECT_EQ(10, aVector3(0));
+ EXPECT_EQ(20, aVector3(1));
+}
+
+TEST(NCollection_VectorTest, EraseLast)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ EXPECT_EQ(3, aVector.Length());
+
+ // Test EraseLast method
+ aVector.EraseLast();
+ EXPECT_EQ(2, aVector.Length());
+ EXPECT_EQ(10, aVector(0));
+ EXPECT_EQ(20, aVector(1));
+
+ // Remove another element
+ aVector.EraseLast();
+ EXPECT_EQ(1, aVector.Length());
+ EXPECT_EQ(10, aVector(0));
+
+ // Remove the last element
+ aVector.EraseLast();
+ EXPECT_EQ(0, aVector.Length());
+ EXPECT_TRUE(aVector.IsEmpty());
+
+ // Calling EraseLast on an empty vector should not cause errors
+ aVector.EraseLast();
+ EXPECT_EQ(0, aVector.Length());
+}
+
+TEST(NCollection_VectorTest, Appended)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+
+ // Test Appended method - returns reference to the appended element
+ Standard_Integer& ref1 = aVector.Appended();
+ ref1 = 10;
+
+ Standard_Integer& ref2 = aVector.Appended();
+ ref2 = 20;
+
+ EXPECT_EQ(2, aVector.Length());
+ EXPECT_EQ(10, aVector(0));
+ EXPECT_EQ(20, aVector(1));
+
+ // Modify through the reference
+ ref1 = 15;
+ EXPECT_EQ(15, aVector(0));
+}
+
+TEST(NCollection_VectorTest, CustomAllocator)
+{
+ // Test with custom allocator
+ Handle(NCollection_BaseAllocator) anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+ NCollection_Vector<Standard_Integer> aVector(256, anAlloc);
+
+ // Verify vector works with custom allocator
+ aVector.Append(10);
+ aVector.Append(20);
+ aVector.Append(30);
+
+ EXPECT_EQ(3, aVector.Length());
+ EXPECT_EQ(10, aVector(0));
+ EXPECT_EQ(20, aVector(1));
+ EXPECT_EQ(30, aVector(2));
+
+ // Test clear with custom allocator
+ aVector.Clear();
+ EXPECT_EQ(0, aVector.Length());
+}
+
+TEST(NCollection_VectorTest, SetIncrement)
+{
+ NCollection_Vector<Standard_Integer> aVector;
+
+ // SetIncrement only works on empty vectors
+ aVector.SetIncrement(512);
+
+ // Fill the vector to test the custom increment size
+ for (Standard_Integer i = 0; i < 1000; i++)
+ {
+ aVector.Append(i);
+ }
+
+ EXPECT_EQ(1000, aVector.Length());
+
+ // Verify data integrity with the custom increment
+ for (Standard_Integer i = 0; i < 1000; i++)
+ {
+ EXPECT_EQ(i, aVector(i));
+ }
+}
\ No newline at end of file