Merge "Clean-up tests in test_vsperf_dpdk.py:VsperfDPDKTestCase"
[yardstick.git] / yardstick / tests / unit / benchmark / scenarios / networking / test_vnf_generic.py
1 # Copyright (c) 2016-2017 Intel 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 implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from copy import deepcopy
16 import os
17 import sys
18
19 import mock
20 import unittest
21
22 from yardstick import tests
23 from yardstick.common import exceptions
24 from yardstick.common import utils
25 from yardstick.network_services.collector.subscriber import Collector
26 from yardstick.network_services.traffic_profile import base
27 from yardstick.network_services.vnf_generic import vnfdgen
28 from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
29 from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
30
31
32 stl_patch = mock.patch.dict(sys.modules, tests.STL_MOCKS)
33 stl_patch.start()
34
35 if stl_patch:
36     from yardstick.benchmark.scenarios.networking import vnf_generic
37
38 # pylint: disable=unused-argument
39 # disable this for now because I keep forgetting mock patch arg ordering
40
41
42 COMPLETE_TREX_VNFD = {
43     'vnfd:vnfd-catalog': {
44         'vnfd': [
45             {
46                 'benchmark': {
47                     'kpi': [
48                         'rx_throughput_fps',
49                         'tx_throughput_fps',
50                         'tx_throughput_mbps',
51                         'rx_throughput_mbps',
52                         'tx_throughput_pc_linerate',
53                         'rx_throughput_pc_linerate',
54                         'min_latency',
55                         'max_latency',
56                         'avg_latency',
57                     ],
58                 },
59                 'connection-point': [
60                     {
61                         'name': 'xe0',
62                         'type': 'VPORT',
63                     },
64                     {
65                         'name': 'xe1',
66                         'type': 'VPORT',
67                     },
68                 ],
69                 'description': 'TRex stateless traffic generator for RFC2544',
70                 'id': 'TrexTrafficGen',
71                 'mgmt-interface': {
72                     'ip': '1.1.1.1',
73                     'password': 'berta',
74                     'user': 'berta',
75                     'vdu-id': 'trexgen-baremetal',
76                 },
77                 'name': 'trexgen',
78                 'short-name': 'trexgen',
79                 'class-name': 'TrexTrafficGen',
80                 'vdu': [
81                     {
82                         'description': 'TRex stateless traffic generator for RFC2544',
83                         'external-interface': [
84                             {
85                                 'name': 'xe0',
86                                 'virtual-interface': {
87                                     'bandwidth': '10 Gbps',
88                                     'dst_ip': '1.1.1.1',
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",
94                                     'driver': 'i40',
95                                     'vpci': '0000:00:10.2',
96                                 },
97                                 'vnfd-connection-point-ref': 'xe0',
98                             },
99                             {
100                                 'name': 'xe1',
101                                 'virtual-interface': {
102                                     'bandwidth': '10 Gbps',
103                                     'dst_ip': '2.1.1.1',
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",
109                                     'driver': 'i40',
110                                     'vpci': '0000:00:10.1',
111                                 },
112                                 'vnfd-connection-point-ref': 'xe1',
113                             },
114                         ],
115                         'id': 'trexgen-baremetal',
116                         'name': 'trexgen-baremetal',
117                     },
118                 ],
119             },
120         ],
121     },
122 }
123
124 IP_ADDR_SHOW = """
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
137 """
138
139 SYS_CLASS_NET = """
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
144 """
145
146 TRAFFIC_PROFILE = {
147     "schema": "isb:traffic_profile:0.1",
148     "name": "fixed",
149     "description": "Fixed traffic profile to run UDP traffic",
150     "traffic_profile": {
151         "traffic_type": "FixedTraffic",
152         "frame_rate": 100,  # pps
153         "flow_number": 10,
154         "frame_size": 64,
155     },
156 }
157
158
159 class TestNetworkServiceTestCase(unittest.TestCase):
160
161     def setUp(self):
162         self.tg__1 = {
163             'name': 'trafficgen_1.yardstick',
164             'ip': '10.10.10.11',
165             'role': 'TrafficGen',
166             'user': 'root',
167             'password': 'r00t',
168             'interfaces': {
169                 'xe0': {
170                     'netmask': '255.255.255.0',
171                     'local_ip': '152.16.100.20',
172                     'local_mac': '00:00:00:00:00:01',
173                     'driver': 'i40e',
174                     'vpci': '0000:07:00.0',
175                     'dpdk_port_num': 0,
176                 },
177                 'xe1': {
178                     'netmask': '255.255.255.0',
179                     'local_ip': '152.16.40.20',
180                     'local_mac': '00:00:00:00:00:02',
181                     'driver': 'i40e',
182                     'vpci': '0000:07:00.1',
183                     'dpdk_port_num': 1,
184                 },
185             },
186         }
187
188         self.vnf__1 = {
189             'name': 'vnf.yardstick',
190             'ip': '10.10.10.12',
191             'host': '10.223.197.164',
192             'role': 'vnf',
193             'user': 'root',
194             'password': 'r00t',
195             'interfaces': {
196                 'xe0': {
197                     'netmask': '255.255.255.0',
198                     'local_ip': '152.16.100.19',
199                     'local_mac': '00:00:00:00:00:03',
200                     'driver': 'i40e',
201                     'vpci': '0000:07:00.0',
202                     'dpdk_port_num': 0,
203                 },
204                 'xe1': {
205                     'netmask': '255.255.255.0',
206                     'local_ip': '152.16.40.19',
207                     'local_mac': '00:00:00:00:00:04',
208                     'driver': 'i40e',
209                     'vpci': '0000:07:00.1',
210                     'dpdk_port_num': 1,
211                 },
212             },
213             'routing_table': [
214                 {
215                     'netmask': '255.255.255.0',
216                     'gateway': '152.16.100.20',
217                     'network': '152.16.100.20',
218                     'if': 'xe0',
219                 },
220                 {
221                     'netmask': '255.255.255.0',
222                     'gateway': '152.16.40.20',
223                     'network': '152.16.40.20',
224                     'if': 'xe1',
225                 },
226             ],
227             'nd_route_tbl': [
228                 {
229                     'netmask': '112',
230                     'gateway': '0064:ff9b:0:0:0:0:9810:6414',
231                     'network': '0064:ff9b:0:0:0:0:9810:6414',
232                     'if': 'xe0',
233                 },
234                 {
235                     'netmask': '112',
236                     'gateway': '0064:ff9b:0:0:0:0:9810:2814',
237                     'network': '0064:ff9b:0:0:0:0:9810:2814',
238                     'if': 'xe1',
239                 },
240             ],
241         }
242
243         self.context_cfg = {
244             'nodes': {
245                 'tg__1': self.tg__1,
246                 'vnf__1': self.vnf__1,
247             },
248             'networks': {
249                 GenericVNF.UPLINK: {
250                     'vld_id': GenericVNF.UPLINK,
251                 },
252                 GenericVNF.DOWNLINK: {
253                     'vld_id': GenericVNF.DOWNLINK,
254                 },
255             },
256         }
257
258         self.vld0 = {
259             'vnfd-connection-point-ref': [
260                 {
261                     'vnfd-connection-point-ref': 'xe0',
262                     'member-vnf-index-ref': '1',
263                     'vnfd-id-ref': 'trexgen'
264                 },
265                 {
266                     'vnfd-connection-point-ref': 'xe0',
267                     'member-vnf-index-ref': '2',
268                     'vnfd-id-ref': 'trexgen'
269                 }
270             ],
271             'type': 'ELAN',
272             'id': GenericVNF.UPLINK,
273             'name': 'tg__1 to vnf__1 link 1'
274         }
275
276         self.vld1 = {
277             'vnfd-connection-point-ref': [
278                 {
279                     'vnfd-connection-point-ref': 'xe1',
280                     'member-vnf-index-ref': '1',
281                     'vnfd-id-ref': 'trexgen'
282                 },
283                 {
284                     'vnfd-connection-point-ref': 'xe1',
285                     'member-vnf-index-ref': '2',
286                     'vnfd-id-ref': 'trexgen'
287                 }
288             ],
289             'type': 'ELAN',
290             'id': GenericVNF.DOWNLINK,
291             'name': 'vnf__1 to tg__1 link 2'
292         }
293
294         self.topology = {
295             'id': 'trex-tg-topology',
296             'short-name': 'trex-tg-topology',
297             'name': 'trex-tg-topology',
298             'description': 'trex-tg-topology',
299             'constituent-vnfd': [
300                 {
301                     'member-vnf-index': '1',
302                     'VNF model': 'tg_trex_tpl.yaml',
303                     'vnfd-id-ref': 'tg__1',
304                 },
305                 {
306                     'member-vnf-index': '2',
307                     'VNF model': 'tg_trex_tpl.yaml',
308                     'vnfd-id-ref': 'vnf__1',
309                 },
310             ],
311             'vld': [self.vld0, self.vld1],
312         }
313
314         self.scenario_cfg = {
315             'task_path': "",
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',
320             'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
321             'type': 'ISB',
322             'tc_options': {
323                 'rfc2544': {
324                     'allowed_drop_rate': '0.8 - 1',
325                 },
326             },
327             'options': {
328                 'framesize': {'64B': 100}
329             },
330             'runner': {
331                 'object': 'NetworkServiceTestCase',
332                 'interval': 35,
333                 'output_filename': 'yardstick.out',
334                 'runner_id': 74476,
335                 'duration': 400,
336                 'type': 'Duration',
337             },
338             'traffic_options': {
339                 'flow': 'ipv4_1flow_Packets_vpe.yaml',
340                 'imix': 'imix_voice.yaml'
341             },
342             'nodes': {
343                 'tg__2': 'trafficgen_2.yardstick',
344                 'tg__1': 'trafficgen_1.yardstick',
345                 'vnf__1': 'vnf.yardstick',
346             },
347         }
348
349         self.s = vnf_generic.NetworkServiceTestCase(self.scenario_cfg,
350                                                     self.context_cfg)
351
352     def _get_file_abspath(self, filename):
353         curr_path = os.path.dirname(os.path.abspath(__file__))
354         file_path = os.path.join(curr_path, filename)
355         return file_path
356
357     def test___init__(self):
358         self.assertIsNotNone(self.topology)
359
360     def test__get_ip_flow_range_string(self):
361         self.scenario_cfg["traffic_options"]["flow"] = \
362             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
363         result = '152.16.100.2-152.16.100.254'
364         self.assertEqual(result, self.s._get_ip_flow_range(
365             '152.16.100.2-152.16.100.254'))
366
367     def test__get_ip_flow_range(self):
368         self.scenario_cfg["traffic_options"]["flow"] = \
369             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
370         result = '152.16.100.2-152.16.100.254'
371         self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'}))
372
373     @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.ipaddress')
374     def test__get_ip_flow_range_no_node_data(self, mock_ipaddress):
375         scenario_cfg = deepcopy(self.scenario_cfg)
376         scenario_cfg["traffic_options"]["flow"] = \
377             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
378
379         mock_ipaddress.ip_network.return_value = ipaddr = mock.Mock()
380         ipaddr.hosts.return_value = []
381
382         expected = '0.0.0.0'
383         result = self.s._get_ip_flow_range({"tg__2": 'xe0'})
384         self.assertEqual(result, expected)
385
386     def test__get_ip_flow_range_no_nodes(self):
387         expected = '0.0.0.0'
388         result = self.s._get_ip_flow_range({})
389         self.assertEqual(result, expected)
390
391     def test___get_traffic_flow(self):
392         self.scenario_cfg["traffic_options"]["flow"] = \
393             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
394         self.scenario_cfg["options"] = {}
395         self.scenario_cfg['options'] = {
396             'flow': {
397                 'src_ip': [
398                     {
399                         'tg__1': 'xe0',
400                     },
401                 ],
402                 'dst_ip': [
403                     {
404                         'tg__1': 'xe1',
405                     },
406                 ],
407                 'public_ip': ['1.1.1.1'],
408             },
409         }
410         # NOTE(ralonsoh): check the expected output. This test could be
411         # incorrect
412         # result = {'flow': {'dst_ip0': '152.16.40.2-152.16.40.254',
413         #                    'src_ip0': '152.16.100.2-152.16.100.254'}}
414         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
415
416     def test___get_traffic_flow_error(self):
417         self.scenario_cfg["traffic_options"]["flow"] = \
418             "ipv4_1flow_Packets_vpe.yaml1"
419         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
420
421     def test_get_vnf_imp(self):
422         vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
423         with mock.patch.dict(sys.modules, tests.STL_MOCKS):
424             self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
425
426         with self.assertRaises(exceptions.IncorrectConfig) as raised:
427             self.s.get_vnf_impl('NonExistentClass')
428
429         exc_str = str(raised.exception)
430         print(exc_str)
431         self.assertIn('No implementation', exc_str)
432         self.assertIn('found in', exc_str)
433
434     def test_load_vnf_models_invalid(self):
435         self.context_cfg["nodes"]['tg__1']['VNF model'] = \
436             self._get_file_abspath("tg_trex_tpl.yaml")
437         self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
438             self._get_file_abspath("tg_trex_tpl.yaml")
439         self.context_cfg['task_id'] = 'fake_task_id'
440
441         vnf = mock.Mock(autospec=GenericVNF)
442         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
443
444         self.assertIsNotNone(
445             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
446
447     def test_load_vnf_models_no_model(self):
448         vnf = mock.Mock(autospec=GenericVNF)
449         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
450
451         self.assertIsNotNone(
452             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
453
454     def test_map_topology_to_infrastructure(self):
455         self.s.map_topology_to_infrastructure()
456
457         nodes = self.context_cfg["nodes"]
458         self.assertEqual('../../vnf_descriptors/tg_rfc2544_tpl.yaml',
459                          nodes['tg__1']['VNF model'])
460         self.assertEqual('../../vnf_descriptors/vpe_vnf.yaml',
461                          nodes['vnf__1']['VNF model'])
462
463     def test_map_topology_to_infrastructure_insufficient_nodes(self):
464         cfg = deepcopy(self.context_cfg)
465         del cfg['nodes']['vnf__1']
466
467         cfg_patch = mock.patch.object(self.s, 'context_cfg', cfg)
468         with cfg_patch:
469             with self.assertRaises(exceptions.IncorrectConfig):
470                 self.s.map_topology_to_infrastructure()
471
472     def test_map_topology_to_infrastructure_config_invalid(self):
473         ssh_mock = mock.Mock()
474         ssh_mock.execute.return_value = 0, SYS_CLASS_NET + IP_ADDR_SHOW, ""
475
476         cfg = deepcopy(self.s.context_cfg)
477
478         # delete all, we don't know which will come first
479         del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
480         del cfg['nodes']['vnf__1']['interfaces']['xe1']['local_mac']
481         del cfg['nodes']['tg__1']['interfaces']['xe0']['local_mac']
482         del cfg['nodes']['tg__1']['interfaces']['xe1']['local_mac']
483
484         config_patch = mock.patch.object(self.s, 'context_cfg', cfg)
485         with config_patch:
486             with self.assertRaises(exceptions.IncorrectConfig):
487                 self.s.map_topology_to_infrastructure()
488
489     def test__resolve_topology_invalid_config(self):
490         with mock.patch("yardstick.ssh.SSH") as ssh:
491             ssh_mock = mock.Mock(autospec=ssh.SSH)
492             ssh_mock.execute = \
493                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
494             ssh.from_node.return_value = ssh_mock
495
496             # purge an important key from the data structure
497             for interface in self.tg__1['interfaces'].values():
498                 del interface['local_mac']
499
500             with self.assertRaises(exceptions.IncorrectConfig) as raised:
501                 self.s._resolve_topology()
502
503             self.assertIn('not found', str(raised.exception))
504
505             # restore local_mac
506             for index, interface in enumerate(self.tg__1['interfaces'].values()):
507                 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
508
509             # make a connection point ref with 3 points
510             self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
511                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
512
513             with self.assertRaises(exceptions.IncorrectConfig) as raised:
514                 self.s._resolve_topology()
515
516             self.assertIn('wrong endpoint count', str(raised.exception))
517
518             # make a connection point ref with 1 point
519             self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
520                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
521
522             with self.assertRaises(exceptions.IncorrectConfig) as raised:
523                 self.s._resolve_topology()
524
525             self.assertIn('wrong endpoint count', str(raised.exception))
526
527     def test_run(self):
528         tgen = mock.Mock(autospec=GenericTrafficGen)
529         tgen.traffic_finished = True
530         verified_dict = {"verified": True}
531         tgen.verify_traffic = lambda x: verified_dict
532         tgen.name = "tgen__1"
533         vnf = mock.Mock(autospec=GenericVNF)
534         vnf.runs_traffic = False
535         self.s.vnfs = [tgen, vnf]
536         self.s.traffic_profile = mock.Mock()
537         self.s.collector = mock.Mock(autospec=Collector)
538         self.s.collector.get_kpi = \
539             mock.Mock(return_value={tgen.name: verified_dict})
540         result = {}
541         self.s.run(result)
542         self.assertDictEqual(result, {tgen.name: verified_dict})
543
544     def test_setup(self):
545         with mock.patch("yardstick.ssh.SSH") as ssh:
546             ssh_mock = mock.Mock(autospec=ssh.SSH)
547             ssh_mock.execute = \
548                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
549             ssh.from_node.return_value = ssh_mock
550
551             tgen = mock.Mock(autospec=GenericTrafficGen)
552             tgen.traffic_finished = True
553             verified_dict = {"verified": True}
554             tgen.verify_traffic = lambda x: verified_dict
555             tgen.terminate = mock.Mock(return_value=True)
556             tgen.name = "tgen__1"
557             tgen.run_traffic.return_value = 'tg_id'
558             vnf = mock.Mock(autospec=GenericVNF)
559             vnf.runs_traffic = False
560             vnf.terminate = mock.Mock(return_value=True)
561             self.s.vnfs = [tgen, vnf]
562             self.s.traffic_profile = mock.Mock()
563             self.s.collector = mock.Mock(autospec=Collector)
564             self.s.collector.get_kpi = \
565                 mock.Mock(return_value={tgen.name: verified_dict})
566             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
567             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
568             self.s._fill_traffic_profile = \
569                 mock.Mock(return_value=TRAFFIC_PROFILE)
570
571     def test_setup_exception(self):
572         with mock.patch("yardstick.ssh.SSH") as ssh:
573             ssh_mock = mock.Mock(autospec=ssh.SSH)
574             ssh_mock.execute = \
575                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
576             ssh.from_node.return_value = ssh_mock
577
578             tgen = mock.Mock(autospec=GenericTrafficGen)
579             tgen.traffic_finished = True
580             verified_dict = {"verified": True}
581             tgen.verify_traffic = lambda x: verified_dict
582             tgen.terminate = mock.Mock(return_value=True)
583             tgen.name = "tgen__1"
584             vnf = mock.Mock(autospec=GenericVNF)
585             vnf.runs_traffic = False
586             vnf.instantiate.side_effect = RuntimeError(
587                 "error during instantiate")
588             vnf.terminate = mock.Mock(return_value=True)
589             self.s.vnfs = [tgen, vnf]
590             self.s.traffic_profile = mock.Mock()
591             self.s.collector = mock.Mock(autospec=Collector)
592             self.s.collector.get_kpi = \
593                 mock.Mock(return_value={tgen.name: verified_dict})
594             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
595             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
596             self.s._fill_traffic_profile = \
597                 mock.Mock(return_value=TRAFFIC_PROFILE)
598             with self.assertRaises(RuntimeError):
599                 self.s.setup()
600
601     def test__get_traffic_profile(self):
602         self.scenario_cfg["traffic_profile"] = \
603             self._get_file_abspath("ipv4_throughput_vpe.yaml")
604         self.assertIsNotNone(self.s._get_traffic_profile())
605
606     def test__get_traffic_profile_exception(self):
607         with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
608             with self.assertRaises(IOError):
609                 self.s._get_traffic_profile()
610
611     def test___get_traffic_imix_exception(self):
612         with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
613             self.assertEqual({'imix': {'64B': 100}},
614                              self.s._get_traffic_imix())
615
616     @mock.patch.object(base.TrafficProfile, 'get')
617     @mock.patch.object(vnfdgen, 'generate_vnfd')
618     def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get):
619         fake_tprofile = mock.Mock()
620         fake_vnfd = mock.Mock()
621         with mock.patch.object(self.s, '_get_traffic_profile',
622                                return_value=fake_tprofile) as mock_get_tp:
623             mock_generate.return_value = fake_vnfd
624             self.s._fill_traffic_profile()
625             mock_get_tp.assert_called_once()
626             mock_generate.assert_called_once_with(
627                 fake_tprofile,
628                 {'downlink': {},
629                  'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
630                  'flow': {'flow': {}},
631                  'imix': {'imix': {'64B': 100}},
632                  'uplink': {},
633                  'duration': 30}
634             )
635             mock_tprofile_get.assert_called_once_with(fake_vnfd)
636
637     @mock.patch.object(utils, 'open_relative_file')
638     def test__get_topology(self, mock_open_path):
639         self.s.scenario_cfg['topology'] = 'fake_topology'
640         self.s.scenario_cfg['task_path'] = 'fake_path'
641         mock_open_path.side_effect = mock.mock_open(read_data='fake_data')
642         self.assertEqual('fake_data', self.s._get_topology())
643         mock_open_path.assert_called_once_with('fake_topology', 'fake_path')
644
645     @mock.patch.object(vnfdgen, 'generate_vnfd')
646     def test__render_topology(self, mock_generate):
647         fake_topology = 'fake_topology'
648         mock_generate.return_value = {'nsd:nsd-catalog': {'nsd': ['fake_nsd']}}
649         with mock.patch.object(self.s, '_get_topology',
650                                return_value=fake_topology) as mock_get_topology:
651             self.s._render_topology()
652             mock_get_topology.assert_called_once()
653
654         mock_generate.assert_called_once_with(
655             fake_topology,
656             {'extra_args': {'arg1': 'value1', 'arg2': 'value2'}}
657         )
658         self.assertEqual(self.s.topology, 'fake_nsd')
659
660     def test_get_mq_ids(self):
661         self.assertEqual(self.s._mq_ids, self.s.get_mq_ids())
662
663     def test_teardown(self):
664         vnf = mock.Mock(autospec=GenericVNF)
665         vnf.terminate = mock.Mock(return_value=True)
666         vnf.name = str(vnf)
667         self.s.vnfs = [vnf]
668         self.s.traffic_profile = mock.Mock()
669         self.s.collector = mock.Mock(autospec=Collector)
670         self.s.collector.stop = \
671             mock.Mock(return_value=True)
672         self.assertIsNone(self.s.teardown())
673
674     def test_teardown_exception(self):
675         vnf = mock.Mock(autospec=GenericVNF)
676         vnf.terminate = mock.Mock(
677             side_effect=RuntimeError("error duing terminate"))
678         vnf.name = str(vnf)
679         self.s.vnfs = [vnf]
680         self.s.traffic_profile = mock.Mock()
681         self.s.collector = mock.Mock(autospec=Collector)
682         self.s.collector.stop = \
683             mock.Mock(return_value=True)
684         with self.assertRaises(RuntimeError):
685             self.s.teardown()