You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gump.apache.org by le...@apache.org on 2005/04/18 21:16:20 UTC

svn commit: r161784 - in gump/branches/Gump3/pygump/python/gump: engine/modeller.py test/testModeller.py

Author: leosimons
Date: Mon Apr 18 12:16:19 2005
New Revision: 161784

URL: http://svn.apache.org/viewcvs?view=rev&rev=161784
Log:
Start testing Loader and solidifying it a little.

* pygump/python/gump/engine/modeller.py: add in (untested so far, unfortunately) code to prevent recursive hrefs (GUMP-38), and do argument checking on the stuff provided to __init__.

* pygump/python/gump/test/testModeller.py: start with basic unit tests for the Loader class (GUMP-91).

Modified:
    gump/branches/Gump3/pygump/python/gump/engine/modeller.py
    gump/branches/Gump3/pygump/python/gump/test/testModeller.py

Modified: gump/branches/Gump3/pygump/python/gump/engine/modeller.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/modeller.py?view=diff&r1=161783&r2=161784
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/modeller.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/modeller.py Mon Apr 18 12:16:19 2005
@@ -202,6 +202,11 @@
                      be None only if the workspace to load does not contain
                      any hrefs.
         """
+        assert hasattr(log, "warning")
+        assert callable(log.warning)
+        if vfs:
+            assert hasattr(vfs, "get_as_stream")
+            assert callable(vfs.get_as_stream)
         self.log = log
         self.vfs = vfs
     
@@ -228,9 +233,10 @@
     
     def _resolve_hrefs_in_workspace(self, ws, dropped_nodes):
         """Redirects to _resolve_hrefs_in_children."""
-        self._resolve_hrefs_in_children(ws, dropped_nodes)
+        found_hrefs=[]
+        self._resolve_hrefs_in_children(ws, dropped_nodes, found_hrefs)
     
-    def _resolve_hrefs_in_children(self, element, dropped_nodes):
+    def _resolve_hrefs_in_children(self, element, dropped_nodes, found_hrefs):
         """Recursively resolve all hrefs in all the children for a DOM node.
         
         The resolution is done in a resolve-then-recurse manner, so the end
@@ -238,8 +244,12 @@
         be passed in a dom Element or something else which actually has children;
         passing in an Attr for example makes no sense and results in problems.
         
-        The dropped_nodes arguments should be a list that will be populated with
+        The dropped_nodes argument should be a list that will be populated with
         nodes for which href resolution fails.
+        
+        The found_hrefs argument should be al ist that will be populated with all
+        the hrefs that have been resolved by the method that resolved hrefs for
+        the parent. An error will be thrown when recursion is detected.
         """
         for child in element.childNodes:
             # only resolve hrefs for elements
@@ -252,12 +262,15 @@
                 self._resolve_href(child, dropped_nodes)
 
             # now recurse to resolve any hrefs within this child
-            self._resolve_hrefs_in_children(child, dropped_nodes)
+            # note that we duplicate the found_hrefs array. This means that the
+            # same file can be imported multiple times, as long as it is imported
+            # by siblings, rather than as part of some parent<->child relation.
+            self._resolve_hrefs_in_children(child, dropped_nodes, found_hrefs[:])
         
         # we're now done with resolution
         #return node
     
-    def _resolve_href(self, node, dropped_nodes):
+    def _resolve_href(self, node, dropped_nodes, found_hrefs):
         """Resolve a href for the provided node.
 
         We merge in the referenced xml document into the provided node.
@@ -266,7 +279,12 @@
         its parent and appended to the dropped_nodes list.
         """
         href = node.getAttribute('href')
+        if href in found_hrefs:
+            raise ModellerError, \
+"""Recursive inclusion because files refer to each other. This href leads to
+a cycle: %s.""" % href
         self.log.debug( "Resolving HREF: %s" % href )
+        found_hrefs.append(href)
         
         try:
             stream = self.vfs.get_as_stream(href)

Modified: gump/branches/Gump3/pygump/python/gump/test/testModeller.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/test/testModeller.py?view=diff&r1=161783&r2=161784
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/test/testModeller.py (original)
+++ gump/branches/Gump3/pygump/python/gump/test/testModeller.py Mon Apr 18 12:16:19 2005
@@ -21,6 +21,7 @@
 from unittest import TestCase
 
 from xml.dom import minidom
+import StringIO
 
 from gump.engine.modeller import _find_element_text
 from gump.engine.modeller import _do_drop
@@ -30,6 +31,8 @@
 from gump.engine.modeller import _find_module_containing_node
 from gump.engine.modeller import _find_project_containing_node
 from gump.engine.modeller import _import_node
+from gump.engine.modeller import ModellerError
+from gump.engine.modeller import Loader
 
 class ModellerTestCase(TestCase):
     def setUp(self):
@@ -83,6 +86,20 @@
 """
         self.sampledom2 = minidom.parseString(self.samplexml2)
 
+        self.sampleworkspacestring = """<?xml version="1.0"?>
+
+<workspace>
+  <newelem attr="yo">contents</newelem>
+  <module name="foo">
+    <project name="bar">
+      <blah/>
+    </project>
+  </module>
+  <newelem>ignore</newelem>
+</workspace>
+"""
+        self.sampleworkspace = minidom.parseString(self.sampleworkspacestring)
+    
     def test_find_element_text(self):
         root = self.sampledom.documentElement
         text = _find_element_text(root, "elem")
@@ -158,6 +175,49 @@
         self.assertEqual(1, oldroot.getElementsByTagName("uniquetaghere").length)
         self.assertEqual(2, oldroot.getElementsByTagName("newelem").length)
         self.assertEqual(1, oldroot.getElementsByTagName("newstuff").length)
+    
+    def test_modeller_error(self):
+        error = ModellerError()
+        self.assert_(isinstance(error, Exception))
+    
+    def test_loader_init(self):
+        log = MockLog()
+        vfs = MockVFS()
+        
+        loader = Loader(log,vfs)
+        loader = Loader(log,None)
+        
+        self.assertRaises(AssertionError, Loader, self, vfs)
+        self.assertRaises(AssertionError, Loader, log, self)
+        self.assertRaises(AssertionError, Loader, None, vfs)
+    
+    def test_loader_get_workspace_tree_simple(self):
+        log = MockLog()
+        vfs = MockVFS()
+        loader = Loader(log,vfs)
+        
+        (wsdom, dropped_nodes) = loader.get_workspace_tree(StringIO.StringIO(self.sampleworkspacestring))
+        # TODO check wsdom content validity
+        self.assertEqual(0, len(dropped_nodes))
+        self.assertEqual(type(self.sampleworkspace), type(wsdom))
+        self.assertEqual(None, log.msg)
+        self.assertEqual(None, vfs.href)
+    
+    # TODO test loader href resolution
+    # TODO test loader looping href resolution
+    # TODO test loader href resolution failure
+    # TODO test loader vfs exception
+        
+class MockLog:
+    msg = None
+    def warning(self,msg):
+        self.msg = msg
+
+class MockVFS:
+    href = None
+    def get_as_stream(href):
+        self.href = href
+        return StringIO.StringIO()
 
 # this is used by testrunner.py to determine what tests to run
 def test_suite():