blob: b557730bdb4013e5cf2eff8c2d9af5da5f195d32 [file] [log] [blame]
Rich Lanea22233e2013-04-25 13:18:41 -07001#!/usr/bin/env python
2# Copyright 2013, Big Switch Networks, Inc.
3#
4# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
5# the following special exception:
6#
7# LOXI Exception
8#
9# As a special exception to the terms of the EPL, you may distribute libraries
10# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
11# that copyright and licensing notices generated by LoxiGen are not altered or removed
12# from the LoxiGen Libraries and the notice provided below is (i) included in
13# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
14# documentation for the LoxiGen Libraries, if distributed in binary form.
15#
16# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
17#
18# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
19# a copy of the EPL at:
20#
21# http://www.eclipse.org/legal/epl-v10.html
22#
23# Unless required by applicable law or agreed to in writing, software
24# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
25# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26# EPL for the specific language governing permissions and limitations
27# under the EPL.
28import unittest
29
30try:
31 import loxi.of12 as ofp
32except ImportError:
33 exit("loxi package not found. Try setting PYTHONPATH.")
34
35class TestImports(unittest.TestCase):
36 def test_toplevel(self):
37 import loxi
38 self.assertTrue(hasattr(loxi, "ProtocolError"))
Rich Lane00549ea2013-04-25 13:33:16 -070039 self.assertEquals(loxi.version_names[3], "1.2")
Rich Lanea22233e2013-04-25 13:18:41 -070040 ofp = loxi.protocol(3)
41 self.assertEquals(ofp.OFP_VERSION, 3)
42 self.assertTrue(hasattr(ofp, "action"))
43 self.assertTrue(hasattr(ofp, "common"))
44 self.assertTrue(hasattr(ofp, "const"))
45 self.assertTrue(hasattr(ofp, "message"))
46 self.assertTrue(hasattr(ofp, "oxm"))
47
48 def test_version(self):
49 import loxi
50 self.assertTrue(hasattr(loxi.of12, "ProtocolError"))
51 self.assertTrue(hasattr(loxi.of12, "OFP_VERSION"))
52 self.assertEquals(loxi.of12.OFP_VERSION, 3)
53 self.assertTrue(hasattr(loxi.of12, "action"))
54 self.assertTrue(hasattr(loxi.of12, "common"))
55 self.assertTrue(hasattr(loxi.of12, "const"))
56 self.assertTrue(hasattr(loxi.of12, "message"))
57 self.assertTrue(hasattr(loxi.of12, "oxm"))
58
Rich Lane3005cf92013-05-01 12:33:35 -070059class TestCommon(unittest.TestCase):
60 sample_empty_match_buf = ''.join([
61 '\x00\x01', # type
62 '\x00\x04', # length
63 '\x00\x00\x00\x00', # padding
64 ])
65
66 def test_empty_match_pack(self):
67 obj = ofp.match()
68 self.assertEquals(self.sample_empty_match_buf, obj.pack())
69
70 def test_empty_match_unpack(self):
71 obj = ofp.match.unpack(self.sample_empty_match_buf)
72 self.assertEquals(len(obj.oxm_list), 0)
73
Rich Lane21fd0112013-05-01 12:50:04 -070074 sample_match_buf = ''.join([
75 '\x00\x01', # type
76 '\x00\x3C', # length
77 '\x80\x00', # oxm_list[0].class
78 '\x20\x02', # oxm_list[0].type_len
79 '\x00\x35', # oxm_list[0].value
80 '\x80\x00', # oxm_list[1].class
81 '\x05\x10', # oxm_list[1].type_len
82 '\xFE\xDC\xBA\x98\x76\x54\x32\x10', # oxm_list[1].value
83 '\xFF\xFF\xFF\xFF\x12\x34\x56\x78', # oxm_list[1].mask
84 '\x80\x00', # oxm_list[2].class
85 '\x08\x06', # oxm_list[2].type_len
86 '\x01\x02\x03\x04\x05\x06', # oxm_list[2].value
87 '\x80\x00', # oxm_list[3].class
88 '\x36\x10', # oxm_list[3].type_len
89 '\x12' * 16, # oxm_list[3].value
90 '\x00' * 4, # padding
91 ])
92
93 def test_match_pack(self):
94 obj = ofp.match([
95 ofp.oxm.udp_dst(53),
96 ofp.oxm.metadata_masked(0xFEDCBA9876543210, 0xFFFFFFFF12345678),
97 ofp.oxm.eth_src([1,2,3,4,5,6]),
98 ofp.oxm.ipv6_dst("\x12" * 16),
99 ])
100 self.assertEquals(self.sample_match_buf, obj.pack())
101
102 def test_match_unpack(self):
103 obj = ofp.match.unpack(self.sample_match_buf)
104 self.assertEquals(len(obj.oxm_list), 4)
105 self.assertEquals(obj.oxm_list[0], ofp.oxm.udp_dst(53))
106 self.assertEquals(obj.oxm_list[1], ofp.oxm.metadata_masked(0xFEDCBA9876543210, 0xFFFFFFFF12345678))
107 self.assertEquals(obj.oxm_list[2], ofp.oxm.eth_src([1,2,3,4,5,6]))
108 self.assertEquals(obj.oxm_list[3], ofp.oxm.ipv6_dst("\x12" * 16))
109
Rich Lanea22233e2013-04-25 13:18:41 -0700110class TestOXM(unittest.TestCase):
111 def test_oxm_in_phy_port_pack(self):
112 import loxi.of12 as ofp
113 obj = ofp.oxm.in_phy_port(value=42)
114 expected = ''.join([
115 '\x80\x00', # class
116 '\x02', # type/masked
Rich Lane82e9f6e2013-04-25 17:32:22 -0700117 '\x04', # length
Rich Lanea22233e2013-04-25 13:18:41 -0700118 '\x00\x00\x00\x2a' # value
119 ])
120 self.assertEquals(expected, obj.pack())
121
122 def test_oxm_in_phy_port_masked_pack(self):
123 import loxi.of12 as ofp
124 obj = ofp.oxm.in_phy_port_masked(value=42, value_mask=0xaabbccdd)
125 expected = ''.join([
126 '\x80\x00', # class
127 '\x03', # type/masked
Rich Lane82e9f6e2013-04-25 17:32:22 -0700128 '\x08', # length
Rich Lanea22233e2013-04-25 13:18:41 -0700129 '\x00\x00\x00\x2a', # value
130 '\xaa\xbb\xcc\xdd' # mask
131 ])
132 self.assertEquals(expected, obj.pack())
133
134 def test_oxm_ipv6_dst_pack(self):
135 import loxi.of12 as ofp
136 obj = ofp.oxm.ipv6_dst(value='\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0d\x0f')
137 expected = ''.join([
138 '\x80\x00', # class
139 '\x36', # type/masked
Rich Lane82e9f6e2013-04-25 17:32:22 -0700140 '\x10', # length
Rich Lanea22233e2013-04-25 13:18:41 -0700141 '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0d\x0f', # value
142 ])
143 self.assertEquals(expected, obj.pack())
144
145class TestAllOF12(unittest.TestCase):
146 """
147 Round-trips every class through serialization/deserialization.
148 Not a replacement for handcoded tests because it only uses the
149 default member values.
150 """
151
152 def setUp(self):
153 mods = [ofp.action,ofp.message,ofp.common,ofp.oxm]
154 self.klasses = [klass for mod in mods
155 for klass in mod.__dict__.values()
156 if hasattr(klass, 'show')]
157 self.klasses.sort(key=lambda x: str(x))
158
159 def test_serialization(self):
Rich Laneadb79832013-05-02 17:14:33 -0700160 expected_failures = []
Rich Lanea22233e2013-04-25 13:18:41 -0700161 for klass in self.klasses:
162 def fn():
163 obj = klass()
164 if hasattr(obj, "xid"): obj.xid = 42
165 buf = obj.pack()
166 obj2 = klass.unpack(buf)
167 self.assertEquals(obj, obj2)
168 if klass in expected_failures:
169 self.assertRaises(Exception, fn)
170 else:
171 fn()
172
173 def test_show(self):
Rich Laneadb79832013-05-02 17:14:33 -0700174 expected_failures = []
Rich Lanea22233e2013-04-25 13:18:41 -0700175 for klass in self.klasses:
176 def fn():
177 obj = klass()
178 if hasattr(obj, "xid"): obj.xid = 42
179 obj.show()
180 if klass in expected_failures:
181 self.assertRaises(Exception, fn)
182 else:
183 fn()
184
185if __name__ == '__main__':
186 unittest.main()