loxi_ir: Moved to its own package
to group ir and related functionality. Also introduce a dedicated
frontend_ir model, and adds a unit test
diff --git a/utest/test_build_ir.py b/utest/test_build_ir.py
new file mode 100755
index 0000000..b6d87a3
--- /dev/null
+++ b/utest/test_build_ir.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+# Copyright 2013, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+
+import sys
+import os
+import unittest
+
+from nose.tools import eq_, ok_, raises
+
+root_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
+sys.path.insert(0, root_dir)
+
+import loxi_ir.ir as ir
+import loxi_front_end.frontend_ir as fe
+
+class BuildIRTest(unittest.TestCase):
+
+ def test_simple(self):
+ version = ir.OFVersion("1.0", 1)
+ input = fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass=None,
+ members=(
+ fe.OFDataMember(name='version', oftype='uint32_t'),
+ fe.OFLengthMember(name='length', oftype='uint16_t')
+ ),
+ virtual=False,
+ params={}
+ ),
+ ),
+ enums=()
+ )
+
+ p = ir.build_protocol(version, [ input ])
+ eq_(1, len(p.classes))
+ c = p.classes[0]
+ eq_("OFMessage", c.name)
+ eq_(None, c.superclass)
+ eq_(False, c.virtual)
+ eq_({}, c.params)
+ eq_(2, len(c.members))
+ eq_(p, c.protocol)
+
+ m1 = c.members[0]
+ ok_(isinstance(m1, ir.OFDataMember))
+ eq_("version", m1.name)
+ eq_("uint32_t", m1.oftype)
+ eq_(4, m1.length)
+ eq_(True, m1.is_fixed_length)
+ eq_(0, m1.offset)
+ eq_(c, m1.of_class)
+
+ m2 = c.members[1]
+ ok_(isinstance(m2, ir.OFLengthMember))
+ eq_("length", m2.name)
+ eq_("uint16_t", m2.oftype)
+ eq_(2, m2.length)
+ eq_(True, m2.is_fixed_length)
+ eq_(4, m2.offset)
+ eq_(c, m2.of_class)
+
+ eq_(True, c.is_fixed_length)
+ eq_(6, c.length)
+
+ def test_resolve_superclass(self):
+ version = ir.OFVersion("1.0", 1)
+ input = fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass=None,
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ fe.OFClass(name="OFHello",
+ superclass="OFMessage",
+ members=(),
+ virtual=False,
+ params={}
+ ),
+ ),
+ enums=()
+ )
+ p = ir.build_protocol(version, [ input ])
+ eq_(2, len(p.classes))
+ c, c2 = p.classes
+ eq_("OFMessage", c.name)
+ eq_(None, c.superclass)
+ eq_(True, c.virtual)
+ eq_("OFHello", c2.name)
+ eq_(c, c2.superclass)
+ eq_(False, c2.virtual)
+
+ @raises(ir.ClassNotFoundException)
+ def test_resolve_superclass(self):
+ version = ir.OFVersion("1.0", 1)
+ input = fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass="NotFoundSuperClass",
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ ),
+ enums=()
+ )
+ p = ir.build_protocol(version, [ input ])
+
+
+ @raises(ir.DependencyCycleException)
+ def test_dependency_cycle(self):
+ version = ir.OFVersion("1.0", 1)
+ input = fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass="OFHeader",
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ fe.OFClass(name="OFHeader",
+ superclass="OFMessage",
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ ),
+ enums=()
+ )
+ p = ir.build_protocol(version, [ input ])
+
+ @raises(ir.RedefinedException)
+ def test_class_redefined(self):
+ version = ir.OFVersion("1.0", 1)
+ inputs = (
+ fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass=None,
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ ),
+ enums=(),
+ ),
+ fe.OFInput(filename="test2.dat",
+ wire_versions=(1,),
+ classes=(
+ fe.OFClass(name="OFMessage",
+ superclass=None,
+ members=(),
+ virtual=True,
+ params={}
+ ),
+ ),
+ enums=()
+ )
+ )
+ p = ir.build_protocol(version, inputs)
+
+
+ def test_enums(self):
+ version = ir.OFVersion("1.0", 1)
+ input = fe.OFInput(filename="test.dat",
+ wire_versions=(1,),
+ classes=(),
+ enums=(
+ fe.OFEnum(name='ofp_flow_wildcards',
+ entries=(fe.OFEnumEntry(name="OFPFW_IN_PORT", value=0x01, params={}),
+ fe.OFEnumEntry(name="OFPFW_DL_VLAN", value=0x2, params={})),
+ params = dict(wire_type="uint32_t", bitmask=True)
+ ),
+ fe.OFEnum(name='ofp_queue_properties',
+ entries=(fe.OFEnumEntry(name="OFPQT_NONE", value=0x00, params={}),
+ fe.OFEnumEntry(name="OFPQT_MIN_RATE", value=0x1, params={})),
+ params = dict(wire_type="uint32_t")
+ ),
+ )
+ )
+
+ p = ir.build_protocol(version, [ input ])
+ eq_(0, len(p.classes))
+ eq_(2, len(p.enums))
+ e = p.enums[0]
+ eq_("ofp_flow_wildcards", e.name)
+ eq_(True, e.is_bitmask)
+ eq_("uint32_t", e.wire_type)
+ eq_(ir.OFEnumEntry(name="OFPFW_IN_PORT", value=0x01, params={}), e.entries[0])
+ eq_(ir.OFEnumEntry(name="OFPFW_DL_VLAN", value=0x02, params={}), e.entries[1])
+
+ e = p.enums[1]
+ eq_("ofp_queue_properties", e.name)
+ eq_(False, e.is_bitmask)
+ eq_("uint32_t", e.wire_type)
+ eq_(ir.OFEnumEntry(name="OFPQT_NONE", value=0x00, params={}), e.entries[0])
+ eq_(ir.OFEnumEntry(name="OFPQT_MIN_RATE", value=0x01, params={}), e.entries[1])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/utest/test_frontend.py b/utest/test_frontend.py
index 8febfde..cfadc39 100755
--- a/utest/test_frontend.py
+++ b/utest/test_frontend.py
@@ -35,7 +35,7 @@
import loxi_front_end.parser as parser
import loxi_front_end.frontend as frontend
-from loxi_ir import *
+from loxi_front_end.frontend_ir import *
class FrontendTests(unittest.TestCase):
maxDiff = None
@@ -109,7 +109,7 @@
]
self.assertEquals(expected_ast, ast)
- ofinput = frontend.create_ofinput(ast)
+ ofinput = frontend.create_ofinput("standard-1.0", ast)
self.assertEquals(set([1, 2]), ofinput.wire_versions)
expected_classes = [
OFClass(name='of_echo_reply', superclass=None, members=[
@@ -180,7 +180,7 @@
]
self.assertEquals(expected_ast, ast)
- ofinput = frontend.create_ofinput(ast)
+ ofinput = frontend.create_ofinput("standard-1.0", ast)
expected_classes = [
OFClass(name='of_queue_prop', superclass=None, members=[
OFDiscriminatorMember('type', 'uint16_t'),