Salome HOME
Updated copyright comment
[modules/shaper.git] / src / PythonAPI / model / tests / tests.py
index f888453dd67830271a9915d73aa2fac00386f9b1..e088f7c749723377713df2a22937eb330ffa068c 100644 (file)
@@ -1,27 +1,27 @@
-## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-##
-## See http:##www.salome-platform.org/ or
-## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
-##
+# Copyright (C) 2014-2024  CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
 
 from GeomAlgoAPI import *
 from GeomAPI import *
 from GeomDataAPI import *
-from ModelAPI import ModelAPI_Feature
+from ModelAPI import ModelAPI_Feature, ModelAPI_Session, objectToFeature
+from ModelHighAPI import *
 import math
 from salome.shaper.model import sketcher
 
@@ -69,9 +69,16 @@ def generateTests(theFeature, theFeatureName, theTestsList = []):
     aNbResults = len(theFeature.results())
     aResultsVolumes = []
     for anIndex in range(0, aNbResults):
-      aResultsVolumes.append(GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape()))
+      aResultsVolumes.append(GeomAlgoAPI_ShapeTools.volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape()))
     print("model.testResultsVolumes({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsVolumes)))
 
+  if "testResultsAreas" in theTestsList or len(theTestsList) == 0:
+    aNbResults = len(theFeature.results())
+    aResultsAreas = []
+    for anIndex in range(0, aNbResults):
+      aResultsAreas.append(GeomAlgoAPI_ShapeTools.area(theFeature.results()[anIndex].resultSubShapePair()[0].shape()))
+    print("model.testResultsAreas({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsAreas)))
+
 
 def testNbResults(theFeature, theExpectedNbResults):
   """ Tests number of feature results.
@@ -116,6 +123,64 @@ def testNbSubShapes(theFeature, theShapeType, theExpectedNbSubShapes):
     assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes)
 
 
+def testNbUniqueSubShapes(theFeature, theShapeType, theExpectedNbSubShapes):
+  """ Tests number of unique feature sub-shapes of passed type for each result.
+  :param theFeature: feature to test.
+  :param theShapeType: shape type of sub-shapes to test.
+  :param theExpectedNbSubShapes: list of sub-shapes numbers. Size of list should be equal to len(theFeature.results()).
+  """
+  aResults = theFeature.feature().results()
+  aNbResults = len(aResults)
+  aListSize = len(theExpectedNbSubShapes)
+  assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
+  for anIndex in range(0, aNbResults):
+    aNbResultSubShapes = 0
+    anExpectedNbSubShapes = theExpectedNbSubShapes[anIndex]
+    aNbResultSubShapes = aResults[anIndex].shape().subShapes(theShapeType, True).size()
+    assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes)
+
+
+def testCompound(theFeature, NbSubRes, NbSolid, NbFace, NbEdge, NbVertex):
+  """ Tests number of unique sub-shapes in compound result
+  """
+  aResults = theFeature.feature().results()
+  aNbResults = len(aResults)
+  assert (aNbResults == 1), "Number of results: {} not equal to 1.".format(aNbResults)
+  assert aResults[0].shape().isCompound(), "Result shape type: {}. Expected: COMPOUND.".format(aResults[0].shape().shapeTypeStr())
+  testNbSubResults(theFeature, NbSubRes)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex)
+
+
+def testCompSolid(theFeature, NbSubRes, NbSolid, NbFace, NbEdge, NbVertex):
+  """ Tests number of unique sub-shapes in compsolid result
+  """
+  aResults = theFeature.feature().results()
+  aNbResults = len(aResults)
+  assert (aNbResults == 1), "Number of results: {} not equal to 1.".format(aNbResults)
+  assert aResults[0].shape().isCompSolid(), "Result shape type: {}. Expected: COMPSOLID.".format(aResults[0].shape().shapeTypeStr())
+  testNbSubResults(theFeature, NbSubRes)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex)
+
+
+def testResults(theFeature, NbRes, NbSubRes, NbShell, NbFace, NbEdge, NbVertex):
+  """ Tests numbers of unique sub-shapes in the results
+  """
+  aResults = theFeature.feature().results()
+  aNbResults = len(aResults)
+  assert (aNbResults == NbRes), "Number of results: {} not equal to {}}.".format(aNbResults, NbRes)
+  testNbSubResults(theFeature, NbSubRes)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SHELL, NbShell)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge)
+  testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex)
+
+
 def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7):
   """ Tests results volumes.
   :param theFeature: feature to test.
@@ -126,11 +191,29 @@ def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDi
   aListSize = len(theExpectedResultsVolumes)
   assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
   for anIndex in range(0, aNbResults):
-    aResultVolume = GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape())
+    aResultVolume = GeomAlgoAPI_ShapeTools.volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape())
     aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0")
     anExpectedResultVolume = theExpectedResultsVolumes[anIndex]
     anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0")
-    assert math.fabs(aResultVolume - anExpectedResultVolume) < aTolerance * math.fabs(anExpectedResultVolume), "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
+    assert math.fabs(aResultVolume - anExpectedResultVolume) <= aTolerance * math.fabs(anExpectedResultVolume), "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
+
+
+def testResultsAreas(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7):
+  """ Tests results areas.
+  :param theFeature: feature to test.
+  :param theExpectedResultsAreas: list of results areas. Size of list should be equal to len(theFeature.results()).
+  """
+  aTolerance = 10**(-theNbSignificantDigits)
+  aNbResults = len(theFeature.results())
+  aListSize = len(theExpectedResultsVolumes)
+  assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
+  for anIndex in range(0, aNbResults):
+    aResultVolume = GeomAlgoAPI_ShapeTools.area(theFeature.results()[anIndex].resultSubShapePair()[0].shape())
+    aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0")
+    anExpectedResultVolume = theExpectedResultsVolumes[anIndex]
+    anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0")
+    assert math.fabs(aResultVolume - anExpectedResultVolume) <= aTolerance * math.fabs(anExpectedResultVolume), "Area of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
+
 
 def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
   """ Tests if all faces of result have a name
@@ -322,3 +405,71 @@ def checkGroup(theGroup, theShapeType):
     assert(name != ""), "String empty"
     presented_names.add(name)
   assert(len(presented_names) == groupSelectionList.size()), "Some names are not unique"
+
+def createSubShape(thePartDoc, theModel, theSelection):
+  """ Create feature according to the type of the given subshape
+  """
+  if theSelection.shapeType() == "VERTEX":
+    return theModel.addVertex(thePartDoc, [theSelection])
+  elif theSelection.shapeType() == "EDGE":
+    return theModel.addEdge(thePartDoc, [theSelection])
+  elif theSelection.shapeType() == "FACE":
+    return theModel.addFace(thePartDoc, [theSelection])
+
+def checkFilter(thePartDoc, theModel, theFilter, theShapesList):
+  """ Check filter's work on specified shape.
+      Shapes given as a dictionary of selection and expected result.
+  """
+  aFiltersFactory = ModelAPI_Session.get().filters()
+  for sel, res in theShapesList.items():
+    needUndo = False
+    shapeName = ""
+    shapeType = "UNKNOWN"
+    if sel.variantType() == ModelHighAPI_Selection.VT_ResultSubShapePair:
+      parent = sel.resultSubShapePair()[0]
+      shape = sel.resultSubShapePair()[1]
+      if shape.isNull():
+        shape = sel.resultSubShapePair()[0].shape()
+      shapeName = sel.name()
+      shapeType = shape.shapeTypeStr()
+    else:
+      needUndo = True
+      theModel.begin()
+      subShapeFeature = createSubShape(thePartDoc, theModel, sel)
+      theModel.end()
+      parent = subShapeFeature.results()[0].resultSubShapePair()[0]
+      shape = subShapeFeature.results()[0].resultSubShapePair()[0].shape()
+      shapeType = sel.typeSubShapeNamePair()[0]
+      shapeName = sel.typeSubShapeNamePair()[1]
+    assert aFiltersFactory.isValid(theFilter.feature(), parent, shape) == res, "Filter result for {} \"{}\" incorrect. Expected {}.".format(shapeType, shapeName, res)
+    if needUndo:
+      theModel.undo()
+
+def checkFeaturesValidity(thePartDoc):
+  """ Check that the features are not in error
+  """
+  aFactory = ModelAPI_Session.get().validators()
+
+  nbFeatures = thePartDoc.size("Features")
+
+  assert nbFeatures>0, "No features found in part doc"
+
+  for i in range(nbFeatures):
+    partObject = thePartDoc.object("Features", i)
+    # Check the data
+    partObjectData = partObject.data()
+    name = partObjectData.name()
+    error = partObjectData.error()
+    # raise the error message if there is one
+    assert error == '', "The feature data {0} is in error: {1}".format(name, error)
+    # raise an error if the the feature is not valid (without error message)
+    assert partObject.data().isValid(), "The feature data {0} is in error.".format(name)
+    # Same checks for the feature itself
+    feature = objectToFeature(partObject)
+    if feature is None:
+      # Folders are not real features
+      continue
+    # raise the error message if there is one
+    assert error == '', "The feature {0} is in error: {1}".format(name, error)
+    # raise an error if the the feature is not valid (without error message)
+    assert aFactory.validate(feature), "The feature {0} is in error.".format(name)