// SPDX-License-Identifier: LGPL-2.1-or-later #include #include #include #include #include #include #include #include #include #include #include // NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers) class ShapeRelationKey: public ::testing::Test { protected: static void SetUpTestSuite() { tests::initApplication(); } }; TEST_F(ShapeRelationKey, HistoryTraceTypeComparison) { // Arrange Data::MappedName mappedName {"mappedName"}; Part::HistoryTraceType htt1 {Part::HistoryTraceType::stopOnTypeChange}; Part::HistoryTraceType htt2 {Part::HistoryTraceType::followTypeChange}; Part::ShapeRelationKey key1 {mappedName, htt1}; Part::ShapeRelationKey key2 {mappedName, htt2}; // Act bool key1LessThanKey2 = key1 < key2; // Assert ASSERT_TRUE(key1LessThanKey2); } class TopoShapeCacheTest: public ::testing::Test { protected: static void SetUpTestSuite() { tests::initApplication(); } void SetUp() override { _docName = App::GetApplication().getUniqueDocumentName("test"); App::GetApplication().newDocument(_docName.c_str(), "testUser"); _sids = &_sid; _hasher = Base::Reference(new App::StringHasher); ASSERT_EQ(_hasher.getRefCount(), 1); } void TearDown() override { App::GetApplication().closeDocument(_docName.c_str()); } private: std::string _docName; Data::ElementIDRefs _sid; QVector* _sids = nullptr; App::StringHasherRef _hasher; }; TEST_F(TopoShapeCacheTest, ConstructionFromTopoDS_Shape) { // Arrange - create a TopoDS shape with some location transformation applied TopoDS_Vertex vertex; gp_Quaternion quaternion(1.0, 2.0, 3.0, 4.0); gp_Trsf transform; transform.SetRotation(quaternion); auto location = TopLoc_Location(transform); vertex.Location(location); // Act auto cache = Part::TopoShapeCache(vertex); // Assert - ensure the location of the cached shape was zeroed out EXPECT_NE(cache.shape.Location(), vertex.Location()); } TEST_F(TopoShapeCacheTest, InsertRelationIntoEmptyTableCompacts) { // Arrange Data::IndexedName indexedName {"EDGE1"}; auto mappedName = Data::MappedName::fromRawData("#94;:G0;XTR;:H19:8,F;:H1a,F;BND:-1:0;:H1b:10,F"); ASSERT_TRUE(mappedName.isRaw()); Data::MappedElement mappedElement1 {indexedName, mappedName}; QVector vectorOfElements {mappedElement1}; TopoDS_Vertex vertex; Part::TopoShapeCache cache(vertex); Part::ShapeRelationKey key {mappedName, Part::HistoryTraceType::followTypeChange}; // Act cache.insertRelation(key, vectorOfElements); // Assert auto foundIterator = cache.relations.find(key); EXPECT_NE(foundIterator, cache.relations.end()); EXPECT_FALSE(foundIterator->first.name.isRaw()); // compact() was called } TEST_F(TopoShapeCacheTest, InsertAlreadyExistsUpdatesExisting) { // Arrange Data::IndexedName indexedName {"EDGE1"}; Data::MappedName mappedName("#94;:G0;XTR;:H19:8,F;:H1a,F;BND:-1:0;:H1b:10,F"); Data::MappedElement mappedElement1 {indexedName, mappedName}; QVector vectorOfElements {mappedElement1}; TopoDS_Vertex vertex; Part::TopoShapeCache cache(vertex); Part::ShapeRelationKey key {mappedName, Part::HistoryTraceType::followTypeChange}; // Act cache.insertRelation(key, vectorOfElements); QVector emptyVector; cache.insertRelation(key, emptyVector); // Assert EXPECT_TRUE(cache.relations.find(key)->second.empty()); } TEST_F(TopoShapeCacheTest, IsTouchedNotPartners) { // Arrange BRep_TVertex* vertex1 = new BRep_TVertex; vertex1->Pnt(gp_Pnt(1.0, 1.0, 1.0)); BRep_TVertex* vertex2 = new BRep_TVertex; vertex2->Pnt(gp_Pnt(2.0, 2.0, 2.0)); opencascade::handle handle1(vertex1); opencascade::handle handle2(vertex2); TopoDS_Vertex tds1; TopoDS_Vertex tds2; tds1.TShape(handle1); tds2.TShape(handle2); ASSERT_FALSE(tds1.IsPartner(tds2)); Part::TopoShapeCache cache(tds1); // Act & Assert EXPECT_TRUE(cache.isTouched(tds2)); } TEST_F(TopoShapeCacheTest, IsTouchedArePartners) { // Arrange BRep_TVertex* vertex1 = new BRep_TVertex; vertex1->Pnt(gp_Pnt(1.0, 1.0, 1.0)); opencascade::handle handle1(vertex1); TopoDS_Vertex tds1; TopoDS_Vertex tds2; tds1.TShape(handle1); tds2.TShape(handle1); ASSERT_TRUE(tds1.IsPartner(tds2)); Part::TopoShapeCache cache(tds1); // Act & Assert EXPECT_FALSE(cache.isTouched(tds2)); } std::tuple> CreateShapeWithSubshapes() { auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge(); auto fuse = BRepAlgoAPI_Fuse(edge1, edge2); fuse.Build(); return {fuse.Shape(), {edge1, edge2}}; } TEST_F(TopoShapeCacheTest, GetAncestrySHAPE) { // Arrange auto shape = std::get<0>(CreateShapeWithSubshapes()); Part::TopoShapeCache cache(shape); // Act auto ancestry = cache.getAncestry(TopAbs_SHAPE); // Assert EXPECT_EQ(2, ancestry.count()); } TEST_F(TopoShapeCacheTest, GetAncestryEDGE) { // Arrange auto shape = std::get<0>(CreateShapeWithSubshapes()); Part::TopoShapeCache cache(shape); // Act auto ancestry = cache.getAncestry(TopAbs_EDGE); // Assert EXPECT_EQ(2, ancestry.count()); } TEST_F(TopoShapeCacheTest, GetAncestryFACE) { // Arrange auto shape = std::get<0>(CreateShapeWithSubshapes()); Part::TopoShapeCache cache(shape); // Act auto ancestry = cache.getAncestry(TopAbs_FACE); // Assert EXPECT_EQ(0, ancestry.count()); } TEST_F(TopoShapeCacheTest, CountShape) { // Arrange auto shape = std::get<0>(CreateShapeWithSubshapes()); Part::TopoShapeCache cache(shape); // Act int countOfEdges = cache.countShape(TopAbs_EDGE); int countOfFaces = cache.countShape(TopAbs_FACE); int countOfShapes = cache.countShape(TopAbs_SHAPE); // Assert EXPECT_EQ(2, countOfEdges); EXPECT_EQ(0, countOfFaces); EXPECT_EQ(2, countOfShapes); } TEST_F(TopoShapeCacheTest, FindShapeGivenSubshape) { // Arrange const auto [shape, ancestors] = CreateShapeWithSubshapes(); Part::TopoShapeCache cache(shape); // Act auto shapeResult1 = cache.findShape(ancestors.first, shape); auto shapeResult2 = cache.findShape(ancestors.second, shape); // Assert EXPECT_NE(0, shapeResult1); EXPECT_NE(0, shapeResult2); } TEST_F(TopoShapeCacheTest, FindShapeGivenTypeAndIndex) { // Arrange const auto [shape, ancestors] = CreateShapeWithSubshapes(); Part::TopoShapeCache cache(shape); // Act auto shapeResult = cache.findShape(ancestors.first, TopAbs_EDGE, 1); // NOT zero-indexed! // Assert EXPECT_FALSE(shapeResult.IsNull()); } std::tuple> CreateFusedCubes() { auto boxMaker1 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0); boxMaker1.Build(); auto box1 = boxMaker1.Shape(); auto boxMaker2 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0); boxMaker2.Build(); auto box2 = boxMaker2.Shape(); auto transform = gp_Trsf(); transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)); box2.Location(TopLoc_Location(transform)); auto fuse = BRepAlgoAPI_Fuse(box1, box2); fuse.Build(); return {fuse, {box1, box2}}; } TEST_F(TopoShapeCacheTest, FindAncestor) { // Arrange const auto [shape, ancestors] = CreateFusedCubes(); Part::TopoShapeCache cache(shape); // Act auto ancestorResultCompound = cache.findAncestor(ancestors.first, shape, TopAbs_COMPOUND); // Assert EXPECT_FALSE(ancestorResultCompound.IsNull()); } // NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)