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 copy import deepcopy
29 from yardstick.tests.unit import STL_MOCKS
30 from yardstick.benchmark.scenarios.networking.vnf_generic import \
31 SshManager, NetworkServiceTestCase, IncorrectConfig, \
33 from yardstick.network_services.collector.subscriber import Collector
34 from yardstick.network_services.vnf_generic.vnf.base import \
35 GenericTrafficGen, GenericVNF
38 # pylint: disable=unused-argument
39 # disable this for now because I keep forgetting mock patch arg ordering
42 COMPLETE_TREX_VNFD = {
43 'vnfd:vnfd-catalog': {
52 'tx_throughput_pc_linerate',
53 'rx_throughput_pc_linerate',
69 'description': 'TRex stateless traffic generator for RFC2544',
70 'id': 'TrexTrafficGen',
75 'vdu-id': 'trexgen-baremetal',
78 'short-name': 'trexgen',
79 'class-name': 'TrexTrafficGen',
82 'description': 'TRex stateless traffic generator for RFC2544',
83 'external-interface': [
86 'virtual-interface': {
87 'bandwidth': '10 Gbps',
89 'dst_mac': '00:01:02:03:04:05',
90 'local_ip': '1.1.1.2',
91 'local_mac': '00:01:02:03:05:05',
92 'type': 'PCI-PASSTHROUGH',
93 'netmask': "255.255.255.0",
95 'vpci': '0000:00:10.2',
97 'vnfd-connection-point-ref': 'xe0',
101 'virtual-interface': {
102 'bandwidth': '10 Gbps',
104 'dst_mac': '00:01:02:03:04:06',
105 'local_ip': '2.1.1.2',
106 'local_mac': '00:01:02:03:05:06',
107 'type': 'PCI-PASSTHROUGH',
108 'netmask': "255.255.255.0",
110 'vpci': '0000:00:10.1',
112 'vnfd-connection-point-ref': 'xe1',
115 'id': 'trexgen-baremetal',
116 'name': 'trexgen-baremetal',
125 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
126 group default qlen 1000
127 link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
128 inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
129 inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
130 valid_lft forever preferred_lft forever
131 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
132 group default qlen 1000
133 link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
134 inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
135 inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
136 valid_lft forever preferred_lft forever
140 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> \
141 ../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
142 lrwxrwxrwx 1 root root 0 sie 3 10:37 eth2 -> \
143 ../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
147 "schema": "isb:traffic_profile:0.1",
149 "description": "Fixed traffic profile to run UDP traffic",
151 "traffic_type": "FixedTraffic",
152 "frame_rate": 100, # pps
159 class TestNetworkServiceTestCase(unittest.TestCase):
163 'name': 'trafficgen_1.yardstick',
165 'role': 'TrafficGen',
170 'netmask': '255.255.255.0',
171 'local_ip': '152.16.100.20',
172 'local_mac': '00:00:00:00:00:01',
174 'vpci': '0000:07:00.0',
178 'netmask': '255.255.255.0',
179 'local_ip': '152.16.40.20',
180 'local_mac': '00:00:00:00:00:02',
182 'vpci': '0000:07:00.1',
189 'name': 'vnf.yardstick',
191 'host': '10.223.197.164',
197 'netmask': '255.255.255.0',
198 'local_ip': '152.16.100.19',
199 'local_mac': '00:00:00:00:00:03',
201 'vpci': '0000:07:00.0',
205 'netmask': '255.255.255.0',
206 'local_ip': '152.16.40.19',
207 'local_mac': '00:00:00:00:00:04',
209 'vpci': '0000:07:00.1',
215 'netmask': '255.255.255.0',
216 'gateway': '152.16.100.20',
217 'network': '152.16.100.20',
221 'netmask': '255.255.255.0',
222 'gateway': '152.16.40.20',
223 'network': '152.16.40.20',
230 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
231 'network': '0064:ff9b:0:0:0:0:9810:6414',
236 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
237 'network': '0064:ff9b:0:0:0:0:9810:2814',
246 'vnf__1': self.vnf__1,
250 'vld_id': GenericVNF.UPLINK,
252 GenericVNF.DOWNLINK: {
253 'vld_id': GenericVNF.DOWNLINK,
259 'vnfd-connection-point-ref': [
261 'vnfd-connection-point-ref': 'xe0',
262 'member-vnf-index-ref': '1',
263 'vnfd-id-ref': 'trexgen'
266 'vnfd-connection-point-ref': 'xe0',
267 'member-vnf-index-ref': '2',
268 'vnfd-id-ref': 'trexgen'
272 'id': GenericVNF.UPLINK,
273 'name': 'tg__1 to vnf__1 link 1'
277 'vnfd-connection-point-ref': [
279 'vnfd-connection-point-ref': 'xe1',
280 'member-vnf-index-ref': '1',
281 'vnfd-id-ref': 'trexgen'
284 'vnfd-connection-point-ref': 'xe1',
285 'member-vnf-index-ref': '2',
286 'vnfd-id-ref': 'trexgen'
290 'id': GenericVNF.DOWNLINK,
291 'name': 'vnf__1 to tg__1 link 2'
295 'id': 'trex-tg-topology',
296 'short-name': 'trex-tg-topology',
297 'name': 'trex-tg-topology',
298 'description': 'trex-tg-topology',
299 'constituent-vnfd': [
301 'member-vnf-index': '1',
302 'VNF model': 'tg_trex_tpl.yaml',
303 'vnfd-id-ref': 'tg__1',
306 'member-vnf-index': '2',
307 'VNF model': 'tg_trex_tpl.yaml',
308 'vnfd-id-ref': 'vnf__1',
311 'vld': [self.vld0, self.vld1],
314 self.scenario_cfg = {
316 "topology": self._get_file_abspath("vpe_vnf_topology.yaml"),
317 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
318 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
319 'traffic_profile': 'ipv4_throughput_vpe.yaml',
323 'allowed_drop_rate': '0.8 - 1',
327 'framesize': {'64B': 100}
330 'object': 'NetworkServiceTestCase',
332 'output_filename': 'yardstick.out',
338 'flow': 'ipv4_1flow_Packets_vpe.yaml',
339 'imix': 'imix_voice.yaml'
342 'tg__2': 'trafficgen_2.yardstick',
343 'tg__1': 'trafficgen_1.yardstick',
344 'vnf__1': 'vnf.yardstick',
348 self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
350 def _get_file_abspath(self, filename):
351 curr_path = os.path.dirname(os.path.abspath(__file__))
352 file_path = os.path.join(curr_path, filename)
355 def test_ssh_manager(self):
356 with mock.patch("yardstick.ssh.SSH") as ssh:
357 ssh_mock = mock.Mock(autospec=ssh.SSH)
359 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
360 ssh.from_node.return_value = ssh_mock
361 for _, node_dict in self.context_cfg["nodes"].items():
362 with SshManager(node_dict) as conn:
363 self.assertIsNotNone(conn)
365 def test___init__(self):
368 def test__get_ip_flow_range_string(self):
369 self.scenario_cfg["traffic_options"]["flow"] = \
370 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
371 result = '152.16.100.2-152.16.100.254'
372 self.assertEqual(result, self.s._get_ip_flow_range(
373 '152.16.100.2-152.16.100.254'))
375 def test__get_ip_flow_range(self):
376 self.scenario_cfg["traffic_options"]["flow"] = \
377 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
378 result = '152.16.100.2-152.16.100.254'
379 self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'}))
381 @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.ipaddress')
382 def test__get_ip_flow_range_no_node_data(self, mock_ipaddress):
383 scenario_cfg = deepcopy(self.scenario_cfg)
384 scenario_cfg["traffic_options"]["flow"] = \
385 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
387 mock_ipaddress.ip_network.return_value = ipaddr = mock.Mock()
388 ipaddr.hosts.return_value = []
391 result = self.s._get_ip_flow_range({"tg__2": 'xe0'})
392 self.assertEqual(result, expected)
394 def test__get_ip_flow_range_no_nodes(self):
396 result = self.s._get_ip_flow_range({})
397 self.assertEqual(result, expected)
399 def test___get_traffic_flow(self):
400 self.scenario_cfg["traffic_options"]["flow"] = \
401 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
402 self.scenario_cfg["options"] = {}
403 self.scenario_cfg['options'] = {
415 'public_ip': ['1.1.1.1'],
419 self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
421 def test___get_traffic_flow_error(self):
422 self.scenario_cfg["traffic_options"]["flow"] = \
423 "ipv4_1flow_Packets_vpe.yaml1"
424 self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
426 def test_get_vnf_imp(self):
427 vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
428 with mock.patch.dict("sys.modules", STL_MOCKS):
429 self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
431 with self.assertRaises(IncorrectConfig) as raised:
432 self.s.get_vnf_impl('NonExistentClass')
434 exc_str = str(raised.exception)
436 self.assertIn('No implementation', exc_str)
437 self.assertIn('found in', exc_str)
439 def test_load_vnf_models_invalid(self):
440 self.context_cfg["nodes"]['tg__1']['VNF model'] = \
441 self._get_file_abspath("tg_trex_tpl.yaml")
442 self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
443 self._get_file_abspath("tg_trex_tpl.yaml")
445 vnf = mock.Mock(autospec=GenericVNF)
446 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
448 self.assertIsNotNone(
449 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
451 def test_load_vnf_models_no_model(self):
452 vnf = mock.Mock(autospec=GenericVNF)
453 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
455 self.assertIsNotNone(
456 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
458 def test_map_topology_to_infrastructure(self):
459 with mock.patch("yardstick.ssh.SSH") as ssh:
460 ssh_mock = mock.Mock(autospec=ssh.SSH)
462 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
463 ssh.from_node.return_value = ssh_mock
464 self.s.map_topology_to_infrastructure()
466 nodes = self.context_cfg["nodes"]
468 "../../vnf_descriptors/tg_rfc2544_tpl.yaml", nodes['tg__1']['VNF model'])
469 self.assertEqual("../../vnf_descriptors/vpe_vnf.yaml",
470 nodes['vnf__1']['VNF model'])
472 def test_map_topology_to_infrastructure_insufficient_nodes(self):
473 del self.context_cfg['nodes']['vnf__1']
474 with mock.patch("yardstick.ssh.SSH") as ssh:
475 ssh_mock = mock.Mock(autospec=ssh.SSH)
477 mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
478 ssh.from_node.return_value = ssh_mock
480 with self.assertRaises(IncorrectConfig):
481 self.s.map_topology_to_infrastructure()
483 def test_map_topology_to_infrastructure_config_invalid(self):
484 cfg = dict(self.context_cfg)
485 del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
486 with mock.patch("yardstick.ssh.SSH") as ssh:
487 ssh_mock = mock.Mock(autospec=ssh.SSH)
489 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
490 ssh.from_node.return_value = ssh_mock
492 with self.assertRaises(IncorrectConfig):
493 self.s.map_topology_to_infrastructure()
495 def test__resolve_topology_invalid_config(self):
496 with mock.patch("yardstick.ssh.SSH") as ssh:
497 ssh_mock = mock.Mock(autospec=ssh.SSH)
499 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
500 ssh.from_node.return_value = ssh_mock
502 # purge an important key from the data structure
503 for interface in self.tg__1['interfaces'].values():
504 del interface['local_mac']
507 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
508 with self.assertRaises(IncorrectConfig) as raised:
509 self.s._resolve_topology()
511 self.assertIn('not found', str(raised.exception))
514 for index, interface in enumerate(self.tg__1['interfaces'].values()):
515 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
517 # make a connection point ref with 3 points
518 self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
519 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
522 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
523 with self.assertRaises(IncorrectConfig) as raised:
524 self.s._resolve_topology()
526 self.assertIn('wrong endpoint count', str(raised.exception))
528 # make a connection point ref with 1 point
529 self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
530 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
533 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
534 with self.assertRaises(IncorrectConfig) as raised:
535 self.s._resolve_topology()
537 self.assertIn('wrong endpoint count', str(raised.exception))
540 tgen = mock.Mock(autospec=GenericTrafficGen)
541 tgen.traffic_finished = True
542 verified_dict = {"verified": True}
543 tgen.verify_traffic = lambda x: verified_dict
544 tgen.name = "tgen__1"
545 vnf = mock.Mock(autospec=GenericVNF)
546 vnf.runs_traffic = False
547 self.s.vnfs = [tgen, vnf]
548 self.s.traffic_profile = mock.Mock()
549 self.s.collector = mock.Mock(autospec=Collector)
550 self.s.collector.get_kpi = \
551 mock.Mock(return_value={tgen.name: verified_dict})
554 self.assertDictEqual(result, {tgen.name: verified_dict})
556 def test_setup(self):
557 with mock.patch("yardstick.ssh.SSH") as ssh:
558 ssh_mock = mock.Mock(autospec=ssh.SSH)
560 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
561 ssh.from_node.return_value = ssh_mock
563 tgen = mock.Mock(autospec=GenericTrafficGen)
564 tgen.traffic_finished = True
565 verified_dict = {"verified": True}
566 tgen.verify_traffic = lambda x: verified_dict
567 tgen.terminate = mock.Mock(return_value=True)
568 tgen.name = "tgen__1"
569 vnf = mock.Mock(autospec=GenericVNF)
570 vnf.runs_traffic = False
571 vnf.terminate = mock.Mock(return_value=True)
572 self.s.vnfs = [tgen, vnf]
573 self.s.traffic_profile = mock.Mock()
574 self.s.collector = mock.Mock(autospec=Collector)
575 self.s.collector.get_kpi = \
576 mock.Mock(return_value={tgen.name: verified_dict})
577 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
578 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
579 self.s._fill_traffic_profile = \
580 mock.Mock(return_value=TRAFFIC_PROFILE)
581 self.assertEqual(None, self.s.setup())
583 def test_setup_exception(self):
584 with mock.patch("yardstick.ssh.SSH") as ssh:
585 ssh_mock = mock.Mock(autospec=ssh.SSH)
587 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
588 ssh.from_node.return_value = ssh_mock
590 tgen = mock.Mock(autospec=GenericTrafficGen)
591 tgen.traffic_finished = True
592 verified_dict = {"verified": True}
593 tgen.verify_traffic = lambda x: verified_dict
594 tgen.terminate = mock.Mock(return_value=True)
595 tgen.name = "tgen__1"
596 vnf = mock.Mock(autospec=GenericVNF)
597 vnf.runs_traffic = False
598 vnf.instantiate.side_effect = RuntimeError(
599 "error during instantiate")
600 vnf.terminate = mock.Mock(return_value=True)
601 self.s.vnfs = [tgen, vnf]
602 self.s.traffic_profile = mock.Mock()
603 self.s.collector = mock.Mock(autospec=Collector)
604 self.s.collector.get_kpi = \
605 mock.Mock(return_value={tgen.name: verified_dict})
606 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
607 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
608 self.s._fill_traffic_profile = \
609 mock.Mock(return_value=TRAFFIC_PROFILE)
610 with self.assertRaises(RuntimeError):
613 def test__get_traffic_profile(self):
614 self.scenario_cfg["traffic_profile"] = \
615 self._get_file_abspath("ipv4_throughput_vpe.yaml")
616 self.assertIsNotNone(self.s._get_traffic_profile())
618 def test__get_traffic_profile_exception(self):
619 with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
620 with self.assertRaises(IOError):
621 self.s._get_traffic_profile()
623 def test___get_traffic_imix_exception(self):
624 with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
625 self.assertEqual({'imix': {'64B': 100}},
626 self.s._get_traffic_imix())
628 def test__fill_traffic_profile(self):
629 with mock.patch.dict("sys.modules", STL_MOCKS):
630 self.scenario_cfg["traffic_profile"] = \
631 self._get_file_abspath("ipv4_throughput_vpe.yaml")
632 self.scenario_cfg["traffic_options"]["flow"] = \
633 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
634 self.scenario_cfg["traffic_options"]["imix"] = \
635 self._get_file_abspath("imix_voice.yaml")
636 self.assertIsNotNone(self.s._fill_traffic_profile())
638 def test_teardown(self):
639 vnf = mock.Mock(autospec=GenericVNF)
640 vnf.terminate = mock.Mock(return_value=True)
643 self.s.traffic_profile = mock.Mock()
644 self.s.collector = mock.Mock(autospec=Collector)
645 self.s.collector.stop = \
646 mock.Mock(return_value=True)
647 self.assertIsNone(self.s.teardown())
649 def test_teardown_exception(self):
650 vnf = mock.Mock(autospec=GenericVNF)
651 vnf.terminate = mock.Mock(
652 side_effect=RuntimeError("error duing terminate"))
655 self.s.traffic_profile = mock.Mock()
656 self.s.collector = mock.Mock(autospec=Collector)
657 self.s.collector.stop = \
658 mock.Mock(return_value=True)
659 with self.assertRaises(RuntimeError):
664 'address': '0a:de:ad:be:ef:f5',
668 'interface_name': 'enp11s0',
670 'pci_bus_id': '0000:0b:00.0',
671 'subsystem_device': '0x1533',
672 'subsystem_vendor': '0x15d9',
676 'address': '0a:de:ad:be:ef:f4',
680 'interface_name': 'lan',
682 'pci_bus_id': '0000:00:19.0',
683 'subsystem_device': '0x153a',
684 'subsystem_vendor': '0x15d9',
689 SAMPLE_VM_NETDEVS = {
691 'address': 'fa:de:ad:be:ef:5b',
693 'driver': 'virtio_net',
695 'interface_name': 'eth1',
697 'pci_bus_id': '0000:00:04.0',
702 def test_parse_netdev_info(self):
704 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
705 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
706 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
707 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
708 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
709 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
710 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
711 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
712 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
713 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
714 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
715 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
716 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
717 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
718 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
719 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
720 /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
721 /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
723 res = NetworkServiceTestCase.parse_netdev_info(output)
724 assert res == self.SAMPLE_NETDEVS
726 def test_parse_netdev_info_virtio(self):
728 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
729 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
730 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
731 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
732 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
733 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
735 res = NetworkServiceTestCase.parse_netdev_info(output)
736 assert res == self.SAMPLE_VM_NETDEVS
738 def test_probe_missing_values(self):
739 netdevs = self.SAMPLE_NETDEVS.copy()
740 network = {'local_mac': '0a:de:ad:be:ef:f5'}
741 NetworkServiceTestCase._probe_missing_values(netdevs, network)
742 assert network['vpci'] == '0000:0b:00.0'
744 network = {'local_mac': '0a:de:ad:be:ef:f4'}
745 NetworkServiceTestCase._probe_missing_values(netdevs, network)
746 assert network['vpci'] == '0000:00:19.0'
748 # TODO: Split this into several tests, for different IOError sub-types
749 def test_open_relative_path(self):
750 mock_open = mock.mock_open()
751 mock_open_result = mock_open()
752 mock_open_call_count = 1 # initial call to get result
755 'yardstick.benchmark.scenarios.networking.vnf_generic.open'
758 with mock.patch(module_name, mock_open, create=True):
759 self.assertEqual(open_relative_file(
760 'foo', 'bar'), mock_open_result)
762 mock_open_call_count += 1 # one more call expected
763 self.assertEqual(mock_open.call_count, mock_open_call_count)
764 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
765 self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
767 def open_effect(*args, **kwargs):
768 if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
769 return mock_open_result
770 raise IOError(errno.ENOENT, 'not found')
772 mock_open.side_effect = open_effect
773 self.assertEqual(open_relative_file(
774 'foo', 'bar'), mock_open_result)
776 mock_open_call_count += 2 # two more calls expected
777 self.assertEqual(mock_open.call_count, mock_open_call_count)
778 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
779 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
781 # test an IOError of type ENOENT
782 mock_open.side_effect = IOError(errno.ENOENT, 'not found')
783 with self.assertRaises(IOError):
784 # the second call still raises
785 open_relative_file('foo', 'bar')
787 mock_open_call_count += 2 # two more calls expected
788 self.assertEqual(mock_open.call_count, mock_open_call_count)
789 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
790 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
792 # test an IOError other than ENOENT
793 mock_open.side_effect = IOError(errno.EBUSY, 'busy')
794 with self.assertRaises(IOError):
795 open_relative_file('foo', 'bar')
797 mock_open_call_count += 1 # one more call expected
798 self.assertEqual(mock_open.call_count, mock_open_call_count)