Download tests/src/Mod/Part/App/PropertyTopoShape.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 9.18 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/tests/src/Mod/Part/App/PropertyTopoShape.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/tests/src/Mod/Part/App/PropertyTopoShape.cpp
-
curl -L -o PropertyTopoShape.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/tests/src/Mod/Part/App/PropertyTopoShape.cpp
9.18 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| using namespace Part; | |
| using namespace PartTestHelpers; | |
| class PropertyTopoShapeTest: public ::testing::Test, public PartTestHelperClass | |
| { | |
| protected: | |
| static void SetUpTestSuite() | |
| { | |
| tests::initApplication(); | |
| } | |
| void SetUp() override | |
| { | |
| createTestDoc(); | |
| _common = _doc->addObject<Common>(); | |
| _common->Base.setValue(_boxes[0]); | |
| _common->Tool.setValue(_boxes[1]); | |
| _common->execute(); // We should now have an elementMap with 26 entries. | |
| } | |
| void TearDown() override | |
| {} | |
| std::string getDocumentXml() const | |
| { | |
| return R"x(<?xml version='1.0' encoding='utf-8'?> | |
| <Document SchemaVersion="4" ProgramVersion="0.22R35485 +5758 (Git)" FileVersion="1" Uid="2795701f-8074-4bb6-b707-b2c97acf4128" StringHasher="1"> | |
| <StringHasher saveall="0" threshold="0" count="0" new="1"/> | |
| <StringHasher2 count="1"> | |
| <![CDATA[ | |
| -1.0 0:Shape cache | |
| ]]> | |
| </StringHasher2> | |
| <Properties Count="1" TransientCount="0"> | |
| <Property name="Uid" type="App::PropertyUUID" status="16777217"> | |
| <Uuid value="2795701f-8074-4bb6-b707-b2c97acf4128"/> | |
| </Property> | |
| </Properties> | |
| <Objects Count="1" Dependencies="1"> | |
| <ObjectDeps Name="Sketch" Count="0"/> | |
| <Object type="Sketcher::SketchObject" name="Sketch" id="11" revision="16711878" /> | |
| </Objects> | |
| <ObjectData Count="1"> | |
| <Object name="Sketch" Extensions="True"> | |
| <Properties Count="1" TransientCount="0"> | |
| <Property name="Shape" type="Part::PropertyPartShape"> | |
| <Part HasherIndex="0" ElementMap="1.15.70200.4" file="Sketch.Shape.brp"/> | |
| <ElementMap new="1" count="1"><Element key="Dummy" value="Dummy"/></ElementMap> | |
| <ElementMap2 count="8"> | |
| <![CDATA[ | |
| 1 PostfixCount 3 | |
| Edge | |
| Vertex | |
| ;SKT | |
| MapCount 1 | |
| ElementMap 1 1 2 | |
| Edge | |
| ChildCount 0 | |
| NameCount 5 | |
| 0 | |
| ;g1.3 0 | |
| ;g2.3 0 | |
| ;g3.3 0 | |
| ;g4.3 0 | |
| Vertex | |
| ChildCount 0 | |
| NameCount 5 | |
| 0 | |
| ;g1v1.3 0 | |
| ;g1v2.3 0 | |
| ;g2v2.3 0 | |
| ;g3v2.3 0 | |
| EndMap | |
| ]]> | |
| </ElementMap2> | |
| </Property> | |
| </Properties> | |
| </Object> | |
| </ObjectData> | |
| </Document> | |
| )x"; | |
| } | |
| Common* _common = nullptr; // NOLINT Can't be private in a test framework | |
| }; | |
| TEST_F(PropertyTopoShapeTest, testPropertyPartShapeTopoShape) | |
| { | |
| // Arrange | |
| auto partShape = PropertyPartShape(); | |
| auto topoShapeIn = _common->Shape.getShape(); | |
| auto topoDsShapeIn = _common->Shape.getShape().getShape(); | |
| // Act | |
| partShape.setValue(topoShapeIn); | |
| auto topoShapeOut = partShape.getShape(); | |
| auto topoDsShapeOut = partShape.getValue(); | |
| // Assert | |
| EXPECT_TRUE(topoShapeOut.isSame(topoShapeIn)); | |
| EXPECT_TRUE(topoDsShapeOut.IsSame(topoDsShapeIn)); | |
| EXPECT_EQ(getVolume(topoDsShapeOut), 3); | |
| EXPECT_EQ(topoShapeOut.getElementMapSize(), 26); | |
| } | |
| TEST_F(PropertyTopoShapeTest, testPropertyPartShapeTopoDSShape) | |
| { | |
| // Arrange | |
| auto property = _boxes[0]->addDynamicProperty("Part::PropertyPartShape", "test"); | |
| auto partShape = dynamic_cast<PropertyPartShape*>(property); | |
| auto topoShapeIn = _common->Shape.getShape(); | |
| auto topoDsShapeIn = _common->Shape.getShape().getShape(); | |
| // Act | |
| // The second parameter of setValue, whether to resetElementMap is never called and irrelevant. | |
| // It appears to exist only to pass to the lower level setShape call. | |
| partShape->setValue(topoDsShapeIn); | |
| auto topoShapeOut = partShape->getShape(); | |
| auto topoDsShapeOut = partShape->getValue(); | |
| // Assert | |
| EXPECT_FALSE(topoShapeOut.isSame(topoShapeIn)); | |
| EXPECT_TRUE(topoDsShapeOut.IsSame(topoDsShapeIn)); | |
| EXPECT_EQ(getVolume(topoDsShapeOut), 3); | |
| EXPECT_EQ(topoShapeOut.getElementMapSize(), 0); // We passed in a TopoDS_Shape so lost the map | |
| } | |
| TEST_F(PropertyTopoShapeTest, testPropertyPartShapeGetPyObject) | |
| { | |
| // Arrange | |
| Py_Initialize(); | |
| Base::PyGILStateLocker lock; | |
| auto partShape = PropertyPartShape(); | |
| auto topoDsShapeIn = _common->Shape.getShape().getShape(); | |
| auto topoDsShapeIn2 = _boxes[3]->Shape.getShape().getShape(); | |
| // Act | |
| partShape.setValue(topoDsShapeIn); | |
| auto pyObj = partShape.getPyObject(); | |
| // Assert | |
| EXPECT_TRUE(PyObject_TypeCheck(pyObj, &TopoShapeCompoundPy::Type)); // _common is a compound. | |
| // We can't build a TopoShapeCompoundPy directly ( protected destructor ), so we'll flip | |
| // the compound out and in to prove setPyObject works as expected. | |
| // Act | |
| partShape.setValue(topoDsShapeIn2); | |
| auto pyObj2 = partShape.getPyObject(); | |
| // Assert the shape is no longer a compound | |
| EXPECT_FALSE(PyObject_TypeCheck(pyObj2, &TopoShapeCompoundPy::Type)); // _boxes[3] is not a | |
| // compound. | |
| Py_XDECREF(pyObj2); | |
| // Act | |
| partShape.setPyObject(pyObj); | |
| auto pyObj3 = partShape.getPyObject(); | |
| // Assert the shape returns to a compound if we setPyObject | |
| EXPECT_TRUE(PyObject_TypeCheck(pyObj3, &TopoShapeCompoundPy::Type)); // _common is a compound. | |
| Py_XDECREF(pyObj3); | |
| Py_XDECREF(pyObj); | |
| } | |
| // Possible future PropertyPartShape tests: | |
| // Copy, Paste, getMemSize, beforeSave, Save. Restore | |
| TEST_F(PropertyTopoShapeTest, testShapeHistory) | |
| { | |
| // Arrange | |
| TopoDS_Shape baseShape = _boxes[0]->Shape.getShape().getShape(); | |
| BRepFilletAPI_MakeFillet mkFillet(baseShape); | |
| auto edges = _boxes[0]->Shape.getShape().getSubTopoShapes(TopAbs_EDGE); | |
| mkFillet.Add(0.1, 0.1, TopoDS::Edge(edges[0].getShape())); | |
| TopoDS_Shape newShape = mkFillet.Shape(); | |
| // Act to test the constructor | |
| auto hist = ShapeHistory(mkFillet, TopAbs_EDGE, newShape, baseShape); | |
| // Assert | |
| EXPECT_EQ(hist.type, TopAbs_EDGE); | |
| EXPECT_EQ(hist.shapeMap.size(), 11); // We filleted away one of the cubes 12 Edges | |
| // Act to test the join operation | |
| hist.join(hist); | |
| // Assert | |
| EXPECT_EQ(hist.type, TopAbs_EDGE); | |
| EXPECT_EQ(hist.shapeMap.size(), 9); // TODO: Is this correct? | |
| // Act to test the reset operation | |
| hist.reset(mkFillet, TopAbs_VERTEX, newShape, baseShape); | |
| // Assert | |
| EXPECT_EQ(hist.type, TopAbs_VERTEX); | |
| EXPECT_EQ(hist.shapeMap.size(), 8); // Vertexes on a cube. | |
| } | |
| TEST_F(PropertyTopoShapeTest, testPropertyShapeHistory) | |
| { | |
| // N/A nothing to really test | |
| } | |
| TEST_F(PropertyTopoShapeTest, testPropertyShapeCache) | |
| { | |
| // Arrange | |
| PropertyShapeCache propertyShapeCache; | |
| TopoShape topoShapeIn {_boxes[0]->Shape.getShape()}; // Any TopoShape to test with | |
| TopoShape topoShapeOut; | |
| const char* subName = "Face1"; // Cache key | |
| // Act | |
| auto gotShapeNotYet = propertyShapeCache.getShape(_boxes[0], topoShapeOut, subName); | |
| propertyShapeCache.setShape(_boxes[0], topoShapeIn, subName); | |
| auto gotShapeGood = propertyShapeCache.getShape(_boxes[0], topoShapeOut, subName); | |
| // Assert | |
| ASSERT_FALSE(gotShapeNotYet); | |
| ASSERT_TRUE(gotShapeGood); | |
| EXPECT_EQ(getVolume(topoShapeIn.getShape()), 6); | |
| EXPECT_EQ(getVolume(topoShapeOut.getShape()), 6); | |
| EXPECT_TRUE(topoShapeIn.isSame(topoShapeOut)); | |
| } | |
| TEST_F(PropertyTopoShapeTest, testPropertyShapeCachePyObj) | |
| { | |
| // Arrange | |
| Py_Initialize(); | |
| Base::PyGILStateLocker lock; | |
| PropertyShapeCache catalyst; | |
| auto propertyShapeCache = catalyst.get(_boxes[1], true); | |
| auto faces = _boxes[1]->Shape.getShape().getSubTopoShapes(TopAbs_FACE); | |
| propertyShapeCache->setShape(_boxes[1], faces[0], "Face1"); | |
| propertyShapeCache->setShape(_boxes[1], faces[1], "Face2"); | |
| propertyShapeCache->setShape(_boxes[1], faces[2], "Face3"); | |
| propertyShapeCache->setShape(_boxes[1], faces[3], "Face4"); | |
| auto eraseList = PyList_New(2); | |
| PyList_SetItem(eraseList, 0, PyUnicode_FromString("Face2")); | |
| PyList_SetItem(eraseList, 1, PyUnicode_FromString("Face3")); | |
| // Act | |
| auto pyObjOut = propertyShapeCache->getPyObject(); | |
| propertyShapeCache->setPyObject(eraseList); // pyObjInRepr); | |
| auto pyObjOutErased = propertyShapeCache->getPyObject(); | |
| // The faces that come back from python are in a random order compared to what was passed in | |
| // so testing them individually is difficult. We'll just make sure the counts are right. | |
| EXPECT_EQ(PyList_Size(pyObjOut), 4); // All four faces we added to the cache | |
| EXPECT_EQ(PyList_Size(pyObjOutErased), 2); // setPyObject removed Face2 and Face3 | |
| Py_XDECREF(pyObjOut); | |
| Py_XDECREF(pyObjOutErased); | |
| } | |
| TEST_F(PropertyTopoShapeTest, testRestore) | |
| { | |
| // Test case for https://github.com/FreeCAD/FreeCAD/pull/16576 | |
| std::stringstream str(getDocumentXml()); | |
| Base::XMLReader reader("Document.xml", str); | |
| App::StringHasher hasher; | |
| hasher.Restore(reader); | |
| Part::PropertyPartShape prop; | |
| prop.Restore(reader); | |
| EXPECT_STREQ(reader.localName(), "ElementMap2"); | |
| EXPECT_EQ(reader.level(), 5); | |
| EXPECT_EQ(reader.getAttributeCount(), 1); | |
| EXPECT_TRUE(reader.isValid()); | |
| EXPECT_TRUE(reader.isEndOfElement()); | |
| } | |