pyloxi: automatically test all datafiles
The new function add_datafiles_tests is fairly magical but I don't see a better
way to do this in Python 2.6.
diff --git a/py_gen/tests/of10.py b/py_gen/tests/of10.py
index fa97a79..c91c7b3 100644
--- a/py_gen/tests/of10.py
+++ b/py_gen/tests/of10.py
@@ -27,7 +27,7 @@
# under the EPL.
import unittest
import test_data
-from testutil import test_datafile
+from testutil import add_datafiles_tests
try:
import loxi.of10 as ofp
@@ -58,9 +58,6 @@
self.assertTrue(hasattr(loxi.of10, "message"))
class TestActions(unittest.TestCase):
- def test_output(self):
- test_datafile('action_output.data')
-
def test_output_equality(self):
action = ofp.action.output(port=1, max_len=0x1234)
action2 = ofp.action.output(port=1, max_len=0x1234)
@@ -74,9 +71,6 @@
self.assertNotEquals(action, action2)
action2.max_len = 0x1234
- def test_bsn_set_tunnel_dst(self):
- test_datafile('of10/action_bsn_set_tunnel_dst.data')
-
# Assumes action serialization/deserialization works
class TestActionList(unittest.TestCase):
def test_normal(self):
@@ -130,15 +124,6 @@
self.assertEquals(0xfc000, ofp.OFPFW_NW_DST_MASK)
class TestCommon(unittest.TestCase):
- def test_port_desc(self):
- test_datafile('of10/port_desc.data')
-
- def test_table_stats_entry(self):
- test_datafile('of10/table_stats_entry.data')
-
- def test_flow_stats_entry(self):
- test_datafile('of10/flow_stats_entry.data')
-
def test_match(self):
match = ofp.match()
self.assertEquals(match.wildcards, ofp.OFPFW_ALL)
@@ -161,17 +146,11 @@
msg = ofp.message.hello(xid=0)
self.assertEquals(msg.xid, 0)
- def test_hello(self):
- test_datafile('of10/hello.data')
-
def test_echo_request_construction(self):
msg = ofp.message.echo_request(data="abc")
self.assertEquals(msg.data, "abc")
- def test_echo_request(self):
- test_datafile('of10/echo_request.data')
-
- # Invalid length
+ def test_echo_request_invalid_length(self):
buf = "\x01\x02\x00\x07\x12\x34\x56"
with self.assertRaisesRegexp(ofp.ProtocolError, "buffer too short"):
ofp.message.echo_request.unpack(buf)
@@ -649,6 +628,11 @@
self.assertEquals(msg.queues[1].properties[0].rate, 6)
self.assertEquals(msg.queues[1].properties[1].rate, 7)
+class TestDataFiles(unittest.TestCase):
+ pass
+
+add_datafiles_tests(TestDataFiles, 'of10/', ofp)
+
class TestParse(unittest.TestCase):
def test_parse_header(self):
import loxi
diff --git a/py_gen/tests/testutil.py b/py_gen/tests/testutil.py
index 1e12e9b..ea30902 100644
--- a/py_gen/tests/testutil.py
+++ b/py_gen/tests/testutil.py
@@ -28,6 +28,9 @@
import sys
import difflib
+import re
+import os
+import unittest
import test_data
# Human-friendly format for binary strings. 8 bytes per line.
@@ -72,12 +75,32 @@
(type(obj).__name__, expected, pretty, diff(expected, pretty)))
# Run test_serialization and possibly test_pretty against the named data file
-# Uses the globals of the calling function to get 'ofp'
-def test_datafile(name):
+def test_datafile(name, ofp):
data = test_data.read(name)
+ if not 'python' in data:
+ raise unittest.SkipTest("no python section in datafile")
binary = data['binary']
python = data['python']
- obj = eval(python, sys._getframe(1).f_globals)
+ obj = eval(python, { 'ofp': ofp })
test_serialization(obj, binary)
if 'python pretty-printer' in data:
test_pretty(obj, data['python pretty-printer'])
+
+# Add test_datafile tests for each datafile matching the given regex
+# The argument 'klass' should be a subclass of TestCase which will have the
+# test_* methods added to it.
+#
+# It would be cleaner to do this by constructing a TestSuite instance and
+# adding individual TestCase objects, but the TestLoader wouldn't pick it
+# up. We could use the load_tests protocol but that isn't available before
+# Python 2.7.
+def add_datafiles_tests(klass, regex, ofp):
+ for filename in test_data.list_files():
+ match = re.match(regex, filename)
+ if not match:
+ continue
+ def make_test(filename):
+ def fn(self):
+ test_datafile(filename, ofp)
+ return fn
+ setattr(klass, 'test_' + os.path.splitext(filename)[0], make_test(filename))