Toponaming/Part: Cleanups, problem fixes, and tests
This commit is contained in:
188
tests/src/Mod/Part/App/PropertyTopoShape.cpp
Normal file
188
tests/src/Mod/Part/App/PropertyTopoShape.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include "Mod/Part/App/FeaturePartCommon.h"
|
||||
#include "Mod/Part/App/PropertyTopoShape.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
#include "PartTestHelpers.h"
|
||||
#include "Mod/Part/App/TopoShapeCompoundPy.h"
|
||||
|
||||
using namespace Part;
|
||||
using namespace PartTestHelpers;
|
||||
|
||||
class PropertyTopoShapeTest: public ::testing::Test, public PartTestHelperClass
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
createTestDoc();
|
||||
_common = dynamic_cast<Common*>(_doc->addObject("Part::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
|
||||
{}
|
||||
|
||||
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);
|
||||
#ifdef FC_USE_TNP_FIX
|
||||
EXPECT_EQ(topoShapeOut.getElementMapSize(), 26);
|
||||
#else
|
||||
EXPECT_EQ(topoShapeOut.getElementMapSize(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user