backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / unit / ofproto / test_parser.py
1 # Copyright (C) 2013,2014,2015 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013,2014,2015 YAMAMOTO Takashi <yamamoto at valinux co jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 from __future__ import print_function
18
19 import six
20 import sys
21 import unittest
22 from nose.tools import eq_
23
24 from ryu.ofproto import ofproto_parser
25 from ryu.ofproto import ofproto_protocol
26 from ryu.ofproto import ofproto_v1_0
27 from ryu.ofproto import ofproto_v1_2
28 from ryu.ofproto import ofproto_v1_3
29 from ryu.ofproto import ofproto_v1_4
30 from ryu.ofproto import ofproto_v1_5
31 from ryu.tests import test_lib
32 from ryu import exception
33 import json
34
35
36 # (has_parser, has_serializer)
37 implemented = {
38     1: {
39         ofproto_v1_0.OFPT_PACKET_OUT: (False, True),
40         ofproto_v1_0.OFPT_FEATURES_REQUEST: (False, True),
41         ofproto_v1_0.OFPT_FEATURES_REPLY: (True, False),
42         ofproto_v1_0.OFPT_PACKET_IN: (True, False),
43         ofproto_v1_0.OFPT_FLOW_MOD: (True, True),
44     },
45     3: {
46         ofproto_v1_2.OFPT_FEATURES_REQUEST: (False, True),
47         ofproto_v1_2.OFPT_FEATURES_REPLY: (True, False),
48         ofproto_v1_2.OFPT_GET_CONFIG_REQUEST: (False, True),
49         ofproto_v1_2.OFPT_GET_CONFIG_REPLY: (True, False),
50         ofproto_v1_2.OFPT_SET_CONFIG: (False, True),
51         ofproto_v1_2.OFPT_PACKET_IN: (True, False),
52         ofproto_v1_2.OFPT_FLOW_REMOVED: (True, False),
53         ofproto_v1_2.OFPT_PORT_STATUS: (True, False),
54         ofproto_v1_2.OFPT_PACKET_OUT: (False, True),
55         ofproto_v1_2.OFPT_FLOW_MOD: (True, True),
56         ofproto_v1_2.OFPT_GROUP_MOD: (False, True),
57         ofproto_v1_2.OFPT_PORT_MOD: (False, True),
58         ofproto_v1_2.OFPT_TABLE_MOD: (False, True),
59         ofproto_v1_2.OFPT_STATS_REQUEST: (False, True),
60         ofproto_v1_2.OFPT_STATS_REPLY: (True, False),
61         ofproto_v1_2.OFPT_BARRIER_REQUEST: (False, True),
62         ofproto_v1_2.OFPT_QUEUE_GET_CONFIG_REQUEST: (False, True),
63         ofproto_v1_2.OFPT_QUEUE_GET_CONFIG_REPLY: (True, False),
64         ofproto_v1_2.OFPT_ROLE_REQUEST: (False, True),
65         ofproto_v1_2.OFPT_ROLE_REPLY: (True, False),
66     },
67     4: {
68         ofproto_v1_3.OFPT_HELLO: (True, False),
69         ofproto_v1_3.OFPT_FEATURES_REQUEST: (False, True),
70         ofproto_v1_3.OFPT_FEATURES_REPLY: (True, False),
71         ofproto_v1_3.OFPT_GET_CONFIG_REQUEST: (False, True),
72         ofproto_v1_3.OFPT_GET_CONFIG_REPLY: (True, False),
73         ofproto_v1_3.OFPT_SET_CONFIG: (False, True),
74         ofproto_v1_3.OFPT_PACKET_IN: (True, False),
75         ofproto_v1_3.OFPT_FLOW_REMOVED: (True, False),
76         ofproto_v1_3.OFPT_PORT_STATUS: (True, False),
77         ofproto_v1_3.OFPT_PACKET_OUT: (False, True),
78         ofproto_v1_3.OFPT_FLOW_MOD: (True, True),
79         ofproto_v1_3.OFPT_GROUP_MOD: (False, True),
80         ofproto_v1_3.OFPT_PORT_MOD: (False, True),
81         ofproto_v1_3.OFPT_METER_MOD: (False, True),
82         ofproto_v1_3.OFPT_TABLE_MOD: (False, True),
83         ofproto_v1_3.OFPT_MULTIPART_REQUEST: (False, True),
84         ofproto_v1_3.OFPT_MULTIPART_REPLY: (True, False),
85         ofproto_v1_3.OFPT_BARRIER_REQUEST: (False, True),
86         ofproto_v1_3.OFPT_QUEUE_GET_CONFIG_REQUEST: (False, True),
87         ofproto_v1_3.OFPT_QUEUE_GET_CONFIG_REPLY: (True, False),
88         ofproto_v1_3.OFPT_ROLE_REQUEST: (False, True),
89         ofproto_v1_3.OFPT_ROLE_REPLY: (True, False),
90         ofproto_v1_3.OFPT_GET_ASYNC_REQUEST: (False, True),
91         ofproto_v1_3.OFPT_GET_ASYNC_REPLY: (True, False),
92         ofproto_v1_3.OFPT_SET_ASYNC: (False, True),
93     },
94     5: {
95         ofproto_v1_4.OFPT_HELLO: (True, False),
96         ofproto_v1_4.OFPT_FEATURES_REQUEST: (False, True),
97         ofproto_v1_4.OFPT_FEATURES_REPLY: (True, False),
98         ofproto_v1_4.OFPT_GET_CONFIG_REQUEST: (False, True),
99         ofproto_v1_4.OFPT_GET_CONFIG_REPLY: (True, False),
100         ofproto_v1_4.OFPT_SET_CONFIG: (False, True),
101         ofproto_v1_4.OFPT_PACKET_IN: (True, False),
102         ofproto_v1_4.OFPT_FLOW_REMOVED: (True, False),
103         ofproto_v1_4.OFPT_PORT_STATUS: (True, False),
104         ofproto_v1_4.OFPT_PACKET_OUT: (False, True),
105         ofproto_v1_4.OFPT_FLOW_MOD: (True, True),
106         ofproto_v1_4.OFPT_GROUP_MOD: (True, True),
107         ofproto_v1_4.OFPT_PORT_MOD: (False, True),
108         ofproto_v1_4.OFPT_METER_MOD: (True, True),
109         ofproto_v1_4.OFPT_TABLE_MOD: (False, True),
110         ofproto_v1_4.OFPT_MULTIPART_REQUEST: (False, True),
111         ofproto_v1_4.OFPT_MULTIPART_REPLY: (True, False),
112         ofproto_v1_4.OFPT_BARRIER_REQUEST: (False, True),
113         ofproto_v1_4.OFPT_ROLE_REQUEST: (False, True),
114         ofproto_v1_4.OFPT_ROLE_REPLY: (True, False),
115         ofproto_v1_4.OFPT_GET_ASYNC_REQUEST: (False, True),
116         ofproto_v1_4.OFPT_GET_ASYNC_REPLY: (True, False),
117         ofproto_v1_4.OFPT_SET_ASYNC: (False, True),
118         ofproto_v1_4.OFPT_ROLE_STATUS: (True, False),
119         ofproto_v1_4.OFPT_TABLE_STATUS: (True, False),
120         ofproto_v1_4.OFPT_REQUESTFORWARD: (True, True),
121         ofproto_v1_4.OFPT_BUNDLE_CONTROL: (True, True),
122         ofproto_v1_4.OFPT_BUNDLE_ADD_MESSAGE: (False, True),
123     },
124     6: {
125         ofproto_v1_5.OFPT_HELLO: (True, False),
126         ofproto_v1_5.OFPT_FEATURES_REQUEST: (False, True),
127         ofproto_v1_5.OFPT_FEATURES_REPLY: (True, False),
128         ofproto_v1_5.OFPT_GET_CONFIG_REQUEST: (False, True),
129         ofproto_v1_5.OFPT_GET_CONFIG_REPLY: (True, False),
130         ofproto_v1_5.OFPT_SET_CONFIG: (False, True),
131         ofproto_v1_5.OFPT_PACKET_IN: (True, False),
132         ofproto_v1_5.OFPT_FLOW_REMOVED: (True, False),
133         ofproto_v1_5.OFPT_PORT_STATUS: (True, False),
134         ofproto_v1_5.OFPT_PACKET_OUT: (False, True),
135         ofproto_v1_5.OFPT_FLOW_MOD: (True, True),
136         ofproto_v1_5.OFPT_GROUP_MOD: (True, True),
137         ofproto_v1_5.OFPT_PORT_MOD: (False, True),
138         ofproto_v1_5.OFPT_METER_MOD: (True, True),
139         ofproto_v1_5.OFPT_TABLE_MOD: (False, True),
140         ofproto_v1_5.OFPT_MULTIPART_REQUEST: (False, True),
141         ofproto_v1_5.OFPT_MULTIPART_REPLY: (True, False),
142         ofproto_v1_5.OFPT_BARRIER_REQUEST: (False, True),
143         ofproto_v1_5.OFPT_ROLE_REQUEST: (False, True),
144         ofproto_v1_5.OFPT_ROLE_REPLY: (True, False),
145         ofproto_v1_5.OFPT_GET_ASYNC_REQUEST: (False, True),
146         ofproto_v1_5.OFPT_GET_ASYNC_REPLY: (True, False),
147         ofproto_v1_5.OFPT_SET_ASYNC: (False, True),
148         ofproto_v1_5.OFPT_ROLE_STATUS: (True, False),
149         ofproto_v1_5.OFPT_TABLE_STATUS: (True, False),
150         ofproto_v1_5.OFPT_REQUESTFORWARD: (True, True),
151         ofproto_v1_5.OFPT_BUNDLE_CONTROL: (True, True),
152         ofproto_v1_5.OFPT_BUNDLE_ADD_MESSAGE: (False, True),
153         ofproto_v1_5.OFPT_CONTROLLER_STATUS: (True, False),
154     },
155 }
156
157
158 class Test_Parser(unittest.TestCase):
159     """ Test case for ryu.ofproto, especially json representation
160     """
161
162     def __init__(self, methodName):
163         print('init %s' % methodName)
164         super(Test_Parser, self).__init__(methodName)
165
166     def setUp(self):
167         pass
168
169     def tearDown(self):
170         pass
171
172     @staticmethod
173     def _msg_to_jsondict(msg):
174         return msg.to_jsondict()
175
176     @staticmethod
177     def _jsondict_to_msg(dp, jsondict):
178         return ofproto_parser.ofp_msg_from_jsondict(dp, jsondict)
179
180     def _test_msg(self, name, wire_msg, json_str):
181         def bytes_eq(buf1, buf2):
182             if buf1 != buf2:
183                 msg = 'EOF in either data'
184                 for i in range(0, min(len(buf1), len(buf2))):
185                     c1 = six.indexbytes(six.binary_type(buf1), i)
186                     c2 = six.indexbytes(six.binary_type(buf2), i)
187                     if c1 != c2:
188                         msg = 'differs at chr %d, %d != %d' % (i, c1, c2)
189                         break
190                 assert buf1 == buf2, "%r != %r, %s" % (buf1, buf2, msg)
191
192         json_dict = json.loads(json_str)
193         # on-wire -> OFPxxx -> json
194         (version, msg_type, msg_len, xid) = ofproto_parser.header(wire_msg)
195         try:
196             has_parser, has_serializer = implemented[version][msg_type]
197         except KeyError:
198             has_parser = True
199             has_serializer = True
200
201         dp = ofproto_protocol.ProtocolDesc(version=version)
202         if has_parser:
203             try:
204                 msg = ofproto_parser.msg(dp, version, msg_type, msg_len, xid,
205                                          wire_msg)
206                 json_dict2 = self._msg_to_jsondict(msg)
207             except exception.OFPTruncatedMessage as e:
208                 json_dict2 = {'OFPTruncatedMessage':
209                               self._msg_to_jsondict(e.ofpmsg)}
210             # XXXdebug code
211             open(('/tmp/%s.json' % name), 'w').write(json.dumps(json_dict2))
212             eq_(json_dict, json_dict2)
213             if 'OFPTruncatedMessage' in json_dict2:
214                 return
215
216         # json -> OFPxxx -> json
217         xid = json_dict[list(json_dict.keys())[0]].pop('xid', None)
218         msg2 = self._jsondict_to_msg(dp, json_dict)
219         msg2.set_xid(xid)
220         if has_serializer:
221             msg2.serialize()
222             eq_(self._msg_to_jsondict(msg2), json_dict)
223             bytes_eq(wire_msg, msg2.buf)
224
225             # check if "len" "length" fields can be omitted
226
227             def _remove(d, names):
228                 f = lambda x: _remove(x, names)
229                 if isinstance(d, list):
230                     return list(map(f, d))
231                 if isinstance(d, dict):
232                     d2 = {}
233                     for k, v in d.items():
234                         if k in names:
235                             continue
236                         d2[k] = f(v)
237                     return d2
238                 return d
239
240             json_dict3 = _remove(json_dict, ['len', 'length'])
241             msg3 = self._jsondict_to_msg(dp, json_dict3)
242             msg3.set_xid(xid)
243             msg3.serialize()
244             bytes_eq(wire_msg, msg3.buf)
245
246             msg2.serialize()
247             bytes_eq(wire_msg, msg2.buf)
248
249
250 def _add_tests():
251     import os
252     import os.path
253     import functools
254
255     this_dir = os.path.dirname(sys.modules[__name__].__file__)
256     packet_data_dir = os.path.join(this_dir, '../../packet_data')
257     json_dir = os.path.join(this_dir, 'json')
258     ofvers = [
259         'of10',
260         'of12',
261         'of13',
262         'of14',
263         'of15',
264     ]
265     cases = set()
266     for ver in ofvers:
267         pdir = packet_data_dir + '/' + ver
268         jdir = json_dir + '/' + ver
269         n_added = 0
270         for file in os.listdir(pdir):
271             if file.endswith('.packet'):
272                 truncated = None
273             elif '.truncated' in file:
274                 # contents of .truncated files aren't relevant
275                 s1, s2 = file.split('.truncated')
276                 try:
277                     truncated = int(s2)
278                 except ValueError:
279                     continue
280                 file = s1 + '.packet'
281             else:
282                 continue
283             wire_msg = open(pdir + '/' + file, 'rb').read()
284             if not truncated:
285                 json_str = open(jdir + '/' + file + '.json', 'r').read()
286             else:
287                 json_str = open(jdir + '/' + file +
288                                 '.truncated%d.json' % truncated, 'r').read()
289                 wire_msg = wire_msg[:truncated]
290             method_name = ('test_' + file).replace('-', '_').replace('.', '_')
291             if truncated:
292                 method_name += '_truncated%d' % truncated
293
294             def _run(self, name, wire_msg, json_str):
295                 print('processing %s ...' % name)
296                 if six.PY3:
297                     self._test_msg(self, name, wire_msg, json_str)
298                 else:
299                     self._test_msg(name, wire_msg, json_str)
300             print('adding %s ...' % method_name)
301             f = functools.partial(_run, name=method_name, wire_msg=wire_msg,
302                                   json_str=json_str)
303             test_lib.add_method(Test_Parser, method_name, f)
304             cases.add(method_name)
305             n_added += 1
306         assert n_added > 0
307     assert (cases ==
308             set(unittest.defaultTestLoader.getTestCaseNames(Test_Parser)))
309
310
311 _add_tests()