Merge "Yardstick TC082: move sample test case perf.yaml"
[yardstick.git] / tests / unit / network_services / vnf_generic / vnf / test_vpe_vnf.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016-2017 Intel Corporation
4 #
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
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16 #
17
18 from __future__ import absolute_import
19 import six.moves.configparser as configparser
20
21 import os
22 import unittest
23 import mock
24 from multiprocessing import Process, Queue
25
26 from tests.unit import STL_MOCKS
27 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
28
29
30 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
31
32 STLClient = mock.MagicMock()
33 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
34 stl_patch.start()
35
36 if stl_patch:
37     from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
38     from yardstick.network_services.nfvi.resource import ResourceProfile
39     from yardstick.network_services.vnf_generic.vnf import vpe_vnf
40     from yardstick.network_services.vnf_generic.vnf.vpe_vnf import VpeApproxVnf
41
42 from tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
43 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
44
45
46 TEST_FILE_YAML = 'nsb_test_case.yaml'
47
48 NAME = 'vnf_1'
49
50 PING_OUTPUT_1 = "Pkts in: 101\r\n\tPkts dropped by AH: 100\r\n\tPkts dropped by other: 100"
51
52 MODULE_PATH = FileAbsPath(__file__)
53 get_file_abspath = MODULE_PATH.get_path
54
55
56 class TestConfigCreate(unittest.TestCase):
57
58     def test___init__(self):
59         config_create = ConfigCreate([0], [1], 2)
60         self.assertEqual(config_create.priv_ports, [0])
61         self.assertEqual(config_create.pub_ports, [1])
62         self.assertEqual(config_create.socket, 2)
63
64     def test_vpe_initialize(self):
65         config_create = ConfigCreate([0], [1], 2)
66         config = configparser.ConfigParser()
67         config_create.vpe_initialize(config)
68         self.assertEqual(config.get('EAL', 'log_level'), '0')
69         self.assertEqual(config.get('PIPELINE0', 'type'), 'MASTER')
70         self.assertEqual(config.get('PIPELINE0', 'core'), 's2C0')
71         self.assertEqual(config.get('MEMPOOL0', 'pool_size'), '256K')
72         self.assertEqual(config.get('MEMPOOL1', 'pool_size'), '2M')
73
74     def test_vpe_rxq(self):
75         config_create = ConfigCreate([0], [1, 2], 3)
76         config = configparser.ConfigParser()
77         config_create.vpe_rxq(config)
78         self.assertEqual(config.get('RXQ1.0', 'mempool'), 'MEMPOOL1')
79         self.assertEqual(config.get('RXQ2.0', 'mempool'), 'MEMPOOL1')
80
81     def test_get_sink_swq(self):
82         config_create = ConfigCreate([0], [1], 2)
83         config = configparser.ConfigParser()
84         config.add_section('PIPELINE0')
85         config.set('PIPELINE0', 'key1', 'value1')
86         config.set('PIPELINE0', 'key2', 'value2 SINK')
87         config.set('PIPELINE0', 'key3', 'TM value3')
88         config.set('PIPELINE0', 'key4', 'value4')
89         config.set('PIPELINE0', 'key5', 'the SINK value5')
90
91         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key1', 5), 'SWQ-1')
92         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key2', 5), 'SWQ-1 SINK0')
93         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key3', 5), 'SWQ-1 TM5')
94         config_create.sw_q += 1
95         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key4', 5), 'SWQ0')
96         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key5', 5), 'SWQ0 SINK1')
97
98     def test_generate_vpe_script(self):
99         vpe_config_vnf = ConfigCreate([0], [0], 0)
100         intf = [
101             {
102                 "virtual-interface": {
103                     "dst_ip": "1.1.1.1",
104                     "dst_mac": "00:00:00:00:00:00:02",
105                 },
106             },
107         ]
108         result = vpe_config_vnf.generate_vpe_script(intf)
109         self.assertIsInstance(result, str)
110         self.assertNotEqual(result, '')
111
112     def test_create_vpe_config(self):
113         priv_ports = [
114             {
115                 'index': 0,
116                 'dpdk_port_num': 1,
117                 'peer_intf': {
118                     'dpdk_port_num': 2,
119                     'index': 3,
120                 },
121             },
122         ]
123
124         pub_ports = [
125             {
126                 'index': 2,
127                 'dpdk_port_num': 3,
128                 'peer_intf': {
129                     'dpdk_port_num': 0,
130                     'index': 1,
131                 },
132             },
133         ]
134
135         config_create = ConfigCreate(priv_ports, pub_ports, 23)
136         curr_path = os.path.dirname(os.path.abspath(__file__))
137         vpe_cfg = "samples/vnf_samples/nsut/vpe/vpe_config"
138         vnf_cfg = os.path.join(curr_path, "../../../../..", vpe_cfg)
139         config_create.create_vpe_config(vnf_cfg)
140         os.system("git checkout -- %s" % vnf_cfg)
141
142
143 @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
144 class TestVpeApproxVnf(unittest.TestCase):
145
146     VNFD_0 = {
147         'short-name': 'VpeVnf',
148         'vdu': [
149             {
150                 'routing_table': [
151                     {
152                         'network': '152.16.100.20',
153                         'netmask': '255.255.255.0',
154                         'gateway': '152.16.100.20',
155                         'if': 'xe0',
156                     },
157                     {
158                         'network': '152.16.40.20',
159                         'netmask': '255.255.255.0',
160                         'gateway': '152.16.40.20',
161                         'if': 'xe1',
162                     },
163                 ],
164                 'description': 'VPE approximation using DPDK',
165                 'name': 'vpevnf-baremetal',
166                 'nd_route_tbl': [
167                     {
168                         'network': '0064:ff9b:0:0:0:0:9810:6414',
169                         'netmask': '112',
170                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
171                         'if': 'xe0',
172                     },
173                     {
174                         'network': '0064:ff9b:0:0:0:0:9810:2814',
175                         'netmask': '112',
176                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
177                         'if': 'xe1',
178                     },
179                 ],
180                 'id': 'vpevnf-baremetal',
181                 'external-interface': [
182                     {
183                         'virtual-interface': {
184                             'dst_mac': '00:00:00:00:00:04',
185                             'vpci': '0000:05:00.0',
186                             'local_ip': '152.16.100.19',
187                             'type': 'PCI-PASSTHROUGH',
188                             'vld_id': '',
189                             'netmask': '255.255.255.0',
190                             'dpdk_port_num': '0',
191                             'bandwidth': '10 Gbps',
192                             'driver': "i40e",
193                             'dst_ip': '152.16.100.20',
194                             'local_iface_name': 'xe0',
195                             'local_mac': '00:00:00:00:00:02',
196                         },
197                         'vnfd-connection-point-ref': 'xe0',
198                         'name': 'xe0',
199                     },
200                     {
201                         'virtual-interface': {
202                             'dst_mac': '00:00:00:00:00:03',
203                             'vpci': '0000:05:00.1',
204                             'local_ip': '152.16.40.19',
205                             'type': 'PCI-PASSTHROUGH',
206                             'vld_id': '',
207                             'driver': "i40e",
208                             'netmask': '255.255.255.0',
209                             'dpdk_port_num': '1',
210                             'bandwidth': '10 Gbps',
211                             'dst_ip': '152.16.40.20',
212                             'local_iface_name': 'xe1',
213                             'local_mac': '00:00:00:00:00:01',
214                         },
215                         'vnfd-connection-point-ref': 'xe1',
216                         'name': 'xe1',
217                     },
218                 ],
219             },
220         ],
221         'description': 'Vpe approximation using DPDK',
222         'mgmt-interface': {
223             'vdu-id': 'vpevnf-baremetal',
224             'host': '1.2.1.1',
225             'password': 'r00t',
226             'user': 'root',
227             'ip': '1.2.1.1',
228         },
229         'benchmark': {
230             'kpi': [
231                 'packets_in',
232                 'packets_fwd',
233                 'packets_dropped',
234             ],
235         },
236         'connection-point': [
237             {
238                 'type': 'VPORT',
239                 'name': 'xe0',
240             },
241             {
242                 'type': 'VPORT',
243                 'name': 'xe1',
244             },
245         ],
246         'id': 'VpeApproxVnf',
247         'name': 'VPEVnfSsh',
248     }
249
250     VNFD = {
251         'vnfd:vnfd-catalog': {
252             'vnfd': [
253                 VNFD_0,
254             ],
255         },
256     }
257
258     SCENARIO_CFG = {
259         'options': {
260             'packetsize': 64,
261             'traffic_type': 4 ,
262             'rfc2544': {
263                 'allowed_drop_rate': '0.8 - 1',
264             },
265             'vnf__1': {
266                 'cfg': 'acl_1rule.yaml',
267                 'vnf_config': {
268                     'lb_config': 'SW',
269                     'lb_count': 1,
270                     'worker_config':
271                     '1C/1T',
272                     'worker_threads': 1,
273                 },
274             }
275         },
276         'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
277         'tc': 'tc_ipv4_1Mflow_64B_packetsize',
278         'runner': {
279             'object': 'NetworkServiceTestCase',
280             'interval': 35,
281             'output_filename': '/tmp/yardstick.out',
282             'runner_id': 74476,
283             'duration': 400,
284             'type': 'Duration',
285         },
286         'traffic_profile': 'ipv4_throughput_vpe.yaml',
287         'traffic_options': {
288             'flow': 'ipv4_Packets_vpe.yaml',
289             'imix': 'imix_voice.yaml',
290         },
291         'type': 'ISB',
292         'nodes': {
293             'tg__2': 'trafficgen_2.yardstick',
294             'tg__1': 'trafficgen_1.yardstick',
295             'vnf__1': 'vnf.yardstick',
296         },
297         'topology': 'vpe-tg-topology-baremetal.yaml',
298     }
299
300     CONTEXT_CFG = {
301         'nodes': {
302             'tg__2': {
303                 'member-vnf-index': '3',
304                 'role': 'TrafficGen',
305                 'name': 'trafficgen_2.yardstick',
306                 'vnfd-id-ref': 'tg__2',
307                 'ip': '1.2.1.1',
308                 'interfaces': {
309                     'xe0': {
310                         'local_iface_name': 'ens513f0',
311                         'vld_id': 'public',
312                         'netmask': '255.255.255.0',
313                         'local_ip': '152.16.40.20',
314                         'dst_mac': '00:00:00:00:00:01',
315                         'local_mac': '00:00:00:00:00:03',
316                         'dst_ip': '152.16.40.19',
317                         'driver': 'ixgbe',
318                         'vpci': '0000:02:00.0',
319                         'dpdk_port_num': 0,
320                     },
321                     'xe1': {
322                         'local_iface_name': 'ens513f1',
323                         'netmask': '255.255.255.0',
324                         'network': '202.16.100.0',
325                         'local_ip': '202.16.100.20',
326                         'local_mac': '00:1e:67:d0:60:5d',
327                         'driver': 'ixgbe',
328                         'vpci': '0000:02:00.1',
329                         'dpdk_port_num': 1,
330                     },
331                 },
332                 'password': 'r00t',
333                 'VNF model': 'l3fwd_vnf.yaml',
334                 'user': 'root',
335             },
336             'tg__1': {
337                 'member-vnf-index': '1',
338                 'role': 'TrafficGen',
339                 'name': 'trafficgen_1.yardstick',
340                 'vnfd-id-ref': 'tg__1',
341                 'ip': '1.2.1.1',
342                 'interfaces': {
343                     'xe0': {
344                         'local_iface_name': 'ens785f0',
345                         'vld_id': 'private',
346                         'netmask': '255.255.255.0',
347                         'local_ip': '152.16.100.20',
348                         'dst_mac': '00:00:00:00:00:02',
349                         'local_mac': '00:00:00:00:00:04',
350                         'dst_ip': '152.16.100.19',
351                         'driver': 'i40e',
352                         'vpci': '0000:05:00.0',
353                         'dpdk_port_num': 0,
354                     },
355                     'xe1': {
356                         'local_iface_name': 'ens785f1',
357                         'netmask': '255.255.255.0',
358                         'local_ip': '152.16.100.21',
359                         'local_mac': '00:00:00:00:00:01',
360                         'driver': 'i40e',
361                         'vpci': '0000:05:00.1',
362                         'dpdk_port_num': 1,
363                     },
364                 },
365                 'password': 'r00t',
366                 'VNF model': 'tg_rfc2544_tpl.yaml',
367                 'user': 'root',
368             },
369             'vnf__1': {
370                 'name': 'vnf.yardstick',
371                 'vnfd-id-ref': 'vnf__1',
372                 'ip': '1.2.1.1',
373                 'interfaces': {
374                     'xe0': {
375                         'local_iface_name': 'ens786f0',
376                         'vld_id': 'private',
377                         'netmask': '255.255.255.0',
378                         'local_ip': '152.16.100.19',
379                         'dst_mac': '00:00:00:00:00:04',
380                         'local_mac': '00:00:00:00:00:02',
381                         'dst_ip': '152.16.100.20',
382                         'driver': 'i40e',
383                         'vpci': '0000:05:00.0',
384                         'dpdk_port_num': 0,
385                     },
386                     'xe1': {
387                         'local_iface_name': 'ens786f1',
388                         'vld_id': 'public',
389                         'netmask': '255.255.255.0',
390                         'local_ip': '152.16.40.19',
391                         'dst_mac': '00:00:00:00:00:03',
392                         'local_mac': '00:00:00:00:00:01',
393                         'dst_ip': '152.16.40.20',
394                         'driver': 'i40e',
395                         'vpci': '0000:05:00.1',
396                         'dpdk_port_num': 1,
397                     },
398                 },
399                 'routing_table': [
400                     {
401                         'netmask': '255.255.255.0',
402                         'gateway': '152.16.100.20',
403                         'network': '152.16.100.20',
404                         'if': 'xe0',
405                     },
406                     {
407                         'netmask': '255.255.255.0',
408                         'gateway': '152.16.40.20',
409                         'network': '152.16.40.20',
410                         'if': 'xe1',
411                     },
412                 ],
413                 'member-vnf-index': '2',
414                 'host': '1.2.1.1',
415                 'role': 'vnf',
416                 'user': 'root',
417                 'nd_route_tbl': [
418                     {
419                         'netmask': '112',
420                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
421                         'network': '0064:ff9b:0:0:0:0:9810:6414',
422                         'if': 'xe0',
423                     },
424                     {
425                         'netmask': '112',
426                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
427                         'network': '0064:ff9b:0:0:0:0:9810:2814',
428                         'if': 'xe1',
429                     },
430                 ],
431                 'password': 'r00t',
432                 'VNF model': 'vpe_vnf.yaml',
433             },
434         },
435     }
436
437     def test___init__(self, _):
438         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
439         self.assertIsNone(vpe_approx_vnf._vnf_process)
440
441     @mock.patch(SSH_HELPER)
442     def test_collect_kpi_sa_not_running(self, ssh, _):
443         mock_ssh(ssh)
444
445         resource = mock.Mock(autospec=ResourceProfile)
446         resource.check_if_sa_running.return_value = False, 'error'
447         resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
448
449         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
450         vpe_approx_vnf.q_in = mock.MagicMock()
451         vpe_approx_vnf.q_out = mock.MagicMock()
452         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
453         vpe_approx_vnf.resource_helper.resource = resource
454
455         expected = {
456             'pkt_in_down_stream': 0,
457             'pkt_in_up_stream': 0,
458             'pkt_drop_down_stream': 0,
459             'pkt_drop_up_stream': 0,
460             'collect_stats': {'core': {}},
461         }
462         self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
463
464     @mock.patch(SSH_HELPER)
465     def test_collect_kpi_sa_running(self, ssh, _):
466         mock_ssh(ssh)
467
468         resource = mock.Mock(autospec=ResourceProfile)
469         resource.check_if_sa_running.return_value = True, 'good'
470         resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
471
472         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
473         vpe_approx_vnf.q_in = mock.MagicMock()
474         vpe_approx_vnf.q_out = mock.MagicMock()
475         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
476         vpe_approx_vnf.resource_helper.resource = resource
477
478         expected = {
479             'pkt_in_down_stream': 0,
480             'pkt_in_up_stream': 0,
481             'pkt_drop_down_stream': 0,
482             'pkt_drop_up_stream': 0,
483             'collect_stats': {'core': {'foo': 234}},
484         }
485         self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
486
487     @mock.patch(SSH_HELPER)
488     def test_vnf_execute(self, ssh, _):
489         mock_ssh(ssh)
490         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
491         vpe_approx_vnf.q_in = mock.MagicMock()
492         vpe_approx_vnf.q_out = mock.MagicMock()
493         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
494         self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
495
496     @mock.patch(SSH_HELPER)
497     def test_run_vpe(self, ssh, _):
498         mock_ssh(ssh)
499
500         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
501         vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
502         vpe_approx_vnf.generate_port_pairs = mock.Mock()
503         vpe_approx_vnf.tg_port_pairs = [[[0], [1]]]
504         vpe_approx_vnf.vnf_port_pairs = [[[0], [1]]]
505         vpe_approx_vnf.vnf_cfg = {
506             'lb_config': 'SW',
507             'lb_count': 1,
508             'worker_config': '1C/1T',
509             'worker_threads': 1,
510         }
511         vpe_approx_vnf.scenario_helper.scenario_cfg = {
512             'options': {
513                 NAME: {
514                     'traffic_type': '4',
515                     'topology': 'nsb_test_case.yaml',
516                 }
517             }
518         }
519         vpe_approx_vnf.topology = "nsb_test_case.yaml"
520         vpe_approx_vnf.nfvi_type = "baremetal"
521         vpe_approx_vnf._provide_config_file = mock.Mock()
522
523         self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
524         self.assertIsNone(vpe_approx_vnf._run())
525
526     @mock.patch(SSH_HELPER)
527     def test_wait_for_instantiate(self, ssh, _):
528         mock_ssh(ssh)
529
530         mock_process = mock.Mock(autospec=Process)
531         mock_process.is_alive.return_value = True
532         mock_process.exitcode = 432
533
534         mock_q_out = mock.Mock(autospec=Queue)
535         mock_q_out.get.side_effect = iter(["pipeline>"])
536         mock_q_out.qsize.side_effect = range(1, -1, -1)
537
538         mock_resource = mock.MagicMock()
539
540         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
541         vpe_approx_vnf._vnf_process = mock_process
542         vpe_approx_vnf.q_out = mock_q_out
543         vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
544         vpe_approx_vnf.resource_helper.resource = mock_resource
545
546         vpe_approx_vnf.q_out.put("pipeline>")
547         self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
548
549     @mock.patch(SSH_HELPER)
550     def test_wait_for_instantiate_fragmented(self, ssh, _):
551         mock_ssh(ssh)
552
553         mock_process = mock.Mock(autospec=Process)
554         mock_process.is_alive.return_value = True
555         mock_process.exitcode = 432
556
557         # test that fragmented pipeline prompt is recognized
558         mock_q_out = mock.Mock(autospec=Queue)
559         mock_q_out.get.side_effect = iter(["wow pipel", "ine>"])
560         mock_q_out.qsize.side_effect = range(2, -1, -1)
561
562         mock_resource = mock.MagicMock()
563
564         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
565         vpe_approx_vnf._vnf_process = mock_process
566         vpe_approx_vnf.q_out = mock_q_out
567         vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
568         vpe_approx_vnf.resource_helper.resource = mock_resource
569
570         self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
571
572     @mock.patch(SSH_HELPER)
573     def test_wait_for_instantiate_crash(self, ssh, _):
574         mock_ssh(ssh, exec_result=(1, "", ""))
575
576         mock_process = mock.Mock(autospec=Process)
577         mock_process.is_alive.return_value = False
578         mock_process.exitcode = 432
579
580         mock_resource = mock.MagicMock()
581
582         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
583         vpe_approx_vnf._vnf_process = mock_process
584         vpe_approx_vnf.resource_helper.resource = mock_resource
585
586         with self.assertRaises(RuntimeError) as raised:
587             vpe_approx_vnf.wait_for_instantiate()
588
589         self.assertIn('VNF process died', str(raised.exception))
590
591     @mock.patch(SSH_HELPER)
592     def test_wait_for_instantiate_panic(self, ssh, _):
593         mock_ssh(ssh, exec_result=(1, "", ""))
594
595         mock_process = mock.Mock(autospec=Process)
596         mock_process.is_alive.return_value = True
597         mock_process.exitcode = 432
598
599         mock_resource = mock.MagicMock()
600
601         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
602         vpe_approx_vnf._vnf_process = mock_process
603         vpe_approx_vnf.resource_helper.resource = mock_resource
604
605         vpe_approx_vnf.q_out.put("PANIC")
606         with self.assertRaises(RuntimeError) as raised:
607             vpe_approx_vnf.wait_for_instantiate()
608
609         self.assertIn('Error starting', str(raised.exception))
610
611     @mock.patch(SSH_HELPER)
612     def test_wait_for_instantiate_panic_fragmented(self, ssh, _):
613         mock_ssh(ssh, exec_result=(1, "", ""))
614
615         mock_process = mock.Mock(autospec=Process)
616         mock_process.is_alive.return_value = True
617         mock_process.exitcode = 432
618
619         # test that fragmented PANIC is recognized
620         mock_q_out = mock.Mock(autospec=Queue)
621         mock_q_out.get.side_effect = iter(["omg PA", "NIC this is bad"])
622         mock_q_out.qsize.side_effect = range(2, -1, -1)
623
624         mock_resource = mock.MagicMock()
625
626         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
627         vpe_approx_vnf._vnf_process = mock_process
628         vpe_approx_vnf.q_out = mock_q_out
629         vpe_approx_vnf.resource_helper.resource = mock_resource
630
631         with self.assertRaises(RuntimeError) as raised:
632             vpe_approx_vnf.wait_for_instantiate()
633
634         self.assertIn('Error starting', str(raised.exception))
635
636     def test_scale(self, _):
637         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
638         with self.assertRaises(NotImplementedError):
639             vpe_approx_vnf.scale('')
640
641     @mock.patch(SSH_HELPER)
642     def test_terminate(self, ssh, _):
643         mock_ssh(ssh)
644
645         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
646         vpe_approx_vnf._vnf_process = mock.MagicMock()
647         vpe_approx_vnf._resource_collect_stop = mock.Mock()
648         vpe_approx_vnf.resource_helper = mock.MagicMock()
649
650         self.assertIsNone(vpe_approx_vnf.terminate())
651
652
653 if __name__ == '__main__':
654     unittest.main()