3 # Copyright (c) 2016-2017 Intel Corporation
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 # Unittest for yardstick.benchmark.scenarios.networking.test_vnf_generic
20 from __future__ import absolute_import
27 from yardstick.benchmark.scenarios.networking.vnf_generic import \
28 SshManager, NetworkServiceTestCase, IncorrectConfig, \
29 IncorrectSetup, open_relative_file
30 from yardstick.network_services.collector.subscriber import Collector
31 from yardstick.network_services.vnf_generic.vnf.base import \
32 GenericTrafficGen, GenericVNF
35 'stl': mock.MagicMock(),
36 'stl.trex_stl_lib': mock.MagicMock(),
37 'stl.trex_stl_lib.base64': mock.MagicMock(),
38 'stl.trex_stl_lib.binascii': mock.MagicMock(),
39 'stl.trex_stl_lib.collections': mock.MagicMock(),
40 'stl.trex_stl_lib.copy': mock.MagicMock(),
41 'stl.trex_stl_lib.datetime': mock.MagicMock(),
42 'stl.trex_stl_lib.functools': mock.MagicMock(),
43 'stl.trex_stl_lib.imp': mock.MagicMock(),
44 'stl.trex_stl_lib.inspect': mock.MagicMock(),
45 'stl.trex_stl_lib.json': mock.MagicMock(),
46 'stl.trex_stl_lib.linecache': mock.MagicMock(),
47 'stl.trex_stl_lib.math': mock.MagicMock(),
48 'stl.trex_stl_lib.os': mock.MagicMock(),
49 'stl.trex_stl_lib.platform': mock.MagicMock(),
50 'stl.trex_stl_lib.pprint': mock.MagicMock(),
51 'stl.trex_stl_lib.random': mock.MagicMock(),
52 'stl.trex_stl_lib.re': mock.MagicMock(),
53 'stl.trex_stl_lib.scapy': mock.MagicMock(),
54 'stl.trex_stl_lib.socket': mock.MagicMock(),
55 'stl.trex_stl_lib.string': mock.MagicMock(),
56 'stl.trex_stl_lib.struct': mock.MagicMock(),
57 'stl.trex_stl_lib.sys': mock.MagicMock(),
58 'stl.trex_stl_lib.threading': mock.MagicMock(),
59 'stl.trex_stl_lib.time': mock.MagicMock(),
60 'stl.trex_stl_lib.traceback': mock.MagicMock(),
61 'stl.trex_stl_lib.trex_stl_async_client': mock.MagicMock(),
62 'stl.trex_stl_lib.trex_stl_client': mock.MagicMock(),
63 'stl.trex_stl_lib.trex_stl_exceptions': mock.MagicMock(),
64 'stl.trex_stl_lib.trex_stl_ext': mock.MagicMock(),
65 'stl.trex_stl_lib.trex_stl_jsonrpc_client': mock.MagicMock(),
66 'stl.trex_stl_lib.trex_stl_packet_builder_interface': mock.MagicMock(),
67 'stl.trex_stl_lib.trex_stl_packet_builder_scapy': mock.MagicMock(),
68 'stl.trex_stl_lib.trex_stl_port': mock.MagicMock(),
69 'stl.trex_stl_lib.trex_stl_stats': mock.MagicMock(),
70 'stl.trex_stl_lib.trex_stl_streams': mock.MagicMock(),
71 'stl.trex_stl_lib.trex_stl_types': mock.MagicMock(),
72 'stl.trex_stl_lib.types': mock.MagicMock(),
73 'stl.trex_stl_lib.utils': mock.MagicMock(),
74 'stl.trex_stl_lib.utils.argparse': mock.MagicMock(),
75 'stl.trex_stl_lib.utils.collections': mock.MagicMock(),
76 'stl.trex_stl_lib.utils.common': mock.MagicMock(),
77 'stl.trex_stl_lib.utils.json': mock.MagicMock(),
78 'stl.trex_stl_lib.utils.os': mock.MagicMock(),
79 'stl.trex_stl_lib.utils.parsing_opts': mock.MagicMock(),
80 'stl.trex_stl_lib.utils.pwd': mock.MagicMock(),
81 'stl.trex_stl_lib.utils.random': mock.MagicMock(),
82 'stl.trex_stl_lib.utils.re': mock.MagicMock(),
83 'stl.trex_stl_lib.utils.string': mock.MagicMock(),
84 'stl.trex_stl_lib.utils.sys': mock.MagicMock(),
85 'stl.trex_stl_lib.utils.text_opts': mock.MagicMock(),
86 'stl.trex_stl_lib.utils.text_tables': mock.MagicMock(),
87 'stl.trex_stl_lib.utils.texttable': mock.MagicMock(),
88 'stl.trex_stl_lib.warnings': mock.MagicMock(),
89 'stl.trex_stl_lib.yaml': mock.MagicMock(),
90 'stl.trex_stl_lib.zlib': mock.MagicMock(),
91 'stl.trex_stl_lib.zmq': mock.MagicMock(),
94 COMPLETE_TREX_VNFD = \
101 'tx_throughput_mbps',
102 'rx_throughput_mbps',
103 'tx_throughput_pc_linerate',
104 'rx_throughput_pc_linerate',
108 'connection-point': [{'name': 'xe0',
112 'description': 'TRex stateless traffic generator for RFC2544',
113 'id': 'TrexTrafficGen',
114 'mgmt-interface': {'ip': '1.1.1.1',
117 'vdu-id': 'trexgen-baremetal'},
119 'short-name': 'trexgen',
120 'vdu': [{'description': 'TRex stateless traffic generator for RFC2544',
121 'external-interface':
123 'virtual-interface': {'bandwidth': '10 Gbps',
125 'dst_mac': '00:01:02:03:04:05',
126 'local_ip': '1.1.1.2',
127 'local_mac': '00:01:02:03:05:05',
128 'type': 'PCI-PASSTHROUGH',
129 'netmask': "255.255.255.0",
131 'vpci': '0000:00:10.2'},
132 'vnfd-connection-point-ref': 'xe0'},
134 'virtual-interface': {'bandwidth': '10 Gbps',
136 'dst_mac': '00:01:02:03:04:06',
137 'local_ip': '2.1.1.2',
138 'local_mac': '00:01:02:03:05:06',
139 'type': 'PCI-PASSTHROUGH',
140 'netmask': "255.255.255.0",
142 'vpci': '0000:00:10.1'},
143 'vnfd-connection-point-ref': 'xe1'}],
144 'id': 'trexgen-baremetal',
145 'name': 'trexgen-baremetal'}]}]}}
148 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP """
149 """group default qlen 1000
150 link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
151 inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
152 inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
153 valid_lft forever preferred_lft forever
154 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP """
155 """group default qlen 1000
156 link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
157 inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
158 inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
159 valid_lft forever preferred_lft forever
163 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> """
164 """../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
165 lrwxrwxrwx 1 root root 0 sie 3 10:37 eth2 -> """
166 """../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
170 "schema": "isb:traffic_profile:0.1",
172 "description": "Fixed traffic profile to run UDP traffic",
174 "traffic_type": "FixedTraffic",
175 "frame_rate": 100, # pps
180 class TestNetworkServiceTestCase(unittest.TestCase):
184 {'trexgen__1': {'role': 'TrafficGen',
185 'name': 'trafficgen_1.yardstick',
189 {'netmask': '255.255.255.0',
190 'local_ip': '152.16.100.20',
191 'local_mac': '00:00:00:00:00:01',
193 'vpci': '0000:07:00.0',
196 {'netmask': '255.255.255.0',
197 'local_ip': '152.16.40.20',
198 'local_mac': '00:00:00:00:00:02',
200 'vpci': '0000:07:00.1',
201 'dpdk_port_num': 1}},
204 'trexvnf__1': {'name': 'vnf.yardstick',
208 {'netmask': '255.255.255.0',
209 'local_ip': '152.16.100.19',
210 'local_mac': '00:00:00:00:00:03',
212 'vpci': '0000:07:00.0',
214 'xe1': {'netmask': '255.255.255.0',
215 'local_ip': '152.16.40.19',
216 'local_mac': '00:00:00:00:00:04',
218 'vpci': '0000:07:00.1',
219 'dpdk_port_num': 1}},
220 'routing_table': [{'netmask': '255.255.255.0',
221 'gateway': '152.16.100.20',
222 'network': '152.16.100.20',
224 {'netmask': '255.255.255.0',
225 'gateway': '152.16.40.20',
226 'network': '152.16.40.20',
228 'host': '10.223.197.164',
233 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
234 'network': '0064:ff9b:0:0:0:0:9810:6414',
237 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
238 'network': '0064:ff9b:0:0:0:0:9810:2814',
240 'password': 'r00t'}}}
243 'short-name': 'trex-tg-topology',
245 [{'member-vnf-index': '1',
246 'VNF model': 'tg_trex_tpl.yaml',
247 'vnfd-id-ref': 'trexgen__1'},
248 {'member-vnf-index': '2',
249 'VNF model': 'tg_trex_tpl.yaml',
250 'vnfd-id-ref': 'trexvnf__1'}],
251 'description': 'trex-tg-topology',
252 'name': 'trex-tg-topology',
255 'vnfd-connection-point-ref': [
257 'vnfd-connection-point-ref': 'xe0',
258 'member-vnf-index-ref': '1',
259 'vnfd-id-ref': 'trexgen'
262 'vnfd-connection-point-ref': 'xe0',
263 'member-vnf-index-ref': '2',
264 'vnfd-id-ref': 'trexgen'
269 'name': 'trexgen__1 to trexvnf__1 link 1'
272 'vnfd-connection-point-ref': [
274 'vnfd-connection-point-ref': 'xe1',
275 'member-vnf-index-ref': '1',
276 'vnfd-id-ref': 'trexgen'
279 'vnfd-connection-point-ref': 'xe1',
280 'member-vnf-index-ref': '2',
281 'vnfd-id-ref': 'trexgen'
286 'name': 'trexvnf__1 to trexgen__1 link 2'
288 'id': 'trex-tg-topology',
291 self.scenario_cfg = {
293 'tc_options': {'rfc2544': {'allowed_drop_rate': '0.8 - 1'}},
294 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
295 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
296 'runner': {'object': 'NetworkServiceTestCase',
298 'output_filename': 'yardstick.out',
300 'duration': 400, 'type': 'Duration'},
301 'traffic_profile': 'ipv4_throughput_vpe.yaml',
302 'traffic_options': {'flow': 'ipv4_1flow_Packets_vpe.yaml',
303 'imix': 'imix_voice.yaml'}, 'type': 'ISB',
304 'nodes': {'tg__2': 'trafficgen_2.yardstick',
305 'tg__1': 'trafficgen_1.yardstick',
306 'vnf__1': 'vnf.yardstick'},
307 "topology": self._get_file_abspath("vpe_vnf_topology.yaml")}
309 self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
311 def _get_file_abspath(self, filename):
312 curr_path = os.path.dirname(os.path.abspath(__file__))
313 file_path = os.path.join(curr_path, filename)
316 def test_ssh_manager(self):
317 with mock.patch("yardstick.ssh.SSH") as ssh:
318 ssh_mock = mock.Mock(autospec=ssh.SSH)
320 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
321 ssh.from_node.return_value = ssh_mock
322 for node, node_dict in self.context_cfg["nodes"].items():
323 with SshManager(node_dict) as conn:
324 self.assertIsNotNone(conn)
326 def test___init__(self):
329 def test___get_traffic_flow(self):
330 self.scenario_cfg["traffic_options"]["flow"] = \
331 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
332 result = {'flow': {'dstip4_range': '152.40.0.20',
333 'srcip4_range': '152.16.0.20', 'count': 1}}
334 self.assertEqual(result, self.s._get_traffic_flow(self.scenario_cfg))
336 def test___get_traffic_flow_error(self):
337 self.scenario_cfg["traffic_options"]["flow"] = \
338 "ipv4_1flow_Packets_vpe.yaml1"
339 self.assertEqual({}, self.s._get_traffic_flow(self.scenario_cfg))
341 def test_get_vnf_imp(self):
342 vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]
343 with mock.patch.dict("sys.modules", STL_MOCKS):
344 self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
346 def test_load_vnf_models_invalid(self):
347 self.context_cfg["nodes"]['trexgen__1']['VNF model'] = \
348 self._get_file_abspath("tg_trex_tpl.yaml")
349 self.context_cfg["nodes"]['trexvnf__1']['VNF model'] = \
350 self._get_file_abspath("tg_trex_tpl.yaml")
352 vnf = mock.Mock(autospec=GenericVNF)
353 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
355 self.assertIsNotNone(
356 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
358 def test_map_topology_to_infrastructure(self):
359 with mock.patch("yardstick.ssh.SSH") as ssh:
360 ssh_mock = mock.Mock(autospec=ssh.SSH)
362 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
363 ssh.from_node.return_value = ssh_mock
364 self.s.map_topology_to_infrastructure(self.context_cfg,
366 self.assertEqual("tg_trex_tpl.yaml",
367 self.context_cfg["nodes"]['trexgen__1']['VNF model'])
368 self.assertEqual("tg_trex_tpl.yaml",
369 self.context_cfg["nodes"]['trexvnf__1']['VNF model'])
371 def test_map_topology_to_infrastructure_insufficient_nodes(self):
372 del self.context_cfg['nodes']['trexvnf__1']
373 with mock.patch("yardstick.ssh.SSH") as ssh:
374 ssh_mock = mock.Mock(autospec=ssh.SSH)
376 mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
377 ssh.from_node.return_value = ssh_mock
379 self.assertRaises(IncorrectSetup,
380 self.s.map_topology_to_infrastructure,
381 self.context_cfg, self.topology)
383 def test_map_topology_to_infrastructure_config_invalid(self):
384 cfg = dict(self.context_cfg)
385 del cfg['nodes']['trexvnf__1']['interfaces']['xe0']['local_mac']
386 with mock.patch("yardstick.ssh.SSH") as ssh:
387 ssh_mock = mock.Mock(autospec=ssh.SSH)
389 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
390 ssh.from_node.return_value = ssh_mock
392 self.assertRaises(IncorrectConfig,
393 self.s.map_topology_to_infrastructure,
394 self.context_cfg, self.topology)
396 def test__resolve_topology_invalid_config(self):
397 with mock.patch("yardstick.ssh.SSH") as ssh:
398 ssh_mock = mock.Mock(autospec=ssh.SSH)
400 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
401 ssh.from_node.return_value = ssh_mock
403 del self.context_cfg['nodes']
404 self.assertRaises(IncorrectConfig, self.s._resolve_topology,
405 self.context_cfg, self.topology)
407 self.topology['vld'][0]['vnfd-connection-point-ref'].append(
408 self.topology['vld'][0]['vnfd-connection-point-ref'])
409 self.assertRaises(IncorrectConfig, self.s._resolve_topology,
410 self.context_cfg, self.topology)
413 tgen = mock.Mock(autospec=GenericTrafficGen)
414 tgen.traffic_finished = True
415 verified_dict = {"verified": True}
416 tgen.verify_traffic = lambda x: verified_dict
417 tgen.name = "tgen__1"
418 vnf = mock.Mock(autospec=GenericVNF)
419 vnf.runs_traffic = False
420 self.s.vnfs = [tgen, vnf]
421 self.s.traffic_profile = mock.Mock()
422 self.s.collector = mock.Mock(autospec=Collector)
423 self.s.collector.get_kpi = \
424 mock.Mock(return_value={tgen.name: verified_dict})
427 self.assertDictEqual(result, {tgen.name: verified_dict})
429 def test_setup(self):
430 with mock.patch("yardstick.ssh.SSH") as ssh:
431 ssh_mock = mock.Mock(autospec=ssh.SSH)
433 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
434 ssh.from_node.return_value = ssh_mock
436 tgen = mock.Mock(autospec=GenericTrafficGen)
437 tgen.traffic_finished = True
438 verified_dict = {"verified": True}
439 tgen.verify_traffic = lambda x: verified_dict
440 tgen.terminate = mock.Mock(return_value=True)
441 tgen.name = "tgen__1"
442 vnf = mock.Mock(autospec=GenericVNF)
443 vnf.runs_traffic = False
444 vnf.terminate = mock.Mock(return_value=True)
445 self.s.vnfs = [tgen, vnf]
446 self.s.traffic_profile = mock.Mock()
447 self.s.collector = mock.Mock(autospec=Collector)
448 self.s.collector.get_kpi = \
449 mock.Mock(return_value={tgen.name: verified_dict})
450 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
451 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
452 self.s._fill_traffic_profile = \
453 mock.Mock(return_value=TRAFFIC_PROFILE)
454 self.assertEqual(None, self.s.setup())
456 def test__get_traffic_profile(self):
457 self.scenario_cfg["traffic_profile"] = \
458 self._get_file_abspath("ipv4_throughput_vpe.yaml")
459 self.assertIsNotNone(self.s._get_traffic_profile(self.scenario_cfg,
462 def test__get_traffic_profile_exception(self):
463 cfg = dict(self.scenario_cfg)
464 cfg["traffic_profile"] = ""
465 self.assertRaises(IOError, self.s._get_traffic_profile, cfg,
468 def test___get_traffic_imix_exception(self):
469 cfg = dict(self.scenario_cfg)
470 cfg["traffic_options"]["imix"] = ""
471 self.assertEqual({}, self.s._get_traffic_imix(cfg))
473 def test__fill_traffic_profile(self):
474 with mock.patch.dict("sys.modules", STL_MOCKS):
475 self.scenario_cfg["traffic_profile"] = \
476 self._get_file_abspath("ipv4_throughput_vpe.yaml")
477 self.scenario_cfg["traffic_options"]["flow"] = \
478 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
479 self.scenario_cfg["traffic_options"]["imix"] = \
480 self._get_file_abspath("imix_voice.yaml")
481 self.assertIsNotNone(self.s._fill_traffic_profile(self.scenario_cfg,
484 def test_teardown(self):
485 vnf = mock.Mock(autospec=GenericVNF)
487 mock.Mock(return_value=True)
489 self.s.traffic_profile = mock.Mock()
490 self.s.collector = mock.Mock(autospec=Collector)
491 self.s.collector.stop = \
492 mock.Mock(return_value=True)
493 self.assertIsNone(self.s.teardown())
497 'address': '0a:de:ad:be:ef:f5',
501 'interface_name': 'enp11s0',
503 'pci_bus_id': '0000:0b:00.0',
504 'subsystem_device': '0x1533',
505 'subsystem_vendor': '0x15d9',
509 'address': '0a:de:ad:be:ef:f4',
513 'interface_name': 'lan',
515 'pci_bus_id': '0000:00:19.0',
516 'subsystem_device': '0x153a',
517 'subsystem_vendor': '0x15d9',
521 SAMPLE_VM_NETDEVS = {
523 'address': 'fa:de:ad:be:ef:5b',
525 'driver': 'virtio_net',
527 'interface_name': 'eth1',
529 'pci_bus_id': '0000:00:04.0',
534 def test_parse_netdev_info(self):
536 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
537 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
538 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
539 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
540 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
541 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
542 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
543 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
544 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
545 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
546 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
547 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
548 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
549 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
550 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
551 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
552 /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
553 /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
555 res = NetworkServiceTestCase.parse_netdev_info(output)
556 assert res == self.SAMPLE_NETDEVS
558 def test_parse_netdev_info_virtio(self):
560 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
561 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
562 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
563 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
564 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
565 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
567 res = NetworkServiceTestCase.parse_netdev_info(output)
568 assert res == self.SAMPLE_VM_NETDEVS
570 def test_sort_dpdk_port_num(self):
571 netdevs = self.SAMPLE_NETDEVS.copy()
572 NetworkServiceTestCase._sort_dpdk_port_num(netdevs)
573 assert netdevs['lan']['dpdk_port_num'] == 1
574 assert netdevs['enp11s0']['dpdk_port_num'] == 2
576 def test_probe_missing_values(self):
577 netdevs = self.SAMPLE_NETDEVS.copy()
578 NetworkServiceTestCase._sort_dpdk_port_num(netdevs)
579 network = {'local_mac': '0a:de:ad:be:ef:f5'}
580 NetworkServiceTestCase._probe_missing_values(netdevs, network, set())
581 assert network['dpdk_port_num'] == 2
583 network = {'local_mac': '0a:de:ad:be:ef:f4'}
584 NetworkServiceTestCase._probe_missing_values(netdevs, network, set())
585 assert network['dpdk_port_num'] == 1
587 def test_open_relative_path(self):
588 mock_open = mock.mock_open()
589 mock_open_result = mock_open()
590 mock_open_call_count = 1 # initial call to get result
593 'yardstick.benchmark.scenarios.networking.vnf_generic.open'
596 with mock.patch(module_name, mock_open, create=True):
597 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
599 mock_open_call_count += 1 # one more call expected
600 self.assertEqual(mock_open.call_count, mock_open_call_count)
601 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
602 self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
604 def open_effect(*args, **kwargs):
605 if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
606 return mock_open_result
607 raise IOError(errno.ENOENT, 'not found')
609 mock_open.side_effect = open_effect
610 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
612 mock_open_call_count += 2 # two more calls expected
613 self.assertEqual(mock_open.call_count, mock_open_call_count)
614 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
615 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
617 # test an IOError of type ENOENT
618 mock_open.side_effect = IOError(errno.ENOENT, 'not found')
619 with self.assertRaises(IOError):
620 # the second call still raises
621 open_relative_file('foo', 'bar')
623 mock_open_call_count += 2 # two more calls expected
624 self.assertEqual(mock_open.call_count, mock_open_call_count)
625 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
626 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
628 # test an IOError other than ENOENT
629 mock_open.side_effect = IOError(errno.EBUSY, 'busy')
630 with self.assertRaises(IOError):
631 open_relative_file('foo', 'bar')
633 mock_open_call_count += 1 # one more call expected
634 self.assertEqual(mock_open.call_count, mock_open_call_count)