backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / unit / lib / test_ofctl.py
1 # Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import functools
17 import json
18 import logging
19 from nose.tools import eq_
20 import os
21 import sys
22 import unittest
23
24 from ryu.lib import ofctl_v1_0
25 from ryu.lib import ofctl_v1_2
26 from ryu.lib import ofctl_v1_3
27 from ryu.lib import ofctl_v1_4
28 from ryu.lib import ofctl_v1_5
29 from ryu.ofproto import ofproto_parser
30 from ryu.ofproto.ofproto_protocol import ProtocolDesc
31 from ryu.tests import test_lib
32
33 LOG = logging.getLogger(__name__)
34
35
36 class DummyDatapath(ProtocolDesc):
37
38     def __init__(self, version):
39         super(DummyDatapath, self).__init__(version)
40         self.id = 1  # XXX
41         self.request_msg = None
42         self.reply_msg = None
43         self.waiters = None
44
45     @staticmethod
46     def set_xid(msg):
47         msg.set_xid(0)
48         return 0
49
50     def send_msg(self, msg):
51         msg.serialize()
52         self.request_msg = msg
53
54         if self.reply_msg:
55             lock, msgs = self.waiters[self.id][msg.xid]
56             msgs.append(self.reply_msg)
57             del self.waiters[self.id][msg.xid]
58             lock.set()
59
60     def set_reply(self, msg, waiters):
61         self.reply_msg = msg
62         self.waiters = waiters
63
64
65 class Test_ofctl(unittest.TestCase):
66
67     def _test(self, name, dp, method, args, request, reply, expected):
68         print('processing %s ...' % name)
69         waiters = {}
70         dp.set_reply(reply, waiters)
71         if reply:
72             output = method(dp=dp, waiters=waiters, **args)
73         else:
74             output = method(dp=dp, **args)
75
76         # expected message <--> sent message
77         request.serialize()
78         try:
79             eq_(json.dumps(request.to_jsondict(), sort_keys=True),
80                 json.dumps(dp.request_msg.to_jsondict(), sort_keys=True))
81         except AssertionError as e:
82             # For debugging
83             json.dump(dp.request_msg.to_jsondict(),
84                       open('/tmp/' + name + '_request.json', 'w'),
85                       indent=3, sort_keys=True)
86             raise e
87
88         # expected output <--> return of ofctl
89         def _remove(d, names):
90             def f(x):
91                 return _remove(x, names)
92
93             if isinstance(d, list):
94                 return list(map(f, d))
95             if isinstance(d, dict):
96                 d2 = {}
97                 for k, v in d.items():
98                     if k in names:
99                         continue
100                     d2[k] = f(v)
101                 return d2
102             return d
103
104         expected = _remove(expected, ['len', 'length'])
105         output = _remove(output, ['len', 'length'])
106         try:
107             eq_(json.dumps(expected, sort_keys=True),
108                 json.dumps(output, sort_keys=True))
109         except AssertionError as e:
110             # For debugging
111             json.dump(output, open('/tmp/' + name + '_reply.json', 'w'),
112                       indent=4)
113             raise e
114
115
116 def _add_tests():
117     _ofp_vers = {
118         'of10': 0x01,
119         'of12': 0x03,
120         'of13': 0x04,
121         'of14': 0x05,
122         'of15': 0x06,
123     }
124
125     _test_cases = {
126         'of10': [
127             {
128                 'method': ofctl_v1_0.mod_flow_entry,
129                 'request': '1-2-ofp_flow_mod.packet.json',
130                 'reply': None
131             },
132         ],
133         'of12': [
134             {
135                 'method': ofctl_v1_2.get_desc_stats,
136                 'request': '3-24-ofp_desc_stats_request.packet.json',
137                 'reply': '3-0-ofp_desc_stats_reply.packet.json'
138             },
139             {
140                 'method': ofctl_v1_2.get_queue_stats,
141                 'request': '3-37-ofp_queue_stats_request.packet.json',
142                 'reply': '3-38-ofp_queue_stats_reply.packet.json'
143             },
144             {
145                 'method': ofctl_v1_2.get_queue_stats,
146                 'request': 'lib-ofctl-ofp_queue_stats_request.packet1.json',
147                 'reply': '3-38-ofp_queue_stats_reply.packet.json'
148             },
149             {
150                 'method': ofctl_v1_2.get_queue_stats,
151                 'request': 'lib-ofctl-ofp_queue_stats_request.packet2.json',
152                 'reply': '3-38-ofp_queue_stats_reply.packet.json'
153             },
154             {
155                 'method': ofctl_v1_2.get_queue_stats,
156                 'request': 'lib-ofctl-ofp_queue_stats_request.packet3.json',
157                 'reply': '3-38-ofp_queue_stats_reply.packet.json'
158             },
159             {
160                 'method': ofctl_v1_2.get_queue_config,
161                 'request': '3-35-ofp_queue_get_config_request.packet.json',
162                 'reply': '3-36-ofp_queue_get_config_reply.packet.json'
163             },
164             {
165                 'method': ofctl_v1_2.get_queue_config,
166                 'request': 'lib-ofctl-ofp_queue_get_config_request.packet.json',
167                 'reply': '3-36-ofp_queue_get_config_reply.packet.json'
168             },
169             {
170                 'method': ofctl_v1_2.get_flow_stats,
171                 'request': '3-11-ofp_flow_stats_request.packet.json',
172                 'reply': '3-12-ofp_flow_stats_reply.packet.json'
173             },
174             {
175                 'method': ofctl_v1_2.get_aggregate_flow_stats,
176                 'request': '3-25-ofp_aggregate_stats_request.packet.json',
177                 'reply': '3-26-ofp_aggregate_stats_reply.packet.json'
178             },
179             {
180                 'method': ofctl_v1_2.get_table_stats,
181                 'request': '3-27-ofp_table_stats_request.packet.json',
182                 'reply': '3-28-ofp_table_stats_reply.packet.json'
183             },
184             {
185                 'method': ofctl_v1_2.get_port_stats,
186                 'request': '3-29-ofp_port_stats_request.packet.json',
187                 'reply': '3-30-ofp_port_stats_reply.packet.json'
188             },
189             {
190                 'method': ofctl_v1_2.get_port_stats,
191                 'request': 'lib-ofctl-ofp_port_stats_request.packet.json',
192                 'reply': '3-30-ofp_port_stats_reply.packet.json'
193             },
194             {
195                 'method': ofctl_v1_2.get_group_stats,
196                 'request': '3-61-ofp_group_stats_request.packet.json',
197                 'reply': '3-62-ofp_group_stats_reply.packet.json'
198             },
199             {
200                 'method': ofctl_v1_2.get_group_stats,
201                 'request': 'lib-ofctl-ofp_group_stats_request.packet.json',
202                 'reply': '3-62-ofp_group_stats_reply.packet.json'
203             },
204             {
205                 'method': ofctl_v1_2.get_group_features,
206                 'request': '3-31-ofp_group_features_stats_request.packet.json',
207                 'reply': '3-32-ofp_group_features_stats_reply.packet.json'
208             },
209             {
210                 'method': ofctl_v1_2.get_group_desc,
211                 'request': '3-33-ofp_group_desc_stats_request.packet.json',
212                 'reply': '3-34-ofp_group_desc_stats_reply.packet.json'
213             },
214             # In OpenFlow 1.2, ofp_port_desc is not defined.
215             # We use ofp_features_request to get ports description instead.
216             {
217                 'method': ofctl_v1_2.get_port_desc,
218                 'request': '3-5-ofp_features_request.packet.json',
219                 'reply': '3-6-ofp_features_reply.packet.json'
220             },
221             {
222                 'method': ofctl_v1_2.mod_flow_entry,
223                 'request': '3-2-ofp_flow_mod.packet.json',
224                 'reply': None
225             },
226             {
227                 'method': ofctl_v1_2.mod_group_entry,
228                 'request': '3-21-ofp_group_mod.packet.json',
229                 'reply': None
230             },
231             {
232                 'method': ofctl_v1_2.mod_port_behavior,
233                 'request': '3-22-ofp_port_mod.packet.json',
234                 'reply': None
235             },
236             {
237                 'method': ofctl_v1_2.send_experimenter,
238                 'request': '3-16-ofp_experimenter.packet.json',
239                 'reply': None
240             },
241         ],
242         'of13': [
243             {
244                 'method': ofctl_v1_3.get_desc_stats,
245                 'request': '4-24-ofp_desc_request.packet.json',
246                 'reply': '4-0-ofp_desc_reply.packet.json'
247             },
248             {
249                 'method': ofctl_v1_3.get_queue_stats,
250                 'request': '4-37-ofp_queue_stats_request.packet.json',
251                 'reply': '4-38-ofp_queue_stats_reply.packet.json'
252             },
253             {
254                 'method': ofctl_v1_3.get_queue_stats,
255                 'request': 'lib-ofctl-ofp_queue_stats_request.packet1.json',
256                 'reply': '4-38-ofp_queue_stats_reply.packet.json'
257             },
258             {
259                 'method': ofctl_v1_3.get_queue_stats,
260                 'request': 'lib-ofctl-ofp_queue_stats_request.packet2.json',
261                 'reply': '4-38-ofp_queue_stats_reply.packet.json'
262             },
263             {
264                 'method': ofctl_v1_3.get_queue_stats,
265                 'request': 'lib-ofctl-ofp_queue_stats_request.packet3.json',
266                 'reply': '4-38-ofp_queue_stats_reply.packet.json'
267             },
268             {
269                 'method': ofctl_v1_3.get_queue_config,
270                 'request': '4-35-ofp_queue_get_config_request.packet.json',
271                 'reply': '4-36-ofp_queue_get_config_reply.packet.json'
272             },
273             {
274                 'method': ofctl_v1_3.get_queue_config,
275                 'request': 'lib-ofctl-ofp_queue_get_config_request.packet.json',
276                 'reply': '4-36-ofp_queue_get_config_reply.packet.json'
277             },
278             {
279                 'method': ofctl_v1_3.get_flow_stats,
280                 'request': '4-11-ofp_flow_stats_request.packet.json',
281                 'reply': '4-12-ofp_flow_stats_reply.packet.json'
282             },
283             {
284                 'method': ofctl_v1_3.get_aggregate_flow_stats,
285                 'request': '4-25-ofp_aggregate_stats_request.packet.json',
286                 'reply': '4-26-ofp_aggregate_stats_reply.packet.json'
287             },
288             {
289                 'method': ofctl_v1_3.get_table_stats,
290                 'request': '4-27-ofp_table_stats_request.packet.json',
291                 'reply': '4-28-ofp_table_stats_reply.packet.json'
292             },
293             {
294                 'method': ofctl_v1_3.get_table_features,
295                 'request': 'lib-ofctl-ofp_table_features_request.packet.json',
296                 'reply': '4-56-ofp_table_features_reply.packet.json'
297             },
298             {
299                 'method': ofctl_v1_3.get_port_stats,
300                 'request': '4-29-ofp_port_stats_request.packet.json',
301                 'reply': '4-30-ofp_port_stats_reply.packet.json'
302             },
303             {
304                 'method': ofctl_v1_3.get_port_stats,
305                 'request': 'lib-ofctl-ofp_port_stats_request.packet.json',
306                 'reply': '4-30-ofp_port_stats_reply.packet.json'
307             },
308             {
309                 'method': ofctl_v1_3.get_meter_stats,
310                 'request': '4-49-ofp_meter_stats_request.packet.json',
311                 'reply': '4-50-ofp_meter_stats_reply.packet.json'
312             },
313             {
314                 'method': ofctl_v1_3.get_meter_stats,
315                 'request': 'lib-ofctl-ofp_meter_stats_request.packet.json',
316                 'reply': '4-50-ofp_meter_stats_reply.packet.json'
317             },
318             {
319                 'method': ofctl_v1_3.get_meter_features,
320                 'request': '4-51-ofp_meter_features_request.packet.json',
321                 'reply': '4-52-ofp_meter_features_reply.packet.json'
322             },
323             {
324                 'method': ofctl_v1_3.get_meter_config,
325                 'request': '4-47-ofp_meter_config_request.packet.json',
326                 'reply': '4-48-ofp_meter_config_reply.packet.json'
327             },
328             {
329                 'method': ofctl_v1_3.get_meter_config,
330                 'request': 'lib-ofctl-ofp_meter_config_request.packet.json',
331                 'reply': '4-48-ofp_meter_config_reply.packet.json'
332             },
333             {
334                 'method': ofctl_v1_3.get_group_stats,
335                 'request': '4-57-ofp_group_stats_request.packet.json',
336                 'reply': '4-58-ofp_group_stats_reply.packet.json'
337             },
338             {
339                 'method': ofctl_v1_3.get_group_stats,
340                 'request': 'lib-ofctl-ofp_group_stats_request.packet.json',
341                 'reply': '4-58-ofp_group_stats_reply.packet.json'
342             },
343             {
344                 'method': ofctl_v1_3.get_group_features,
345                 'request': '4-31-ofp_group_features_request.packet.json',
346                 'reply': '4-32-ofp_group_features_reply.packet.json'
347             },
348             {
349                 'method': ofctl_v1_3.get_group_desc,
350                 'request': '4-33-ofp_group_desc_request.packet.json',
351                 'reply': '4-34-ofp_group_desc_reply.packet.json'
352             },
353             {
354                 'method': ofctl_v1_3.get_port_desc,
355                 'request': '4-53-ofp_port_desc_request.packet.json',
356                 'reply': '4-54-ofp_port_desc_reply.packet.json'
357             },
358             {
359                 'method': ofctl_v1_3.mod_flow_entry,
360                 'request': '4-2-ofp_flow_mod.packet.json',
361                 'reply': None
362             },
363             {
364                 'method': ofctl_v1_3.mod_meter_entry,
365                 'request': '4-45-ofp_meter_mod.packet.json',
366                 'reply': None
367             },
368             {
369                 'method': ofctl_v1_3.mod_group_entry,
370                 'request': '4-21-ofp_group_mod.packet.json',
371                 'reply': None
372             },
373             {
374                 'method': ofctl_v1_3.mod_port_behavior,
375                 'request': '4-22-ofp_port_mod.packet.json',
376                 'reply': None
377             },
378             {
379                 'method': ofctl_v1_3.send_experimenter,
380                 'request': '4-16-ofp_experimenter.packet.json',
381                 'reply': None
382             },
383         ],
384         'of14': [
385             {
386                 'method': ofctl_v1_4.get_desc_stats,
387                 'request': '5-24-ofp_desc_request.packet.json',
388                 'reply': '5-0-ofp_desc_reply.packet.json'
389             },
390             {
391                 'method': ofctl_v1_4.get_queue_stats,
392                 'request': '5-35-ofp_queue_stats_request.packet.json',
393                 'reply': '5-36-ofp_queue_stats_reply.packet.json'
394             },
395             {
396                 'method': ofctl_v1_4.get_queue_desc,
397                 'request': '5-63-ofp_queue_desc_request.packet.json',
398                 'reply': '5-64-ofp_queue_desc_reply.packet.json'
399             },
400             {
401                 'method': ofctl_v1_4.get_flow_stats,
402                 'request': '5-11-ofp_flow_stats_request.packet.json',
403                 'reply': '5-12-ofp_flow_stats_reply.packet.json'
404             },
405             {
406                 'method': ofctl_v1_4.get_aggregate_flow_stats,
407                 'request': '5-25-ofp_aggregate_stats_request.packet.json',
408                 'reply': '5-26-ofp_aggregate_stats_reply.packet.json'
409             },
410             {
411                 'method': ofctl_v1_4.get_table_stats,
412                 'request': '5-27-ofp_table_stats_request.packet.json',
413                 'reply': '5-28-ofp_table_stats_reply.packet.json'
414             },
415             {
416                 'method': ofctl_v1_4.get_table_features,
417                 'request': 'lib-ofctl-ofp_table_features_request.packet.json',
418                 'reply': '5-54-ofp_table_features_reply.packet.json'
419             },
420             {
421                 'method': ofctl_v1_4.get_port_stats,
422                 'request': '5-29-ofp_port_stats_request.packet.json',
423                 'reply': '5-30-ofp_port_stats_reply.packet.json'
424             },
425             {
426                 'method': ofctl_v1_4.get_meter_stats,
427                 'request': '5-47-ofp_meter_stats_request.packet.json',
428                 'reply': '5-48-ofp_meter_stats_reply.packet.json'
429             },
430             {
431                 'method': ofctl_v1_4.get_meter_features,
432                 'request': '5-49-ofp_meter_features_request.packet.json',
433                 'reply': '5-50-ofp_meter_features_reply.packet.json'
434             },
435             {
436                 'method': ofctl_v1_4.get_meter_config,
437                 'request': '5-45-ofp_meter_config_request.packet.json',
438                 'reply': '5-46-ofp_meter_config_reply.packet.json'
439             },
440             {
441                 'method': ofctl_v1_4.get_group_stats,
442                 'request': '5-55-ofp_group_stats_request.packet.json',
443                 'reply': '5-56-ofp_group_stats_reply.packet.json'
444             },
445             {
446                 'method': ofctl_v1_4.get_group_features,
447                 'request': '5-31-ofp_group_features_request.packet.json',
448                 'reply': '5-32-ofp_group_features_reply.packet.json'
449             },
450             {
451                 'method': ofctl_v1_4.get_group_desc,
452                 'request': '5-33-ofp_group_desc_request.packet.json',
453                 'reply': '5-34-ofp_group_desc_reply.packet.json'
454             },
455             {
456                 'method': ofctl_v1_4.get_port_desc,
457                 'request': '5-51-ofp_port_desc_request.packet.json',
458                 'reply': '5-52-ofp_port_desc_reply.packet.json'
459             },
460             {
461                 'method': ofctl_v1_4.mod_flow_entry,
462                 'request': '5-2-ofp_flow_mod.packet.json',
463                 'reply': None
464             },
465             {
466                 'method': ofctl_v1_4.mod_meter_entry,
467                 'request': '5-43-ofp_meter_mod.packet.json',
468                 'reply': None
469             },
470             {
471                 'method': ofctl_v1_4.mod_group_entry,
472                 'request': '5-21-ofp_group_mod.packet.json',
473                 'reply': None
474             },
475             {
476                 'method': ofctl_v1_4.mod_port_behavior,
477                 'request': '5-22-ofp_port_mod.packet.json',
478                 'reply': None
479             },
480             {
481                 'method': ofctl_v1_4.send_experimenter,
482                 'request': '5-16-ofp_experimenter.packet.json',
483                 'reply': None
484             },
485         ],
486         'of15': [
487             {
488                 'method': ofctl_v1_5.get_desc_stats,
489                 'request': 'libofproto-OFP15-desc_request.packet.json',
490                 'reply': 'libofproto-OFP15-desc_reply.packet.json'
491             },
492             {
493                 'method': ofctl_v1_5.get_queue_stats,
494                 'request': 'lib-ofctl-ofp_queue_stats_request.packet.json',
495                 'reply': 'libofproto-OFP15-queue_stats_reply.packet.json'
496             },
497             {
498                 'method': ofctl_v1_5.get_queue_desc,
499                 'request': 'libofproto-OFP15-queue_desc_request.packet.json',
500                 'reply': 'libofproto-OFP15-queue_desc_reply.packet.json'
501             },
502             {
503                 'method': ofctl_v1_5.get_flow_stats,
504                 'request': 'libofproto-OFP15-flow_stats_request.packet.json',
505                 'reply': 'libofproto-OFP15-flow_stats_reply.packet.json'
506             },
507             {
508                 'method': ofctl_v1_5.get_flow_desc_stats,
509                 'request': 'libofproto-OFP15-flow_desc_request.packet.json',
510                 'reply': 'libofproto-OFP15-flow_desc_reply.packet.json'
511             },
512             {
513                 'method': ofctl_v1_5.get_flow_desc_stats,
514                 'request': 'lib-ofctl-OFP15-flow_desc_request.packet.json',
515                 'reply': 'lib-ofctl-OFP15-flow_desc_reply.packet.json'
516             },
517             {
518                 'method': ofctl_v1_5.get_aggregate_flow_stats,
519                 'request': 'libofproto-OFP15-aggregate_stats_request.packet.json',
520                 'reply': 'libofproto-OFP15-aggregate_stats_reply.packet.json'
521             },
522             {
523                 'method': ofctl_v1_5.get_table_stats,
524                 'request': 'libofproto-OFP15-table_stats_request.packet.json',
525                 'reply': 'libofproto-OFP15-table_stats_reply.packet.json'
526             },
527             {
528                 'method': ofctl_v1_5.get_table_features,
529                 'request': 'lib-ofctl-ofp_table_features_request.packet.json',
530                 'reply': 'libofproto-OFP15-table_features_reply.packet.json'
531             },
532             {
533                 'method': ofctl_v1_5.get_port_stats,
534                 'request': 'libofproto-OFP15-port_stats_request.packet.json',
535                 'reply': 'libofproto-OFP15-port_stats_reply.packet.json'
536             },
537             {
538                 'method': ofctl_v1_5.get_meter_stats,
539                 'request': 'libofproto-OFP15-meter_stats_request.packet.json',
540                 'reply': 'libofproto-OFP15-meter_stats_reply.packet.json'
541             },
542             {
543                 'method': ofctl_v1_5.get_meter_features,
544                 'request': 'libofproto-OFP15-meter_features_request.packet.json',
545                 'reply': 'libofproto-OFP15-meter_features_reply.packet.json'
546             },
547             {
548                 'method': ofctl_v1_5.get_meter_desc,
549                 'request': 'libofproto-OFP15-meter_desc_request.packet.json',
550                 'reply': 'libofproto-OFP15-meter_desc_reply.packet.json'
551             },
552             {
553                 'method': ofctl_v1_5.get_group_stats,
554                 'request': 'libofproto-OFP15-group_stats_request.packet.json',
555                 'reply': 'libofproto-OFP15-group_stats_reply.packet.json'
556             },
557             {
558                 'method': ofctl_v1_5.get_group_features,
559                 'request': 'libofproto-OFP15-group_features_request.packet.json',
560                 'reply': 'libofproto-OFP15-group_features_reply.packet.json'
561             },
562             {
563                 'method': ofctl_v1_5.get_group_desc,
564                 'request': 'libofproto-OFP15-group_desc_request.packet.json',
565                 'reply': 'libofproto-OFP15-group_desc_reply.packet.json'
566             },
567             {
568                 'method': ofctl_v1_5.get_port_desc,
569                 'request': 'libofproto-OFP15-port_desc_request.packet.json',
570                 'reply': 'libofproto-OFP15-port_desc_reply.packet.json'
571             },
572             {
573                 'method': ofctl_v1_5.mod_flow_entry,
574                 'request': 'libofproto-OFP15-flow_mod_no_nx.packet.json',
575                 'reply': None
576             },
577             {
578                 'method': ofctl_v1_5.mod_flow_entry,
579                 'request': 'lib-ofctl-OFP15-flow_mod.packet.json',
580                 'reply': None
581             },
582             {
583                 'method': ofctl_v1_5.mod_meter_entry,
584                 'request': 'libofproto-OFP15-meter_mod.packet.json',
585                 'reply': None
586             },
587             {
588                 'method': ofctl_v1_5.mod_group_entry,
589                 'request': 'libofproto-OFP15-group_mod.packet.json',
590                 'reply': None
591             },
592             {
593                 'method': ofctl_v1_5.mod_port_behavior,
594                 'request': 'libofproto-OFP15-port_mod.packet.json',
595                 'reply': None
596             },
597             {
598                 'method': ofctl_v1_5.send_experimenter,
599                 'request': 'libofproto-OFP15-experimenter.packet.json',
600                 'reply': None
601             }
602         ],
603     }
604
605     def _jsonfile_to_msg(datapath, jsonfile):
606         return ofproto_parser.ofp_msg_from_jsondict(
607             datapath, json.load(open(jsonfile)))
608
609     this_dir = os.path.dirname(sys.modules[__name__].__file__)
610     parser_json_root = os.path.join(this_dir, '../ofproto/json/')
611     ofctl_json_root = os.path.join(this_dir, 'ofctl_json/')
612
613     for ofp_ver, tests in _test_cases.items():
614         dp = DummyDatapath(_ofp_vers[ofp_ver])
615         parser_json_dir = os.path.join(parser_json_root, ofp_ver)
616         ofctl_json_dir = os.path.join(ofctl_json_root, ofp_ver)
617         for test in tests:
618             name = 'test_ofctl_' + ofp_ver + '_' + test['request']
619             print('adding %s ...' % name)
620             args = {}
621             args_json_path = os.path.join(ofctl_json_dir, test['request'])
622             if os.path.exists(args_json_path):
623                 args = json.load(open(args_json_path))
624             request = _jsonfile_to_msg(
625                 dp, os.path.join(parser_json_dir, test['request']))
626             reply = None
627             expected = None
628             if test['reply']:
629                 reply = _jsonfile_to_msg(
630                     dp, os.path.join(parser_json_dir, test['reply']))
631                 expected = json.load(
632                     open(os.path.join(ofctl_json_dir, test['reply'])))
633             f = functools.partial(
634                 Test_ofctl._test, name=name, dp=dp, method=test['method'],
635                 args=args, request=request, reply=reply, expected=expected)
636             test_lib.add_method(Test_ofctl, name, f)
637
638
639 _add_tests()
640
641 if __name__ == "__main__":
642     unittest.main()