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 from multiprocessing import Process, Queue
23 import six.moves.configparser as configparser
26 from tests.unit import STL_MOCKS
27 from tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
28 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
29 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
30 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
33 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
35 STLClient = mock.MagicMock()
36 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
40 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
41 from yardstick.network_services.nfvi.resource import ResourceProfile
42 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import \
43 VpeApproxVnf, VpeApproxSetupEnvHelper
46 TEST_FILE_YAML = 'nsb_test_case.yaml'
50 PING_OUTPUT_1 = "Pkts in: 101\r\n\tPkts dropped by AH: 100\r\n\tPkts dropped by other: 100"
52 MODULE_PATH = FileAbsPath(__file__)
53 get_file_abspath = MODULE_PATH.get_path
56 class TestConfigCreate(unittest.TestCase):
59 'short-name': 'VpeVnf',
64 'network': '152.16.100.20',
65 'netmask': '255.255.255.0',
66 'gateway': '152.16.100.20',
70 'network': '152.16.40.20',
71 'netmask': '255.255.255.0',
72 'gateway': '152.16.40.20',
76 'description': 'VPE approximation using DPDK',
77 'name': 'vpevnf-baremetal',
80 'network': '0064:ff9b:0:0:0:0:9810:6414',
82 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
86 'network': '0064:ff9b:0:0:0:0:9810:2814',
88 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
92 'id': 'vpevnf-baremetal',
93 'external-interface': [
95 'virtual-interface': {
96 'dst_mac': '00:00:00:00:00:03',
97 'vpci': '0000:05:00.0',
98 'local_ip': '152.16.100.19',
99 'type': 'PCI-PASSTHROUGH',
100 'netmask': '255.255.255.0',
102 'bandwidth': '10 Gbps',
103 'dst_ip': '152.16.100.20',
104 'local_mac': '00:00:00:00:00:01',
105 'vld_id': 'uplink_0',
108 'vnfd-connection-point-ref': 'xe0',
112 'virtual-interface': {
113 'dst_mac': '00:00:00:00:00:04',
114 'vpci': '0000:05:00.1',
115 'local_ip': '152.16.40.19',
116 'type': 'PCI-PASSTHROUGH',
117 'netmask': '255.255.255.0',
119 'bandwidth': '10 Gbps',
120 'dst_ip': '152.16.40.20',
121 'local_mac': '00:00:00:00:00:02',
122 'vld_id': 'downlink_0',
125 'vnfd-connection-point-ref': 'xe1',
131 'description': 'Vpe approximation using DPDK',
133 'vdu-id': 'vpevnf-baremetal',
146 'connection-point': [
156 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
159 def test___init__(self):
160 vnfd_helper = VnfdHelper(self.VNFD_0)
161 config_create = ConfigCreate(vnfd_helper, 2)
162 self.assertEqual(config_create.uplink_ports, ['xe0'])
163 self.assertEqual(config_create.downlink_ports, ['xe1'])
164 self.assertEqual(config_create.socket, 2)
166 def test_dpdk_port_to_link_id(self):
167 vnfd_helper = VnfdHelper(self.VNFD_0)
168 config_create = ConfigCreate(vnfd_helper, 2)
169 self.assertEqual(config_create.dpdk_port_to_link_id_map, {'xe0': 0, 'xe1': 1})
171 def test_vpe_initialize(self):
172 vnfd_helper = VnfdHelper(self.VNFD_0)
173 config_create = ConfigCreate(vnfd_helper, 2)
174 config = configparser.ConfigParser()
175 config_create.vpe_initialize(config)
176 self.assertEqual(config.get('EAL', 'log_level'), '0')
177 self.assertEqual(config.get('PIPELINE0', 'type'), 'MASTER')
178 self.assertEqual(config.get('PIPELINE0', 'core'), 's2C0')
179 self.assertEqual(config.get('MEMPOOL0', 'pool_size'), '256K')
180 self.assertEqual(config.get('MEMPOOL1', 'pool_size'), '2M')
182 def test_vpe_rxq(self):
183 vnfd_helper = VnfdHelper(self.VNFD_0)
184 config_create = ConfigCreate(vnfd_helper, 2)
185 config = configparser.ConfigParser()
186 config_create.downlink_ports = ['xe0']
187 config_create.vpe_rxq(config)
188 self.assertEqual(config.get('RXQ0.0', 'mempool'), 'MEMPOOL1')
190 def test_get_sink_swq(self):
191 vnfd_helper = VnfdHelper(self.VNFD_0)
192 config_create = ConfigCreate(vnfd_helper, 2)
193 config = configparser.ConfigParser()
194 config.add_section('PIPELINE0')
195 config.set('PIPELINE0', 'key1', 'value1')
196 config.set('PIPELINE0', 'key2', 'value2 SINK')
197 config.set('PIPELINE0', 'key3', 'TM value3')
198 config.set('PIPELINE0', 'key4', 'value4')
199 config.set('PIPELINE0', 'key5', 'the SINK value5')
201 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key1', 5), 'SWQ-1')
202 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key2', 5), 'SWQ-1 SINK0')
203 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key3', 5), 'SWQ-1 TM5')
204 config_create.sw_q += 1
205 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key4', 5), 'SWQ0')
206 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key5', 5), 'SWQ0 SINK1')
208 def test_generate_vpe_script(self):
209 vnfd_helper = VnfdHelper(self.VNFD_0)
210 vpe_config_vnf = ConfigCreate(vnfd_helper, 2)
214 "virtual-interface": {
216 "dst_mac": "00:00:00:00:00:00:02",
221 "virtual-interface": {
223 "dst_mac": "00:00:00:00:00:00:02",
227 vpe_config_vnf.downlink_ports = ['xe1']
228 vpe_config_vnf.uplink_ports = ['xe2']
229 result = vpe_config_vnf.generate_vpe_script(intf)
230 self.assertIsInstance(result, str)
231 self.assertNotEqual(result, '')
233 def test_create_vpe_config(self):
234 vnfd_helper = VnfdHelper(self.VNFD_0)
235 config_create = ConfigCreate(vnfd_helper, 23)
236 config_create.downlink_ports = ['xe1']
237 config_create.uplink_ports = ['xe1']
238 curr_path = os.path.dirname(os.path.abspath(__file__))
239 vpe_cfg = "samples/vnf_samples/nsut/vpe/vpe_config"
240 vnf_cfg = os.path.join(curr_path, "../../../../..", vpe_cfg)
241 config_create.create_vpe_config(vnf_cfg)
242 os.system("git checkout -- %s" % vnf_cfg)
245 class TestVpeApproxVnf(unittest.TestCase):
248 'short-name': 'VpeVnf',
253 'network': '152.16.100.20',
254 'netmask': '255.255.255.0',
255 'gateway': '152.16.100.20',
259 'network': '152.16.40.20',
260 'netmask': '255.255.255.0',
261 'gateway': '152.16.40.20',
265 'description': 'VPE approximation using DPDK',
266 'name': 'vpevnf-baremetal',
269 'network': '0064:ff9b:0:0:0:0:9810:6414',
271 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
275 'network': '0064:ff9b:0:0:0:0:9810:2814',
277 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
281 'id': 'vpevnf-baremetal',
282 'external-interface': [
284 'virtual-interface': {
285 'dst_mac': '00:00:00:00:00:04',
286 'vpci': '0000:05:00.0',
287 'local_ip': '152.16.100.19',
288 'type': 'PCI-PASSTHROUGH',
289 'netmask': '255.255.255.0',
291 'bandwidth': '10 Gbps',
293 'dst_ip': '152.16.100.20',
294 'local_iface_name': 'xe0',
295 'local_mac': '00:00:00:00:00:02',
296 'vld_id': 'uplink_0',
299 'vnfd-connection-point-ref': 'xe0',
303 'virtual-interface': {
304 'dst_mac': '00:00:00:00:00:03',
305 'vpci': '0000:05:00.1',
306 'local_ip': '152.16.40.19',
307 'type': 'PCI-PASSTHROUGH',
309 'netmask': '255.255.255.0',
311 'bandwidth': '10 Gbps',
312 'dst_ip': '152.16.40.20',
313 'local_iface_name': 'xe1',
314 'local_mac': '00:00:00:00:00:01',
315 'vld_id': 'downlink_0',
318 'vnfd-connection-point-ref': 'xe1',
324 'description': 'Vpe approximation using DPDK',
326 'vdu-id': 'vpevnf-baremetal',
339 'connection-point': [
349 'id': 'VpeApproxVnf',
354 'vnfd:vnfd-catalog': {
366 'allowed_drop_rate': '0.8 - 1',
369 'cfg': 'acl_1rule.yaml',
379 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
380 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
382 'object': 'NetworkServiceTestCase',
384 'output_filename': '/tmp/yardstick.out',
389 'traffic_profile': 'ipv4_throughput_vpe.yaml',
391 'flow': 'ipv4_Packets_vpe.yaml',
392 'imix': 'imix_voice.yaml',
396 'tg__2': 'trafficgen_2.yardstick',
397 'tg__1': 'trafficgen_1.yardstick',
398 'vnf__1': 'vnf.yardstick',
400 'topology': 'vpe-tg-topology-baremetal.yaml',
406 'member-vnf-index': '3',
407 'role': 'TrafficGen',
408 'name': 'trafficgen_2.yardstick',
409 'vnfd-id-ref': 'tg__2',
413 'local_iface_name': 'ens513f0',
414 'vld_id': VpeApproxVnf.DOWNLINK,
415 'netmask': '255.255.255.0',
416 'local_ip': '152.16.40.20',
417 'dst_mac': '00:00:00:00:00:01',
418 'local_mac': '00:00:00:00:00:03',
419 'dst_ip': '152.16.40.19',
421 'vpci': '0000:02:00.0',
425 'local_iface_name': 'ens513f1',
426 'netmask': '255.255.255.0',
427 'network': '202.16.100.0',
428 'local_ip': '202.16.100.20',
429 'local_mac': '00:1e:67:d0:60:5d',
431 'vpci': '0000:02:00.1',
436 'VNF model': 'l3fwd_vnf.yaml',
440 'member-vnf-index': '1',
441 'role': 'TrafficGen',
442 'name': 'trafficgen_1.yardstick',
443 'vnfd-id-ref': 'tg__1',
447 'local_iface_name': 'ens785f0',
448 'vld_id': VpeApproxVnf.UPLINK,
449 'netmask': '255.255.255.0',
450 'local_ip': '152.16.100.20',
451 'dst_mac': '00:00:00:00:00:02',
452 'local_mac': '00:00:00:00:00:04',
453 'dst_ip': '152.16.100.19',
455 'vpci': '0000:05:00.0',
459 'local_iface_name': 'ens785f1',
460 'netmask': '255.255.255.0',
461 'local_ip': '152.16.100.21',
462 'local_mac': '00:00:00:00:00:01',
464 'vpci': '0000:05:00.1',
469 'VNF model': 'tg_rfc2544_tpl.yaml',
473 'name': 'vnf.yardstick',
474 'vnfd-id-ref': 'vnf__1',
478 'local_iface_name': 'ens786f0',
479 'vld_id': VpeApproxVnf.UPLINK,
480 'netmask': '255.255.255.0',
481 'local_ip': '152.16.100.19',
482 'dst_mac': '00:00:00:00:00:04',
483 'local_mac': '00:00:00:00:00:02',
484 'dst_ip': '152.16.100.20',
486 'vpci': '0000:05:00.0',
490 'local_iface_name': 'ens786f1',
491 'vld_id': VpeApproxVnf.DOWNLINK,
492 'netmask': '255.255.255.0',
493 'local_ip': '152.16.40.19',
494 'dst_mac': '00:00:00:00:00:03',
495 'local_mac': '00:00:00:00:00:01',
496 'dst_ip': '152.16.40.20',
498 'vpci': '0000:05:00.1',
504 'netmask': '255.255.255.0',
505 'gateway': '152.16.100.20',
506 'network': '152.16.100.20',
510 'netmask': '255.255.255.0',
511 'gateway': '152.16.40.20',
512 'network': '152.16.40.20',
516 'member-vnf-index': '2',
523 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
524 'network': '0064:ff9b:0:0:0:0:9810:6414',
529 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
530 'network': '0064:ff9b:0:0:0:0:9810:2814',
535 'VNF model': 'vpe_vnf.yaml',
541 self.mock_sleep = mock.patch.object(time, 'sleep').start()
543 def test___init__(self):
544 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
545 self.assertIsNone(vpe_approx_vnf._vnf_process)
547 @mock.patch(SSH_HELPER)
548 def test_collect_kpi_sa_not_running(self, ssh):
551 resource = mock.Mock(autospec=ResourceProfile)
552 resource.check_if_system_agent_running.return_value = 1, ''
553 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
554 resource.check_if_system_agent_running.return_value = (1, None)
556 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
557 vpe_approx_vnf.q_in = mock.MagicMock()
558 vpe_approx_vnf.q_out = mock.MagicMock()
559 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
560 vpe_approx_vnf.resource_helper.resource = resource
563 'pkt_in_down_stream': 0,
564 'pkt_in_up_stream': 0,
565 'pkt_drop_down_stream': 0,
566 'pkt_drop_up_stream': 0,
567 'collect_stats': {'core': {}},
569 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
571 @mock.patch(SSH_HELPER)
572 def test_collect_kpi_sa_running(self, ssh):
575 resource = mock.Mock(autospec=ResourceProfile)
576 resource.check_if_system_agent_running.return_value = 0, '1234'
577 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
579 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
580 vpe_approx_vnf.q_in = mock.MagicMock()
581 vpe_approx_vnf.q_out = mock.MagicMock()
582 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
583 vpe_approx_vnf.resource_helper.resource = resource
586 'pkt_in_down_stream': 0,
587 'pkt_in_up_stream': 0,
588 'pkt_drop_down_stream': 0,
589 'pkt_drop_up_stream': 0,
590 'collect_stats': {'core': {'foo': 234}},
592 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
594 @mock.patch(SSH_HELPER)
595 def test_vnf_execute(self, ssh):
597 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
598 vpe_approx_vnf.q_in = mock.MagicMock()
599 vpe_approx_vnf.q_out = mock.MagicMock()
600 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
601 self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
603 @mock.patch(SSH_HELPER)
604 def test_run_vpe(self, ssh):
607 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
608 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
609 vpe_approx_vnf.vnf_cfg = {
612 'worker_config': '1C/1T',
615 vpe_approx_vnf.scenario_helper.scenario_cfg = {
619 'topology': 'nsb_test_case.yaml',
620 'vnf_config': 'vpe_config',
624 vpe_approx_vnf.topology = "nsb_test_case.yaml"
625 vpe_approx_vnf.nfvi_type = "baremetal"
626 vpe_approx_vnf._provide_config_file = mock.Mock()
627 vpe_approx_vnf._build_config = mock.MagicMock()
629 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
630 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
631 self.assertIsNone(vpe_approx_vnf._run())
633 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
634 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
635 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
636 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.open")
637 @mock.patch(SSH_HELPER)
638 def test_build_config(self, ssh, *args):
640 vpe_approx_vnf = VpeApproxSetupEnvHelper(mock.MagicMock(),
641 mock.MagicMock(), mock.MagicMock())
642 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
643 vpe_approx_vnf.generate_port_pairs = mock.Mock()
644 vpe_approx_vnf.vnf_cfg = {
647 'worker_config': '1C/1T',
650 vpe_approx_vnf.scenario_helper.scenario_cfg = {
654 'topology': 'nsb_test_case.yaml',
655 'vnf_config': 'vpe_config',
659 vpe_approx_vnf.topology = "nsb_test_case.yaml"
660 vpe_approx_vnf.nfvi_type = "baremetal"
661 vpe_approx_vnf._provide_config_file = mock.Mock()
663 vpe_approx_vnf.ssh_helper = mock.MagicMock()
664 vpe_approx_vnf.scenario_helper = mock.MagicMock()
665 vpe_approx_vnf.ssh_helper.bin_path = mock.Mock()
666 vpe_approx_vnf.ssh_helper.upload_config_file = mock.MagicMock()
667 self.assertIsNone(vpe_approx_vnf._build_vnf_ports())
668 self.assertIsNotNone(vpe_approx_vnf.build_config())
670 @mock.patch(SSH_HELPER)
671 def test_wait_for_instantiate(self, ssh):
674 mock_process = mock.Mock(autospec=Process)
675 mock_process.is_alive.return_value = True
676 mock_process.exitcode = 432
678 mock_q_out = mock.Mock(autospec=Queue)
679 mock_q_out.get.side_effect = iter(["pipeline>"])
680 mock_q_out.qsize.side_effect = range(1, -1, -1)
682 mock_resource = mock.MagicMock()
684 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
685 vpe_approx_vnf._vnf_process = mock_process
686 vpe_approx_vnf.q_out = mock_q_out
687 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
688 vpe_approx_vnf.resource_helper.resource = mock_resource
690 vpe_approx_vnf.q_out.put("pipeline>")
691 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
693 @mock.patch(SSH_HELPER)
694 def test_wait_for_instantiate_fragmented(self, ssh):
697 mock_process = mock.Mock(autospec=Process)
698 mock_process.is_alive.return_value = True
699 mock_process.exitcode = 432
701 # test that fragmented pipeline prompt is recognized
702 mock_q_out = mock.Mock(autospec=Queue)
703 mock_q_out.get.side_effect = iter(["wow pipel", "ine>"])
704 mock_q_out.qsize.side_effect = range(2, -1, -1)
706 mock_resource = mock.MagicMock()
708 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
709 vpe_approx_vnf._vnf_process = mock_process
710 vpe_approx_vnf.q_out = mock_q_out
711 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
712 vpe_approx_vnf.resource_helper.resource = mock_resource
714 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
716 @mock.patch(SSH_HELPER)
717 def test_wait_for_instantiate_crash(self, ssh):
718 mock_ssh(ssh, exec_result=(1, "", ""))
720 mock_process = mock.Mock(autospec=Process)
721 mock_process.is_alive.return_value = False
722 mock_process.exitcode = 432
724 mock_resource = mock.MagicMock()
726 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
727 vpe_approx_vnf._vnf_process = mock_process
728 vpe_approx_vnf.resource_helper.resource = mock_resource
730 with self.assertRaises(RuntimeError) as raised:
731 vpe_approx_vnf.wait_for_instantiate()
733 self.assertIn('VNF process died', str(raised.exception))
735 @mock.patch(SSH_HELPER)
736 def test_wait_for_instantiate_panic(self, ssh):
737 mock_ssh(ssh, exec_result=(1, "", ""))
739 mock_process = mock.Mock(autospec=Process)
740 mock_process.is_alive.return_value = True
741 mock_process.exitcode = 432
743 mock_resource = mock.MagicMock()
745 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
746 vpe_approx_vnf._vnf_process = mock_process
747 vpe_approx_vnf.resource_helper.resource = mock_resource
749 vpe_approx_vnf.q_out.put("PANIC")
750 with self.assertRaises(RuntimeError) as raised:
751 vpe_approx_vnf.wait_for_instantiate()
753 self.assertIn('Error starting', str(raised.exception))
755 @mock.patch(SSH_HELPER)
756 def test_wait_for_instantiate_panic_fragmented(self, ssh):
757 mock_ssh(ssh, exec_result=(1, "", ""))
759 mock_process = mock.Mock(autospec=Process)
760 mock_process.is_alive.return_value = True
761 mock_process.exitcode = 432
763 # test that fragmented PANIC is recognized
764 mock_q_out = mock.Mock(autospec=Queue)
765 mock_q_out.get.side_effect = iter(["omg PA", "NIC this is bad"])
766 mock_q_out.qsize.side_effect = range(2, -1, -1)
768 mock_resource = mock.MagicMock()
770 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
771 vpe_approx_vnf._vnf_process = mock_process
772 vpe_approx_vnf.q_out = mock_q_out
773 vpe_approx_vnf.resource_helper.resource = mock_resource
775 with self.assertRaises(RuntimeError) as raised:
776 vpe_approx_vnf.wait_for_instantiate()
778 self.assertIn('Error starting', str(raised.exception))
780 @mock.patch(SSH_HELPER)
781 def test_terminate(self, ssh):
784 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
785 vpe_approx_vnf._vnf_process = mock.MagicMock()
786 vpe_approx_vnf._resource_collect_stop = mock.Mock()
787 vpe_approx_vnf.resource_helper = mock.MagicMock()
789 self.assertIsNone(vpe_approx_vnf.terminate())