From d9adc9cd6c74353ed3ddc00f26d89990255fe5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Mon, 26 Dec 2016 16:42:49 +0100 Subject: [PATCH] DAG: Add document graph recompute test --- src/App/DocumentPy.xml | 2 +- src/App/DocumentPyImp.cpp | 4 +- src/Mod/Test/Document.py | 78 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/App/DocumentPy.xml b/src/App/DocumentPy.xml index f5afe30b7..da2ce190d 100644 --- a/src/App/DocumentPy.xml +++ b/src/App/DocumentPy.xml @@ -102,7 +102,7 @@ - Recompute the document + Recompute the document and returns the amount of recomputed features diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index a57ce47bd..88296ce9d 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -384,8 +384,8 @@ PyObject* DocumentPy::recompute(PyObject * args) { if (!PyArg_ParseTuple(args, "")) // convert args: Python->C return NULL; // NULL triggers exception - getDocumentPtr()->recompute(); - Py_Return; + int objectCount = getDocumentPtr()->recompute(); + return Py::new_reference_to(Py::Int(objectCount)); } PyObject* DocumentPy::getObject(PyObject *args) diff --git a/src/Mod/Test/Document.py b/src/Mod/Test/Document.py index 5fdc3ae95..ae15e84ec 100644 --- a/src/Mod/Test/Document.py +++ b/src/Mod/Test/Document.py @@ -263,7 +263,85 @@ class DocumentBasicCases(unittest.TestCase): self.Doc.removeObject(obj.Name) del obj + + def testRecompute(self): + + # sequence to test recompute behaviour + # L1---\ L7 + # / \ \ | + # L2 L3 \ L8 + # / \ / \ / + # L4 L5 L6 + + L1 = self.Doc.addObject("App::FeatureTest","Label_1") + L2 = self.Doc.addObject("App::FeatureTest","Label_2") + L3 = self.Doc.addObject("App::FeatureTest","Label_3") + L4 = self.Doc.addObject("App::FeatureTest","Label_4") + L5 = self.Doc.addObject("App::FeatureTest","Label_5") + L6 = self.Doc.addObject("App::FeatureTest","Label_6") + L7 = self.Doc.addObject("App::FeatureTest","Label_7") + L8 = self.Doc.addObject("App::FeatureTest","Label_8") + L1.LinkList = [L2,L3,L6] + L2.Link = L4 + L2.LinkList = [L5] + L3.LinkList = [L5,L6] + L7.Link = L8 #make second root + + self.failUnless(L7 in self.Doc.RootObjects) + self.failUnless(L1 in self.Doc.RootObjects) + + self.failUnless(len(self.Doc.Objects) == len(self.Doc.ToplogicalSortedObjects)) + + seqDic = {} + i = 0 + for obj in self.Doc.ToplogicalSortedObjects: + seqDic[obj] = i + print obj + i += 1 + + self.failUnless(seqDic[L2] > seqDic[L1]) + self.failUnless(seqDic[L3] > seqDic[L1]) + self.failUnless(seqDic[L5] > seqDic[L2]) + self.failUnless(seqDic[L5] > seqDic[L3]) + self.failUnless(seqDic[L5] > seqDic[L1]) + + + self.failUnless((0, 0, 0, 0, 0, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + self.failUnless(self.Doc.recompute()==4) + self.failUnless((1, 1, 1, 0, 0, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L5.touch() + self.failUnless((1, 1, 1, 0, 0, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + self.failUnless(self.Doc.recompute()==4) + self.failUnless((2, 2, 2, 0, 1, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L4.touch() + self.failUnless(self.Doc.recompute()==3) + self.failUnless((3, 3, 2, 1, 1, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L5.touch() + self.failUnless(self.Doc.recompute()==4) + self.failUnless((4, 4, 3, 1, 2, 0)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L6.touch() + self.failUnless(self.Doc.recompute()==3) + self.failUnless((5, 4, 4, 1, 2, 1)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L2.touch() + self.failUnless(self.Doc.recompute()==2) + self.failUnless((6, 5, 4, 1, 2, 1)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L1.touch() + self.failUnless(self.Doc.recompute()==1) + self.failUnless((7, 5, 4, 1, 2, 1)==(L1.ExecCount,L2.ExecCount,L3.ExecCount,L4.ExecCount,L5.ExecCount,L6.ExecCount)) + L6.Link = L1 # create a circular dependency + self.failUnless(self.Doc.recompute()==-1) + L6.Link = None # resolve the circular dependency + self.failUnless(self.Doc.recompute()==3) + self.Doc.removeObject(L1.Name) + self.Doc.removeObject(L2.Name) + self.Doc.removeObject(L3.Name) + self.Doc.removeObject(L4.Name) + self.Doc.removeObject(L5.Name) + self.Doc.removeObject(L6.Name) + self.Doc.removeObject(L7.Name) + self.Doc.removeObject(L8.Name) + def tearDown(self): #closing doc FreeCAD.closeDocument("CreateTest")