blob: 753d3c50189ec13bb0e2a2a3713755b3507cfcc2 [file] [log] [blame]
Rich Lane3f075972013-03-15 22:56:29 -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
Rich Lane1d5b0102013-05-10 16:28:17 -070029from testutil import test_serialization
Rich Lanec9fc57d2013-05-16 16:39:12 -070030from testutil import add_datafiles_tests
Rich Lane3f075972013-03-15 22:56:29 -070031
32try:
33 import loxi.of13 as ofp
Rich Lane57026dc2013-05-01 10:13:16 -070034 from loxi.generic_util import OFReader
Rich Lane3f075972013-03-15 22:56:29 -070035except ImportError:
36 exit("loxi package not found. Try setting PYTHONPATH.")
37
38class TestImports(unittest.TestCase):
39 def test_toplevel(self):
40 import loxi
41 self.assertTrue(hasattr(loxi, "ProtocolError"))
Rich Lane00549ea2013-04-25 13:33:16 -070042 self.assertEquals(loxi.version_names[4], "1.3")
Rich Lane3f075972013-03-15 22:56:29 -070043 ofp = loxi.protocol(4)
44 self.assertEquals(ofp.OFP_VERSION, 4)
45 self.assertTrue(hasattr(ofp, "action"))
46 self.assertTrue(hasattr(ofp, "common"))
47 self.assertTrue(hasattr(ofp, "const"))
48 self.assertTrue(hasattr(ofp, "message"))
Rich Lanea22233e2013-04-25 13:18:41 -070049 self.assertTrue(hasattr(ofp, "oxm"))
Rich Lane3f075972013-03-15 22:56:29 -070050
51 def test_version(self):
52 import loxi
53 self.assertTrue(hasattr(loxi.of13, "ProtocolError"))
54 self.assertTrue(hasattr(loxi.of13, "OFP_VERSION"))
55 self.assertEquals(loxi.of13.OFP_VERSION, 4)
56 self.assertTrue(hasattr(loxi.of13, "action"))
57 self.assertTrue(hasattr(loxi.of13, "common"))
58 self.assertTrue(hasattr(loxi.of13, "const"))
59 self.assertTrue(hasattr(loxi.of13, "message"))
Rich Lanea22233e2013-04-25 13:18:41 -070060 self.assertTrue(hasattr(loxi.of13, "oxm"))
Rich Lane3f075972013-03-15 22:56:29 -070061
Rich Lanee90685c2013-04-05 17:27:41 -070062class TestCommon(unittest.TestCase):
Rich Lanee90685c2013-04-05 17:27:41 -070063 def test_list_hello_elem_unpack(self):
64 buf = ''.join([
65 '\x00\x01\x00\x04', # versionbitmap
66 '\x00\x00\x00\x04', # unknown type
67 '\x00\x01\x00\x04', # versionbitmap
68 ])
Rich Lane57026dc2013-05-01 10:13:16 -070069 l = ofp.unpack_list_hello_elem(OFReader(buf))
Rich Lanee90685c2013-04-05 17:27:41 -070070 self.assertEquals(len(l), 2)
71 self.assertTrue(isinstance(l[0], ofp.hello_elem_versionbitmap))
72 self.assertTrue(isinstance(l[1], ofp.hello_elem_versionbitmap))
73
Rich Lanec9fc57d2013-05-16 16:39:12 -070074# The majority of the serialization tests are created here using the files in
75# the test_data directory.
76class TestDataFiles(unittest.TestCase):
77 pass
78add_datafiles_tests(TestDataFiles, 'of13/', ofp)
Rich Lanee02314c2013-05-02 16:42:04 -070079
Rich Lane3f075972013-03-15 22:56:29 -070080class TestAllOF13(unittest.TestCase):
81 """
82 Round-trips every class through serialization/deserialization.
83 Not a replacement for handcoded tests because it only uses the
84 default member values.
85 """
86
87 def setUp(self):
Rich Laneea693752013-03-18 11:05:45 -070088 mods = [ofp.action,ofp.message,ofp.common,ofp.oxm]
Rich Lane3f075972013-03-15 22:56:29 -070089 self.klasses = [klass for mod in mods
90 for klass in mod.__dict__.values()
91 if hasattr(klass, 'show')]
92 self.klasses.sort(key=lambda x: str(x))
93
94 def test_serialization(self):
95 expected_failures = [
Rich Lane8692ecd2013-05-02 11:33:53 -070096 ofp.common.table_feature_prop_apply_actions,
97 ofp.common.table_feature_prop_apply_actions_miss,
Rich Lane8692ecd2013-05-02 11:33:53 -070098 ofp.common.table_feature_prop_write_actions,
99 ofp.common.table_feature_prop_write_actions_miss,
100 ofp.common.table_features,
Rich Lane3f075972013-03-15 22:56:29 -0700101 ofp.message.table_features_stats_reply,
102 ofp.message.table_features_stats_request,
103 ]
104 for klass in self.klasses:
105 def fn():
106 obj = klass()
107 if hasattr(obj, "xid"): obj.xid = 42
108 buf = obj.pack()
109 obj2 = klass.unpack(buf)
110 self.assertEquals(obj, obj2)
111 if klass in expected_failures:
112 self.assertRaises(Exception, fn)
113 else:
114 fn()
115
Rich Lane65790d22013-06-14 00:08:52 -0700116 def test_parse_message(self):
117 expected_failures = [
118 ofp.message.aggregate_stats_reply,
119 ofp.message.aggregate_stats_request,
120 ofp.message.bsn_bw_clear_data_reply,
121 ofp.message.bsn_bw_clear_data_request,
122 ofp.message.bsn_bw_enable_get_reply,
123 ofp.message.bsn_bw_enable_get_request,
124 ofp.message.bsn_bw_enable_set_reply,
125 ofp.message.bsn_bw_enable_set_request,
126 ofp.message.bsn_get_interfaces_reply,
127 ofp.message.bsn_get_interfaces_request,
128 ofp.message.bsn_get_mirroring_reply,
129 ofp.message.bsn_get_mirroring_request,
130 ofp.message.bsn_set_mirroring,
131 ofp.message.bsn_set_pktin_suppression_reply,
132 ofp.message.bsn_set_pktin_suppression_request,
133 ofp.message.bsn_virtual_port_create_reply,
134 ofp.message.bsn_virtual_port_create_request,
135 ofp.message.bsn_virtual_port_remove_reply,
136 ofp.message.bsn_virtual_port_remove_request,
137 ofp.message.desc_stats_reply,
138 ofp.message.desc_stats_request,
139 ofp.message.flow_add,
140 ofp.message.flow_delete,
141 ofp.message.flow_delete_strict,
142 ofp.message.flow_modify,
143 ofp.message.flow_modify_strict,
144 ofp.message.flow_stats_reply,
145 ofp.message.flow_stats_request,
146 ofp.message.group_desc_stats_reply,
147 ofp.message.group_desc_stats_request,
148 ofp.message.group_features_stats_reply,
149 ofp.message.group_features_stats_request,
150 ofp.message.group_stats_reply,
151 ofp.message.group_stats_request,
152 ofp.message.meter_config_stats_reply,
153 ofp.message.meter_config_stats_request,
154 ofp.message.meter_features_stats_reply,
155 ofp.message.meter_features_stats_request,
156 ofp.message.meter_stats_reply,
157 ofp.message.meter_stats_request,
158 ofp.message.port_desc_stats_reply,
159 ofp.message.port_desc_stats_request,
160 ofp.message.port_stats_reply,
161 ofp.message.port_stats_request,
162 ofp.message.queue_stats_reply,
163 ofp.message.queue_stats_request,
164 ofp.message.table_features_stats_reply,
165 ofp.message.table_features_stats_request,
166 ofp.message.table_stats_reply,
167 ofp.message.table_stats_request,
168 ]
169 for klass in self.klasses:
170 if not issubclass(klass, ofp.message.Message):
171 continue
172 def fn():
173 obj = klass(xid=42)
174 buf = obj.pack()
175 obj2 = ofp.message.parse_message(buf)
176 self.assertEquals(obj, obj2)
177 if klass in expected_failures:
178 self.assertRaises(Exception, fn)
179 else:
180 fn()
181
Rich Lane3f075972013-03-15 22:56:29 -0700182 def test_show(self):
Rich Lane8ca3b772013-04-30 13:36:55 -0700183 expected_failures = []
Rich Lane3f075972013-03-15 22:56:29 -0700184 for klass in self.klasses:
185 def fn():
186 obj = klass()
187 if hasattr(obj, "xid"): obj.xid = 42
188 obj.show()
189 if klass in expected_failures:
190 self.assertRaises(Exception, fn)
191 else:
192 fn()
193
194if __name__ == '__main__':
195 unittest.main()