added mock testbed for unit testing.
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Wed, 9 Mar 2011 16:27:23 +0000 (17:27 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Wed, 9 Mar 2011 16:27:23 +0000 (17:27 +0100)
17 files changed:
Makefile
src/nepi/core/design.py
src/nepi/core/execute.py
src/nepi/core/metadata.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/execute.py
src/nepi/testbeds/netns/metadata_v01.py
src/nepi/util/parser/base.py
test/core/design.py [new file with mode: 0755]
test/core/execute.py [new file with mode: 0755]
test/core/integration.py [new file with mode: 0755]
test/lib/mock/__init__.py [new file with mode: 0644]
test/lib/mock/constants.py [new file with mode: 0644]
test/lib/mock/execute.py [new file with mode: 0644]
test/lib/mock/metadata_v01.py [new file with mode: 0644]
test/lib/test_util.py [moved from test/util/test_util.py with 100% similarity]
test/testbeds/netns/integration.py

index 12570b2..f3b1e06 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ BUILDDIR := $(BUILDDIR)/lib
 endif
 
 #PYPATH = $(BUILDDIR):$(TESTLIB):$(PYTHONPATH)
-PYPATH = "../nepi2/src:../nepi2/test/util:../netns/src"
+PYPATH = "../nepi2/src:../nepi2/test/lib:../netns/src"
 COVERAGE = $(or $(shell which coverage), $(shell which python-coverage), \
           coverage)
 
index c37a45e..67ed62d 100644 (file)
@@ -240,7 +240,7 @@ class Box(AttributesMap):
         for trace in factory.traces:
             tr = Trace(trace.trace_id, trace.help, trace.enabled)
             self._traces[trace.trace_id] = tr
-        for attr in factory.box_attributes:
+        for attr in factory.box_attributes.attributes:
             self.add_attribute(attr.name, attr.help, attr.type, attr.value, 
                     attr.range, attr.allowed, attr.flags, 
                     attr.validation_function)
@@ -377,7 +377,7 @@ class Factory(AttributesMap):
         self._category = category
         self._connector_types = list()
         self._traces = list()
-        self._box_attributes = list()
+        self._box_attributes = AttributesMap()
 
     @property
     def factory_id(self):
@@ -420,9 +420,8 @@ class Factory(AttributesMap):
 
     def add_box_attribute(self, name, help, type, value = None, range = None,
         allowed = None, flags = Attribute.NoFlags, validation_function = None):
-        attribute = Attribute(name, help, type, value, range, allowed, flags,
-                validation_function)
-        self._box_attributes.append(attribute)
+        self._box_attributes.add_attribute(name, help, type, value, range,
+                allowed, flags, validation_function)
 
     def create(self, guid, testbed_description):
         if self._allow_addresses:
index b92e85c..e333940 100644 (file)
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from nepi.core.attributes import AttributesMap
+from nepi.core.attributes import Attribute, AttributesMap
+from nepi.util.constants import STATUS_FINISHED
 from nepi.util.parser._xml import XmlExperimentParser
 from nepi.util import validation
 import sys
@@ -100,6 +101,7 @@ class Factory(AttributesMap):
         self._status_function = status_function
         self._connector_types = dict()
         self._traces = list()
+        self._box_attributes = AttributesMap()
 
     @property
     def factory_id(self):
@@ -113,6 +115,10 @@ class Factory(AttributesMap):
     def allow_routes(self):
         return self._allow_routes
 
+    @property
+    def box_attributes(self):
+        return self._box_attributes
+
     @property
     def create_function(self):
         return self._create_function
@@ -142,6 +148,11 @@ class Factory(AttributesMap):
     def add_trace(self, trace_id):
         self._traces.append(trace_id)
 
+    def add_box_attribute(self, name, help, type, value = None, range = None,
+        allowed = None, flags = Attribute.NoFlags, validation_function = None):
+        self._box_attributes.add_attribute(name, help, type, value, range, 
+                allowed, flags, validation_function)
+
 class TestbedInstance(object):
     def __init__(self, testbed_id, testbed_version):
         self._testbed_id = testbed_id
@@ -160,7 +171,11 @@ class TestbedInstance(object):
         raise NotImplementedError
 
     def create_set(self, guid, name, value):
-        """Instructs setting an attribute on an element"""
+        """Instructs setting an initial attribute on an element"""
+        raise NotImplementedError
+
+    def factory_set(self, guid, name, value):
+        """Instructs setting an attribute on a factory"""
         raise NotImplementedError
 
     def connect(self, guid1, connector_type_name1, guid2, 
@@ -247,6 +262,41 @@ class ExperimentController(object):
         return self._testbeds[testbed_guid].trace(guid, trace_id)
 
     def start(self):
+        self._create_testbed_instances()
+        for instance in self._testbeds.values():
+            instance.do_setup()
+        for instance in self._testbeds.values():
+            instance.do_create()
+            instance.do_connect()
+            instance.do_configure()
+        for instances in self._testbeds.values():
+            instance.do_cross_connect()
+        for instances in self._testbeds.values():
+            instance.start()
+
+    def stop(self):
+       for instance in self._testbeds.values():
+           instance.stop()
+
+    def is_finished(self, guid):
+        for instance in self._testbeds.values():
+            for guid_ in instance.guids:
+                if guid_ == guid:
+                    return instance.status(guid) == STATUS_FINISHED
+        raise RuntimeError("No element exists with guid %d" % guid)    
+
+    def shutdown(self):
+       for instance in self._testbeds.values():
+           instance.shutdown()
+
+    def _build_testbed_instance(self, testbed_id, testbed_version):
+        mod_name = "nepi.testbeds.%s" % (testbed_id.lower())
+        if not mod_name in sys.modules:
+            __import__(mod_name)
+        module = sys.modules[mod_name]
+        return module.TestbedInstance(testbed_version)
+
+    def _create_testbed_instances(self):
         parser = XmlExperimentParser()
         data = parser.from_xml_to_data(self._experiment_xml)
         element_guids = list()
@@ -260,7 +310,9 @@ class ExperimentController(object):
                 self._testbeds[guid] = instance
             else:
                 element_guids.append(guid)
+        self._program_testbed_instances(element_guids, data)
 
+    def _program_testbed_instances(self, element_guids, data):
         for guid in element_guids:
             (testbed_guid, factory_id) = data.get_box_data(guid)
             instance = self._testbeds[testbed_guid]
@@ -293,36 +345,3 @@ class ExperimentController(object):
                     data.get_route_data(guid):
                 instance.add_route(guid, destination, netprefix, nexthop)
 
-        for instance in self._testbeds.values():
-            instance.do_setup()
-        for instance in self._testbeds.values():
-            instance.do_create()
-            instance.do_connect()
-            instance.do_configure()
-        for instances in self._testbeds.values():
-            instance.do_cross_connect()
-        for instances in self._testbeds.values():
-            instance.start()
-
-    def stop(self):
-       for instance in self._testbeds.values():
-           instance.stop()
-
-    def status(self, guid):
-        for instance in self._testbeds.values():
-            for guid_ in instance.guids:
-                if guid_ == guid:
-                    return instance.status(guid)
-        raise RuntimeError("No element exists with guid %d" % guid)    
-
-    def shutdown(self):
-       for instance in self._testbeds.values():
-           instance.shutdown()
-
-    def _build_testbed_instance(self, testbed_id, testbed_version):
-        mod_name = "nepi.testbeds.%s" % (testbed_id.lower())
-        if not mod_name in sys.modules:
-            __import__(mod_name)
-        module = sys.modules[mod_name]
-        return module.TestbedInstance(testbed_version)
-
index cf84a2d..88529f7 100644 (file)
@@ -161,7 +161,7 @@ class Metadata(object):
                     stop_function, status_function, allow_addresses, 
                     allow_routes)
             self._add_attributes(factory, info, "factory_attributes")
-            self._add_attributes(factory, info, "box_attributes")
+            self._add_attributes(factory, info, "box_attributes", True)
             self._add_execute_traces(factory, info)
             self._add_execute_connector_types(factory, info)
             factories.append(factory)
index ea039e1..5f60c19 100644 (file)
@@ -20,6 +20,7 @@ class TestbedInstance(execute.TestbedInstance):
         # experiment construction instructions
         self._create = dict()
         self._create_set = dict()
+        self._factory_set = dict()
         self._connect = dict()
         self._cross_connect = dict()
         self._add_trace = dict()
@@ -29,8 +30,6 @@ class TestbedInstance(execute.TestbedInstance):
 
         # log of set operations
         self._set = dict()
-        # log of actions
-        self._actions = dict()
 
         # testbed element instances
         self._elements = dict()
@@ -69,14 +68,27 @@ class TestbedInstance(execute.TestbedInstance):
             raise RuntimeError("Element guid %d doesn't exist" % guid)
         factory_id = self._create[guid]
         factory = self._factories[factory_id]
-        if not factory.has_attribute(name):
+        if not factory.box_attributes.has_attribute(name):
             raise RuntimeError("Invalid attribute %s for element type %s" %
                     (name, factory_id))
-        factory.set_attribute_value(name, value)
+        factory.box_attributes.set_attribute_value(name, value)
         if guid not in self._create_set:
             self._create_set[guid] = dict()
         self._create_set[guid][name] = value
-       
+
+    def factory_set(self, guid, name, value):
+        if not guid in self._create:
+            raise RuntimeError("Element guid %d doesn't exist" % guid)
+        factory_id = self._create[guid]
+        factory = self._factories[factory_id]
+        if not factory.has_attribute(name):
+            raise RuntimeError("Invalid attribute %s for element type %s" %
+                    (name, factory_id))
+        factory.set_attribute_value(name, value)
+        if guid not in self._factory_set:
+            self._factory_set[guid] = dict()
+        self._factory_set[guid][name] = value
+
     def connect(self, guid1, connector_type_name1, guid2, 
             connector_type_name2):
         factory_id1 = self._create[guid1]
@@ -176,7 +188,10 @@ class TestbedInstance(execute.TestbedInstance):
             for guid in guids[factory_id]:
                 parameters = dict() if guid not in self._create_set else \
                         self._create_set[guid]
-                factory.create_function(self, guid, parameters)
+                factory_parameters = dict() if guid not in \
+                        self._factory_set else self._create_set[guid]
+                factory.create_function(self, guid, parameters, 
+                        factory_parameters)
                 for name, value in parameters.iteritems():
                     self.set(TIME_NOW, guid, name, value)
 
@@ -223,12 +238,12 @@ class TestbedInstance(execute.TestbedInstance):
             raise RuntimeError("Element guid %d doesn't exist" % guid)
         factory_id = self._create[guid]
         factory = self._factories[factory_id]
-        if not factory.has_attribute(name):
+        if not factory.box_attributes.has_attribute(name):
             raise RuntimeError("Invalid attribute %s for element type %s" %
                     (name, factory_id))
         if self._started and factory.is_attribute_design_only(name):
             raise RuntimeError("Attribute %s can only be modified during experiment design" % name)
-        factory.set_attribute_value(name, value)
+        factory.box_attributes.set_attribute_value(name, value)
         if guid not in self._set:
             self._set[guid] = dict()
         if time not in self._set[guid]:
index c37db2c..8636677 100644 (file)
@@ -3,8 +3,6 @@
 
 from constants import TESTBED_ID
 from nepi.core import testbed_impl
-from nepi.core.metadata import Metadata
-from nepi.util import validation
 from nepi.util.constants import AF_INET, AF_INET6
 import os
 
index d164540..58cab37 100644 (file)
@@ -37,7 +37,7 @@ def connect_fd_local(tap, fdnd):
 
 ### Creation functions ###
 
-def create_node(testbed_instance, guid, parameters):
+def create_node(testbed_instance, guid, parameters, factory_parameters):
     forward_X11 = False
     if "forward_X11" in parameters:
         forward_X11 = parameters["forward_X11"]
@@ -45,7 +45,7 @@ def create_node(testbed_instance, guid, parameters):
     element = testbed_instance.netns.Node(forward_X11 = forward_X11)
     testbed_instance.elements[guid] = element
 
-def create_p2piface(testbed_instance, guid, parameters):
+def create_p2piface(testbed_instance, guid, parameters, factory_parameters):
     if guid in testbed_instance.elements:
         # The interface pair was already instantiated
         return
@@ -71,7 +71,7 @@ def create_p2piface(testbed_instance, guid, parameters):
     testbed_instance.elements[guid] = element1
     testbed_instance.elements[guid2] = element2
 
-def create_tapiface(testbed_instance, guid, parameters):
+def create_tapiface(testbed_instance, guid, parameters, factory_parameters):
     node_guid = testbed_instance.get_connected(guid, "node", "devs")
     if len(node_guid) == 0:
         raise RuntimeError("Can't instantiate interface %d outside netns \
@@ -80,7 +80,7 @@ def create_tapiface(testbed_instance, guid, parameters):
     element = node.add_tap()
     testbed_instance.elements[guid] = element
 
-def create_nodeiface(testbed_instance, guid, parameters):
+def create_nodeiface(testbed_instance, guid, parameters, factory_parameters):
     node_guid = testbed_instance.get_connected(guid, "node", "devs")
     if len(node_guid) == 0:
         raise RuntimeError("Can't instantiate interface %d outside netns \
@@ -89,11 +89,11 @@ def create_nodeiface(testbed_instance, guid, parameters):
     element = node.add_if()
     testbed_instance.elements[guid] = element
 
-def create_switch(testbed_instance, guid, parameters):
+def create_switch(testbed_instance, guid, parameters, factory_parameters):
     element = testbed_instance.netns.Switch()
     testbed_instance.elements[guid] = element
 
-def create_application(testbed_instance, guid, parameters):
+def create_application(testbed_instance, guid, parameters, factory_parameters):
     testbed_instance.elements[guid] = None # Delayed construction 
 
 ### Start/Stop functions ###
index 35df079..4dff0e9 100644 (file)
@@ -296,7 +296,7 @@ class ExperimentParser(object):
 
     def traces_from_data(self, box, data):
         for name in data.get_trace_data(box.guid):
-            box.trace(name).enable()
+            box.enable_trace(name)
 
     def addresses_from_data(self, box, data):
         for (autoconf, address, family, netprefix, broadcast) \
diff --git a/test/core/design.py b/test/core/design.py
new file mode 100755 (executable)
index 0000000..2481d19
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+import mock.metadata_v01 
+import sys
+import unittest
+
+class DesignTestCase(unittest.TestCase):
+    def setUp(self):
+        sys.modules["nepi.testbeds.mock.metadata_v01"] = mock.metadata_v01
+
+    def test_design(self):
+        exp_desc = ExperimentDescription()
+        testbed_version = "01"
+        testbed_id = "mock"
+        provider = FactoriesProvider(testbed_id, testbed_version)
+        desc = exp_desc.add_testbed_description(provider)
+        desc.set_attribute_value("fake", True)
+        node1 = desc.create("Node")
+        node2 = desc.create("Node")
+        iface1 = desc.create("Interface")
+        iface1.set_attribute_value("fake", True)
+        node1.connector("devs").connect(iface1.connector("node"))
+        iface2 = desc.create("Interface")
+        iface2.set_attribute_value("fake", True)
+        node2.connector("devs").connect(iface2.connector("node"))
+        iface1.connector("iface").connect(iface2.connector("iface"))
+        app = desc.create("Application")
+        app.connector("node").connect(node1.connector("apps"))
+        app.enable_trace("fake")
+
+        xml = exp_desc.to_xml()
+        exp_desc2 = ExperimentDescription()
+        exp_desc2.from_xml(xml)
+        xml2 = exp_desc2.to_xml()
+        self.assertTrue(xml == xml2)
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/test/core/execute.py b/test/core/execute.py
new file mode 100755 (executable)
index 0000000..34ca0c9
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from nepi.util.constants import STATUS_FINISHED
+import mock
+import mock.metadata_v01 
+import sys
+import time
+import unittest
+
+class ExecuteTestCase(unittest.TestCase):
+    def setUp(self):
+        sys.modules["nepi.testbeds.mock.metadata_v01"] = mock.metadata_v01
+
+    def test_execute(self):
+        testbed_version = "01"
+        testbed_id = "mock"
+        instance = mock.TestbedInstance(testbed_version)
+        instance.configure("fake", True)
+        instance.create(2, "Node")
+        instance.create(3, "Node")
+        instance.create(4, "Node")
+        instance.create(5, "Interface")
+        instance.create_set(5, "fake", True)
+        instance.connect(2, "devs", 5, "node")
+        instance.create(6, "Interface")
+        instance.create_set(6, "fake", True)
+        instance.connect(3, "devs", 6, "node")
+        instance.connect(5, "iface", 6, "iface")
+        instance.create(7, "Application")
+        instance.add_trace(7, "fake")
+        instance.connect(7, "node", 2, "apps")
+
+        instance.do_setup()
+        instance.do_create()
+        instance.do_connect()
+        instance.do_configure()
+        instance.start()
+        while instance.status(7) != STATUS_FINISHED:
+            time.sleep(0.5)
+        app_result = instance.trace(7, "fake")
+        comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
+
+--- 10.0.0.2 ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+"""
+        
+        self.assertTrue(app_result.startswith(comp_result))
+        instance.stop()
+        instance.shutdown()
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/test/core/integration.py b/test/core/integration.py
new file mode 100755 (executable)
index 0000000..e6b82fc
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from nepi.core.execute import ExperimentController
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.util.constants import STATUS_FINISHED
+import mock
+import mock.metadata_v01 
+import sys
+import time
+import unittest
+
+class ExecuteTestCase(unittest.TestCase):
+    def setUp(self):
+        sys.modules["nepi.testbeds.mock.metadata_v01"] = mock.metadata_v01
+        sys.modules["nepi.testbeds.mock"] = mock
+
+    def test_integration(self):
+        exp_desc = ExperimentDescription()
+        testbed_version = "01"
+        testbed_id = "mock"
+        provider = FactoriesProvider(testbed_id, testbed_version)
+        desc = exp_desc.add_testbed_description(provider)
+        desc.set_attribute_value("fake", True)
+        node1 = desc.create("Node")
+        node2 = desc.create("Node")
+        iface1 = desc.create("Interface")
+        iface1.set_attribute_value("fake", True)
+        node1.connector("devs").connect(iface1.connector("node"))
+        iface2 = desc.create("Interface")
+        iface2.set_attribute_value("fake", True)
+        node2.connector("devs").connect(iface2.connector("node"))
+        iface1.connector("iface").connect(iface2.connector("iface"))
+        app = desc.create("Application")
+        app.connector("node").connect(node1.connector("apps"))
+        app.enable_trace("fake")
+
+        xml = exp_desc.to_xml()
+        controller = ExperimentController(xml)
+        controller.start()
+        while not controller.is_finished(app.guid):
+            time.sleep(0.5)
+        fake_result = controller.trace(desc.guid, app.guid, "fake")
+        comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
+
+--- 10.0.0.2 ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+"""
+        self.assertTrue(fake_result.startswith(comp_result))
+        controller.stop()
+        controller.shutdown()
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/test/lib/mock/__init__.py b/test/lib/mock/__init__.py
new file mode 100644 (file)
index 0000000..3b3f853
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from constants import TESTBED_ID
+from execute import TestbedInstance 
+
diff --git a/test/lib/mock/constants.py b/test/lib/mock/constants.py
new file mode 100644 (file)
index 0000000..c4401b2
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+TESTBED_ID = "mock"
+
diff --git a/test/lib/mock/execute.py b/test/lib/mock/execute.py
new file mode 100644 (file)
index 0000000..1244dbd
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from constants import TESTBED_ID
+from nepi.core import testbed_impl
+
+class TestbedInstance(testbed_impl.TestbedInstance):
+    def __init__(self, testbed_version):
+        super(TestbedInstance, self).__init__(TESTBED_ID, testbed_version)
+
+    def do_setup(self):
+        pass
+
+    def do_configure(self):
+        pass
+
+    def set(self, time, guid, name, value):
+        super(TestbedInstance, self).set(time, guid, name, value)
+
+    def get(self, time, guid, name):
+        return True 
+
+    def action(self, time, guid, action):
+        raise NotImplementedError
+
+    def trace(self, guid, trace_id):
+        return """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
+
+--- 10.0.0.2 ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+"""
+
+    def shutdown(self):
+           pass
+
diff --git a/test/lib/mock/metadata_v01.py b/test/lib/mock/metadata_v01.py
new file mode 100644 (file)
index 0000000..17a5657
--- /dev/null
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from constants import TESTBED_ID
+from nepi.core import metadata
+from nepi.core.attributes import Attribute
+from nepi.util import validation
+from nepi.util.constants import STATUS_FINISHED
+
+NODE = "Node"
+IFACE = "Interface"
+APP = "Application"
+
+### Connection functions ####
+
+### Creation functions ###
+
+def create_node(testbed_instance, guid, parameters, factory_parameters):
+    element = NODE 
+    testbed_instance.elements[guid] = element
+
+def create_iface(testbed_instance, guid, parameters, factory_parameters):
+     element = IFACE
+     testbed_instance.elements[guid] = element
+
+def create_application(testbed_instance, guid, parameters, factory_parameters):
+     element = APP
+     testbed_instance.elements[guid] = element
+
+### Start/Stop functions ###
+
+### Status functions ###
+
+def status_application(testbed_instance, guid):
+    return STATUS_FINISHED
+
+### Factory information ###
+
+connector_types = dict({
+    "apps": dict({
+                "help": "Connector from node to applications", 
+                "name": "apps",
+                "max": -1, 
+                "min": 0
+            }),
+    "devs": dict({
+                "help": "Connector from node to network interfaces", 
+                "name": "devs",
+                "max": -1, 
+                "min": 0
+            }),
+    "node": dict({
+                "help": "Connector to a Node", 
+                "name": "node",
+                "max": 1, 
+                "min": 1
+            }),
+    "iface": dict({
+                "help": "Connector to a Interface", 
+                "name": "iface",
+                "max": 1, 
+                "min": 0
+            }),
+   })
+
+connections = [
+    dict({
+        "from": (TESTBED_ID, NODE, "devs"),
+        "to":   (TESTBED_ID, IFACE, "node"),
+        "code": None,
+        "can_cross": False
+    }),
+    dict({
+        "from": (TESTBED_ID, IFACE, "iface"),
+        "to":   (TESTBED_ID, IFACE, "iface"),
+        "code": None,
+        "can_cross": False
+    }),
+    dict({
+        "from": (TESTBED_ID, NODE, "apps"),
+        "to":   (TESTBED_ID, APP, "node"),
+        "code": None,
+        "can_cross": False
+    })
+]
+
+attributes = dict({
+    "fake": dict({
+                "name": "fake",
+                "help": "fake attribute",
+                "type": Attribute.BOOL,
+                "value": False,
+                "range": None,
+                "allowed": None,
+                "validation_function": validation.is_bool
+            }),
+    })
+
+traces = dict({
+    "fake": dict({
+                "name": "fake",
+                "help": "fake trace"
+              }),
+    })
+
+factories_order = [ NODE, IFACE, APP ]
+
+factories_info = dict({
+    NODE: dict({
+            "help": "Fake node",
+            "category": "topology",
+            "create_function": create_node,
+            "start_function": None,
+            "stop_function": None,
+            "status_function": None,
+            "box_attributes": ["fake"],
+            "connector_types": ["devs", "apps"]
+       }),
+    IFACE: dict({
+            "help": "Fake iface",
+            "category": "devices",
+            "create_function": create_iface,
+            "start_function": None,
+            "stop_function": None,
+            "status_function": None,
+            "factory_attributes": ["fake"],
+            "box_attributes": ["fake"],
+            "connector_types": ["node", "iface"]
+       }),
+    APP: dict({
+            "help": "Fake application",
+            "category": "applications",
+            "create_function": create_application,
+            "start_function": None,
+            "stop_function": None,
+            "status_function": status_application,
+            "box_attributes": ["fake"],
+            "connector_types": ["node"],
+            "traces": ["fake"]
+        }),
+})
+
+testbed_attributes = dict({
+        "fake": dict({
+                "name": "fake",
+                "help": "fake attribute",
+                "type": Attribute.BOOL,
+                "value": False,
+                "range": None,
+                "allowed": None,
+                "validation_function": validation.is_bool
+            }),
+    })
+
+class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
+    @property
+    def connections_types(self):
+        return connection_types
+
+    @property
+    def connections(self):
+        return connections
+
+    @property
+    def attributes(self):
+        return attributes
+
+    @property
+    def traces(self):
+        return traces
+
+    @property
+    def factories_order(self):
+        return factories_order
+
+    @property
+    def factories_info(self):
+        return factories_info
+
+    @property
+    def testbed_attributes(self):
+        return testbed_attributes
+
similarity index 100%
rename from test/util/test_util.py
rename to test/lib/test_util.py
index a4c5da9..a0244d5 100755 (executable)
@@ -4,7 +4,6 @@
 import getpass
 from nepi.core.design import ExperimentDescription, FactoriesProvider
 from nepi.core.execute import ExperimentController
-from nepi.util.constants import AF_INET, STATUS_FINISHED
 import os
 import shutil
 import test_util
@@ -53,7 +52,7 @@ class NetnsIntegrationTestCase(unittest.TestCase):
 
         controller = ExperimentController(xml)
         controller.start()
-        while controller.status(app.guid) != STATUS_FINISHED:
+        while not controller.is_finished(app.guid):
             time.sleep(0.5)
         ping_result = controller.trace(netns_desc.guid, app.guid, "stdout")
         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.