Merge "Prox standalone test case changes:"
[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                 'simulated_users': {'uplink': [1, 2]},
329                 'page_object': {'uplink': [1, 2]},
330                 'framesize': {'64B': 100}
331             },
332             'runner': {
333                 'object': 'NetworkServiceTestCase',
334                 'interval': 35,
335                 'output_filename': 'yardstick.out',
336                 'runner_id': 74476,
337                 'duration': 400,
338                 'type': 'Duration',
339             },
340             'traffic_options': {
341                 'flow': 'ipv4_1flow_Packets_vpe.yaml',
342                 'imix': 'imix_voice.yaml'
343             },
344             'nodes': {
345                 'tg__2': 'trafficgen_2.yardstick',
346                 'tg__1': 'trafficgen_1.yardstick',
347                 'vnf__1': 'vnf.yardstick',
348             },
349         }
350
351         self.s = vnf_generic.NetworkServiceTestCase(self.scenario_cfg,
352                                                     self.context_cfg)
353
354     def _get_file_abspath(self, filename):
355         curr_path = os.path.dirname(os.path.abspath(__file__))
356         file_path = os.path.join(curr_path, filename)
357         return file_path
358
359     def test___init__(self):
360         self.assertIsNotNone(self.topology)
361
362     def test__get_ip_flow_range_string(self):
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_no_nodes(self):
368         self.assertEqual('0.0.0.0', self.s._get_ip_flow_range({}))
369
370     def test__get_ip_flow_range_no_node_data(self):
371         node_data = {'tg__0': 'xe0'}
372         self.s.context_cfg['nodes']['tg__0'] = {}
373         result = self.s._get_ip_flow_range(node_data)
374         self.assertEqual('0.0.0.2-0.0.0.254', result)
375
376     def test__et_ip_flow_range_ipv4(self):
377         node_data = {'tg__0': 'xe0'}
378         self.s.context_cfg['nodes']['tg__0'] = {
379             'interfaces': {
380                 'xe0': {'local_ip': '192.168.1.15',
381                         'netmask': '255.255.255.128'}
382             }
383         }
384         result = self.s._get_ip_flow_range(node_data)
385         self.assertEqual('192.168.1.2-192.168.1.126', result)
386
387     def test__get_ip_flow_range_ipv4_mask_30(self):
388         node_data = {'tg__0': 'xe0'}
389         self.s.context_cfg['nodes']['tg__0'] = {
390             'interfaces': {
391                 'xe0': {'local_ip': '192.168.1.15', 'netmask': 30}
392             }
393         }
394         result = self.s._get_ip_flow_range(node_data)
395         self.assertEqual('192.168.1.15', result)
396
397     def test__get_ip_flow_range_ipv6(self):
398         node_data = {'tg__0': 'xe0'}
399         self.s.context_cfg['nodes']['tg__0'] = {
400             'interfaces': {
401                 'xe0': {'local_ip': '2001::11', 'netmask': 64}
402             }
403         }
404         result = self.s._get_ip_flow_range(node_data)
405         self.assertEqual('2001::2-2001::ffff:ffff:ffff:fffe', result)
406
407     def test___get_traffic_flow(self):
408         self.scenario_cfg["traffic_options"]["flow"] = \
409             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
410         self.scenario_cfg['options'] = {
411             'flow': {
412                 'src_ip': [
413                     {
414                         'tg__1': 'xe0',
415                     },
416                 ],
417                 'dst_ip': [
418                     {
419                         'tg__1': 'xe1',
420                     },
421                 ],
422                 'public_ip': ['1.1.1.1'],
423             },
424         }
425         expected_flow = {'flow': {'dst_ip_0': '152.16.40.2-152.16.40.254',
426                                   'public_ip_0': '1.1.1.1',
427                                   'src_ip_0': '152.16.100.2-152.16.100.254'}}
428         self.assertEqual(expected_flow, self.s._get_traffic_flow())
429
430     def test___get_traffic_flow_error(self):
431         self.scenario_cfg["traffic_options"]["flow"] = \
432             "ipv4_1flow_Packets_vpe.yaml1"
433         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
434
435     def test_get_vnf_imp(self):
436         vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
437         with mock.patch.dict(sys.modules, tests.STL_MOCKS):
438             self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
439
440         with self.assertRaises(exceptions.IncorrectConfig) as raised:
441             self.s.get_vnf_impl('NonExistentClass')
442
443         exc_str = str(raised.exception)
444         print(exc_str)
445         self.assertIn('No implementation', exc_str)
446         self.assertIn('found in', exc_str)
447
448     def test_load_vnf_models_invalid(self):
449         self.context_cfg["nodes"]['tg__1']['VNF model'] = \
450             self._get_file_abspath("tg_trex_tpl.yaml")
451         self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
452             self._get_file_abspath("tg_trex_tpl.yaml")
453         self.context_cfg['task_id'] = 'fake_task_id'
454
455         vnf = mock.Mock(autospec=GenericVNF)
456         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
457
458         self.assertIsNotNone(
459             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
460
461     def test_load_vnf_models_no_model(self):
462         vnf = mock.Mock(autospec=GenericVNF)
463         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
464
465         self.assertIsNotNone(
466             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
467
468     def test_map_topology_to_infrastructure(self):
469         self.s.map_topology_to_infrastructure()
470
471         nodes = self.context_cfg["nodes"]
472         self.assertEqual('../../vnf_descriptors/tg_rfc2544_tpl.yaml',
473                          nodes['tg__1']['VNF model'])
474         self.assertEqual('../../vnf_descriptors/vpe_vnf.yaml',
475                          nodes['vnf__1']['VNF model'])
476
477     def test_map_topology_to_infrastructure_insufficient_nodes(self):
478         cfg = deepcopy(self.context_cfg)
479         del cfg['nodes']['vnf__1']
480
481         cfg_patch = mock.patch.object(self.s, 'context_cfg', cfg)
482         with cfg_patch:
483             with self.assertRaises(exceptions.IncorrectConfig):
484                 self.s.map_topology_to_infrastructure()
485
486     def test_map_topology_to_infrastructure_config_invalid(self):
487         ssh_mock = mock.Mock()
488         ssh_mock.execute.return_value = 0, SYS_CLASS_NET + IP_ADDR_SHOW, ""
489
490         cfg = deepcopy(self.s.context_cfg)
491
492         # delete all, we don't know which will come first
493         del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
494         del cfg['nodes']['vnf__1']['interfaces']['xe1']['local_mac']
495         del cfg['nodes']['tg__1']['interfaces']['xe0']['local_mac']
496         del cfg['nodes']['tg__1']['interfaces']['xe1']['local_mac']
497
498         config_patch = mock.patch.object(self.s, 'context_cfg', cfg)
499         with config_patch:
500             with self.assertRaises(exceptions.IncorrectConfig):
501                 self.s.map_topology_to_infrastructure()
502
503     def test__resolve_topology_invalid_config(self):
504         with mock.patch("yardstick.ssh.SSH") as ssh:
505             ssh_mock = mock.Mock(autospec=ssh.SSH)
506             ssh_mock.execute = \
507                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
508             ssh.from_node.return_value = ssh_mock
509
510             # purge an important key from the data structure
511             for interface in self.tg__1['interfaces'].values():
512                 del interface['local_mac']
513
514             with self.assertRaises(exceptions.IncorrectConfig) as raised:
515                 self.s._resolve_topology()
516
517             self.assertIn('not found', str(raised.exception))
518
519             # restore local_mac
520             for index, interface in enumerate(self.tg__1['interfaces'].values()):
521                 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
522
523             # make a connection point ref with 3 points
524             self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
525                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
526
527             with self.assertRaises(exceptions.IncorrectConfig) as raised:
528                 self.s._resolve_topology()
529
530             self.assertIn('wrong endpoint count', str(raised.exception))
531
532             # make a connection point ref with 1 point
533             self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
534                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
535
536             with self.assertRaises(exceptions.IncorrectConfig) as raised:
537                 self.s._resolve_topology()
538
539             self.assertIn('wrong endpoint count', str(raised.exception))
540
541     def test_run(self):
542         tgen = mock.Mock(autospec=GenericTrafficGen)
543         tgen.traffic_finished = True
544         verified_dict = {"verified": True}
545         tgen.verify_traffic = lambda x: verified_dict
546         tgen.name = "tgen__1"
547         vnf = mock.Mock(autospec=GenericVNF)
548         vnf.runs_traffic = False
549         self.s.vnfs = [tgen, vnf]
550         self.s.traffic_profile = mock.Mock()
551         self.s.collector = mock.Mock(autospec=Collector)
552         self.s.collector.get_kpi = \
553             mock.Mock(return_value={tgen.name: verified_dict})
554         result = {}
555         self.s.run(result)
556         self.assertDictEqual(result, {tgen.name: verified_dict})
557
558     def test_setup(self):
559         with mock.patch("yardstick.ssh.SSH") as ssh:
560             ssh_mock = mock.Mock(autospec=ssh.SSH)
561             ssh_mock.execute = \
562                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
563             ssh.from_node.return_value = ssh_mock
564
565             tgen = mock.Mock(autospec=GenericTrafficGen)
566             tgen.traffic_finished = True
567             verified_dict = {"verified": True}
568             tgen.verify_traffic = lambda x: verified_dict
569             tgen.terminate = mock.Mock(return_value=True)
570             tgen.name = "tgen__1"
571             tgen.run_traffic.return_value = 'tg_id'
572             vnf = mock.Mock(autospec=GenericVNF)
573             vnf.runs_traffic = False
574             vnf.terminate = mock.Mock(return_value=True)
575             self.s.vnfs = [tgen, vnf]
576             self.s.traffic_profile = mock.Mock()
577             self.s.collector = mock.Mock(autospec=Collector)
578             self.s.collector.get_kpi = \
579                 mock.Mock(return_value={tgen.name: verified_dict})
580             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
581             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
582             self.s._fill_traffic_profile = \
583                 mock.Mock(return_value=TRAFFIC_PROFILE)
584
585     def test_setup_exception(self):
586         with mock.patch("yardstick.ssh.SSH") as ssh:
587             ssh_mock = mock.Mock(autospec=ssh.SSH)
588             ssh_mock.execute = \
589                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
590             ssh.from_node.return_value = ssh_mock
591
592             tgen = mock.Mock(autospec=GenericTrafficGen)
593             tgen.traffic_finished = True
594             verified_dict = {"verified": True}
595             tgen.verify_traffic = lambda x: verified_dict
596             tgen.terminate = mock.Mock(return_value=True)
597             tgen.name = "tgen__1"
598             vnf = mock.Mock(autospec=GenericVNF)
599             vnf.runs_traffic = False
600             vnf.instantiate.side_effect = RuntimeError(
601                 "error during instantiate")
602             vnf.terminate = mock.Mock(return_value=True)
603             self.s.vnfs = [tgen, vnf]
604             self.s.traffic_profile = mock.Mock()
605             self.s.collector = mock.Mock(autospec=Collector)
606             self.s.collector.get_kpi = \
607                 mock.Mock(return_value={tgen.name: verified_dict})
608             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
609             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
610             self.s._fill_traffic_profile = \
611                 mock.Mock(return_value=TRAFFIC_PROFILE)
612             with self.assertRaises(RuntimeError):
613                 self.s.setup()
614
615     def test__get_traffic_profile(self):
616         self.scenario_cfg["traffic_profile"] = \
617             self._get_file_abspath("ipv4_throughput_vpe.yaml")
618         self.assertIsNotNone(self.s._get_traffic_profile())
619
620     def test__get_traffic_profile_exception(self):
621         with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
622             with self.assertRaises(IOError):
623                 self.s._get_traffic_profile()
624
625     def test__key_list_to_dict(self):
626         result = self.s._key_list_to_dict("uplink", {"uplink": [1, 2]})
627         self.assertEqual({"uplink_0": 1, "uplink_1": 2}, result)
628
629     def test__get_simulated_users(self):
630         result = self.s._get_simulated_users()
631         self.assertEqual({'simulated_users': {'uplink_0': 1, 'uplink_1': 2}},
632                          result)
633
634     def test__get_page_object(self):
635         result = self.s._get_page_object()
636         self.assertEqual({'page_object': {'uplink_0': 1, 'uplink_1': 2}},
637                          result)
638
639     def test___get_traffic_imix_exception(self):
640         with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
641             self.assertEqual({'imix': {'64B': 100}},
642                              self.s._get_traffic_imix())
643
644     @mock.patch.object(base.TrafficProfile, 'get')
645     @mock.patch.object(vnfdgen, 'generate_vnfd')
646     def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get):
647         fake_tprofile = mock.Mock()
648         fake_vnfd = mock.MagicMock()
649         with mock.patch.object(self.s, '_get_traffic_profile',
650                                return_value=fake_tprofile) as mock_get_tp:
651             mock_generate.return_value = fake_vnfd
652             self.s._fill_traffic_profile()
653             mock_get_tp.assert_called_once()
654             mock_generate.assert_called_once_with(
655                 fake_tprofile,
656                 {'downlink': {},
657                  'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
658                  'flow': {'flow': {}},
659                  'imix': {'imix': {'64B': 100}},
660                  'uplink': {},
661                  'duration': 30,
662                  'simulated_users': {
663                      'simulated_users': {'uplink_0': 1, 'uplink_1': 2}},
664                  'page_object': {
665                      'page_object': {'uplink_0': 1, 'uplink_1': 2}},}
666             )
667             mock_tprofile_get.assert_called_once_with(fake_vnfd)
668
669     @mock.patch.object(base.TrafficProfile, 'get')
670     @mock.patch.object(vnfdgen, 'generate_vnfd')
671     def test__fill_traffic_profile2(self, mock_generate, mock_tprofile_get):
672         fake_tprofile = mock.Mock()
673         fake_vnfd = {}
674         with mock.patch.object(self.s, '_get_traffic_profile',
675                                return_value=fake_tprofile) as mock_get_tp:
676             mock_generate.return_value = fake_vnfd
677
678             self.s.scenario_cfg["options"] = {"traffic_config": {"duration": 99899}}
679             self.s._fill_traffic_profile()
680             mock_get_tp.assert_called_once()
681             self.assertIn("traffic_profile", fake_vnfd)
682             self.assertIn("duration", fake_vnfd["traffic_profile"])
683             self.assertEqual(99899, fake_vnfd["traffic_profile"]["duration"])
684
685     @mock.patch.object(utils, 'open_relative_file')
686     def test__get_topology(self, mock_open_path):
687         self.s.scenario_cfg['topology'] = 'fake_topology'
688         self.s.scenario_cfg['task_path'] = 'fake_path'
689         mock_open_path.side_effect = mock.mock_open(read_data='fake_data')
690         self.assertEqual('fake_data', self.s._get_topology())
691         mock_open_path.assert_called_once_with('fake_topology', 'fake_path')
692
693     @mock.patch.object(vnfdgen, 'generate_vnfd')
694     def test__render_topology(self, mock_generate):
695         fake_topology = 'fake_topology'
696         mock_generate.return_value = {'nsd:nsd-catalog': {'nsd': ['fake_nsd']}}
697         with mock.patch.object(self.s, '_get_topology',
698                                return_value=fake_topology) as mock_get_topology:
699             self.s._render_topology()
700             mock_get_topology.assert_called_once()
701
702         mock_generate.assert_called_once_with(
703             fake_topology,
704             {'extra_args': {'arg1': 'value1', 'arg2': 'value2'}}
705         )
706         self.assertEqual(self.s.topology, 'fake_nsd')
707
708     def test_get_mq_ids(self):
709         self.assertEqual(self.s._mq_ids, self.s.get_mq_ids())
710
711     def test_teardown(self):
712         vnf = mock.Mock(autospec=GenericVNF)
713         vnf.terminate = mock.Mock(return_value=True)
714         vnf.name = str(vnf)
715         self.s.vnfs = [vnf]
716         self.s.traffic_profile = mock.Mock()
717         self.s.collector = mock.Mock(autospec=Collector)
718         self.s.collector.stop = \
719             mock.Mock(return_value=True)
720         self.assertIsNone(self.s.teardown())
721
722     def test_teardown_exception(self):
723         vnf = mock.Mock(autospec=GenericVNF)
724         vnf.terminate = mock.Mock(
725             side_effect=RuntimeError("error duing terminate"))
726         vnf.name = str(vnf)
727         self.s.vnfs = [vnf]
728         self.s.traffic_profile = mock.Mock()
729         self.s.collector = mock.Mock(autospec=Collector)
730         self.s.collector.stop = \
731             mock.Mock(return_value=True)
732         with self.assertRaises(RuntimeError):
733             self.s.teardown()