Create a SampleVNF MQ consumer class
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_acl_vnf.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 import unittest
16 import mock
17 import os
18 import re
19 import copy
20
21 from yardstick.common import utils
22 from yardstick.common import exceptions
23 from yardstick.benchmark.contexts import base as ctx_base
24 from yardstick.network_services.vnf_generic.vnf import acl_vnf
25 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
26 from yardstick.network_services.nfvi.resource import ResourceProfile
27 from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
28 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
29
30
31 TEST_FILE_YAML = 'nsb_test_case.yaml'
32 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
33
34
35 name = 'vnf__1'
36
37
38 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
39 class TestAclApproxVnf(unittest.TestCase):
40     VNFD = {'vnfd:vnfd-catalog':
41             {'vnfd':
42              [{'short-name': 'VpeVnf',
43                'vdu':
44                [{'routing_table':
45                  [{'network': '152.16.100.20',
46                    'netmask': '255.255.255.0',
47                    'gateway': '152.16.100.20',
48                    'if': 'xe0'},
49                   {'network': '152.16.40.20',
50                    'netmask': '255.255.255.0',
51                    'gateway': '152.16.40.20',
52                    'if': 'xe1'}],
53                  'description': 'VPE approximation using DPDK',
54                  'name': 'vpevnf-baremetal',
55                  'nd_route_tbl':
56                  [{'network': '0064:ff9b:0:0:0:0:9810:6414',
57                    'netmask': '112',
58                    'gateway': '0064:ff9b:0:0:0:0:9810:6414',
59                    'if': 'xe0'},
60                   {'network': '0064:ff9b:0:0:0:0:9810:2814',
61                    'netmask': '112',
62                    'gateway': '0064:ff9b:0:0:0:0:9810:2814',
63                    'if': 'xe1'}],
64                  'id': 'vpevnf-baremetal',
65                  'external-interface':
66                  [{'virtual-interface':
67                    {'dst_mac': '00:00:00:00:00:04',
68                     'vpci': '0000:05:00.0',
69                     'local_ip': '152.16.100.19',
70                     'type': 'PCI-PASSTHROUGH',
71                     'netmask': '255.255.255.0',
72                     'dpdk_port_num': 0,
73                     'bandwidth': '10 Gbps',
74                     'driver': "i40e",
75                     'dst_ip': '152.16.100.20',
76                     'local_iface_name': 'xe0',
77                     'local_mac': '00:00:00:00:00:02'},
78                    'vnfd-connection-point-ref': 'xe0',
79                    'name': 'xe0'},
80                   {'virtual-interface':
81                    {'dst_mac': '00:00:00:00:00:03',
82                     'vpci': '0000:05:00.1',
83                     'local_ip': '152.16.40.19',
84                     'type': 'PCI-PASSTHROUGH',
85                     'driver': "i40e",
86                     'netmask': '255.255.255.0',
87                     'dpdk_port_num': 1,
88                     'bandwidth': '10 Gbps',
89                     'dst_ip': '152.16.40.20',
90                     'local_iface_name': 'xe1',
91                     'local_mac': '00:00:00:00:00:01'},
92                    'vnfd-connection-point-ref': 'xe1',
93                    'name': 'xe1'}]}],
94                'description': 'Vpe approximation using DPDK',
95                'mgmt-interface':
96                    {'vdu-id': 'vpevnf-baremetal',
97                     'host': '1.2.1.1',
98                     'password': 'r00t',
99                     'user': 'root',
100                     'ip': '1.2.1.1'},
101                'benchmark':
102                    {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
103                'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
104                                     {'type': 'VPORT', 'name': 'xe1'}],
105                'id': 'AclApproxVnf', 'name': 'VPEVnfSsh'}]}}
106
107     scenario_cfg = {'options': {'packetsize': 64, 'traffic_type': 4,
108                                 'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
109                                 'vnf__1': {'rules': 'acl_1rule.yaml',
110                                            'vnf_config': {'lb_config': 'SW',
111                                                           'lb_count': 1,
112                                                           'worker_config':
113                                                           '1C/1T',
114                                                           'worker_threads': 1}}
115                                 },
116                     'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
117                     'task_path': '/tmp',
118                     'tc': 'tc_ipv4_1Mflow_64B_packetsize',
119                     'runner': {'object': 'NetworkServiceTestCase',
120                                'interval': 35,
121                                'output_filename': '/tmp/yardstick.out',
122                                'runner_id': 74476, 'duration': 400,
123                                'type': 'Duration'},
124                     'traffic_profile': 'ipv4_throughput_acl.yaml',
125                     'traffic_options': {'flow': 'ipv4_Packets_acl.yaml',
126                                         'imix': 'imix_voice.yaml'},
127                     'type': 'ISB',
128                     'nodes': {'tg__2': 'trafficgen_2.yardstick',
129                               'tg__1': 'trafficgen_1.yardstick',
130                               'vnf__1': 'vnf.yardstick'},
131                     'topology': 'vpe-tg-topology-baremetal.yaml'}
132
133     context_cfg = {'nodes': {'tg__2':
134                              {'member-vnf-index': '3',
135                               'role': 'TrafficGen',
136                               'name': 'trafficgen_2.yardstick',
137                               'vnfd-id-ref': 'tg__2',
138                               'ip': '1.2.1.1',
139                               'interfaces':
140                               {'xe0': {'local_iface_name': 'ens513f0',
141                                        'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
142                                        'netmask': '255.255.255.0',
143                                        'local_ip': '152.16.40.20',
144                                        'dst_mac': '00:00:00:00:00:01',
145                                        'local_mac': '00:00:00:00:00:03',
146                                        'dst_ip': '152.16.40.19',
147                                        'driver': 'ixgbe',
148                                        'vpci': '0000:02:00.0',
149                                        'dpdk_port_num': 0},
150                                'xe1': {'local_iface_name': 'ens513f1',
151                                        'netmask': '255.255.255.0',
152                                        'network': '202.16.100.0',
153                                        'local_ip': '202.16.100.20',
154                                        'local_mac': '00:1e:67:d0:60:5d',
155                                        'driver': 'ixgbe',
156                                        'vpci': '0000:02:00.1',
157                                        'dpdk_port_num': 1}},
158                               'password': 'r00t',
159                               'VNF model': 'l3fwd_vnf.yaml',
160                               'user': 'root'},
161                              'tg__1':
162                              {'member-vnf-index': '1',
163                               'role': 'TrafficGen',
164                               'name': 'trafficgen_1.yardstick',
165                               'vnfd-id-ref': 'tg__1',
166                               'ip': '1.2.1.1',
167                               'interfaces':
168                               {'xe0': {'local_iface_name': 'ens785f0',
169                                        'vld_id': acl_vnf.AclApproxVnf.UPLINK,
170                                        'netmask': '255.255.255.0',
171                                        'local_ip': '152.16.100.20',
172                                        'dst_mac': '00:00:00:00:00:02',
173                                        'local_mac': '00:00:00:00:00:04',
174                                        'dst_ip': '152.16.100.19',
175                                        'driver': 'i40e',
176                                        'vpci': '0000:05:00.0',
177                                        'dpdk_port_num': 0},
178                                'xe1': {'local_iface_name': 'ens785f1',
179                                        'netmask': '255.255.255.0',
180                                        'local_ip': '152.16.100.21',
181                                        'local_mac': '00:00:00:00:00:01',
182                                        'driver': 'i40e',
183                                        'vpci': '0000:05:00.1',
184                                        'dpdk_port_num': 1}},
185                               'password': 'r00t',
186                               'VNF model': 'tg_rfc2544_tpl.yaml',
187                               'user': 'root'},
188                              'vnf__1':
189                              {'name': 'vnf.yardstick',
190                               'vnfd-id-ref': 'vnf__1',
191                               'ip': '1.2.1.1',
192                               'interfaces':
193                               {'xe0': {'local_iface_name': 'ens786f0',
194                                        'vld_id': acl_vnf.AclApproxVnf.UPLINK,
195                                        'netmask': '255.255.255.0',
196                                        'local_ip': '152.16.100.19',
197                                        'dst_mac': '00:00:00:00:00:04',
198                                        'local_mac': '00:00:00:00:00:02',
199                                        'dst_ip': '152.16.100.20',
200                                        'driver': 'i40e',
201                                        'vpci': '0000:05:00.0',
202                                        'dpdk_port_num': 0},
203                                'xe1': {'local_iface_name': 'ens786f1',
204                                        'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
205                                        'netmask': '255.255.255.0',
206                                        'local_ip': '152.16.40.19',
207                                        'dst_mac': '00:00:00:00:00:03',
208                                        'local_mac': '00:00:00:00:00:01',
209                                        'dst_ip': '152.16.40.20',
210                                        'driver': 'i40e',
211                                        'vpci': '0000:05:00.1',
212                                        'dpdk_port_num': 1}},
213                               'routing_table':
214                               [{'netmask': '255.255.255.0',
215                                 'gateway': '152.16.100.20',
216                                 'network': '152.16.100.20',
217                                 'if': 'xe0'},
218                                {'netmask': '255.255.255.0',
219                                 'gateway': '152.16.40.20',
220                                 'network': '152.16.40.20',
221                                 'if': 'xe1'}],
222                               'member-vnf-index': '2',
223                               'host': '1.2.1.1',
224                               'role': 'vnf',
225                               'user': 'root',
226                               'nd_route_tbl':
227                               [{'netmask': '112',
228                                 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
229                                 'network': '0064:ff9b:0:0:0:0:9810:6414',
230                                 'if': 'xe0'},
231                                {'netmask': '112',
232                                 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
233                                 'network': '0064:ff9b:0:0:0:0:9810:2814',
234                                 'if': 'xe1'}],
235                               'password': 'r00t',
236                               'VNF model': 'acl_vnf.yaml'}}}
237
238     def test___init__(self, *args):
239         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
240         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
241         self.assertIsNone(acl_approx_vnf._vnf_process)
242
243     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
244     @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
245     @mock.patch(SSH_HELPER)
246     def test_collect_kpi(self, ssh, *args):
247         mock_ssh(ssh)
248
249         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
250         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
251         acl_approx_vnf.scenario_helper.scenario_cfg = {
252             'nodes': {acl_approx_vnf.name: "mock"}
253         }
254         acl_approx_vnf.q_in = mock.MagicMock()
255         acl_approx_vnf.q_out = mock.MagicMock()
256         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
257         acl_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
258         acl_approx_vnf.vnf_execute = mock.Mock(return_value="")
259         result = {
260             'physical_node': 'mock_node',
261             'packets_dropped': 0,
262             'packets_fwd': 0,
263             'packets_in': 0
264         }
265         self.assertEqual(result, acl_approx_vnf.collect_kpi())
266
267     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
268     @mock.patch(SSH_HELPER)
269     def test_vnf_execute_command(self, ssh, *args):
270         mock_ssh(ssh)
271
272         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
273         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
274         acl_approx_vnf.q_in = mock.MagicMock()
275         acl_approx_vnf.q_out = mock.MagicMock()
276         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
277         cmd = "quit"
278         self.assertEqual("", acl_approx_vnf.vnf_execute(cmd))
279
280     @mock.patch(SSH_HELPER)
281     def test_get_stats(self, ssh, *args):
282         mock_ssh(ssh)
283
284         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
285         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
286         acl_approx_vnf.q_in = mock.MagicMock()
287         acl_approx_vnf.q_out = mock.MagicMock()
288         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
289         result = "ACL TOTAL: pkts_processed: 100, pkts_drop: 0, spkts_received: 100"
290         acl_approx_vnf.vnf_execute = mock.Mock(return_value=result)
291         self.assertEqual(result, acl_approx_vnf.get_stats())
292
293     def _get_file_abspath(self, filename):
294         curr_path = os.path.dirname(os.path.abspath(__file__))
295         file_path = os.path.join(curr_path, filename)
296         return file_path
297
298     @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.hex")
299     @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.eval")
300     @mock.patch('yardstick.network_services.vnf_generic.vnf.acl_vnf.open')
301     @mock.patch(SSH_HELPER)
302     def test_run_acl(self, ssh, *args):
303         mock_ssh(ssh)
304
305         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
306         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
307         acl_approx_vnf._build_config = mock.MagicMock()
308         acl_approx_vnf.queue_wrapper = mock.MagicMock()
309         acl_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
310         acl_approx_vnf.vnf_cfg = {'lb_config': 'SW',
311                                   'lb_count': 1,
312                                   'worker_config': '1C/1T',
313                                   'worker_threads': 1}
314         acl_approx_vnf.all_options = {'traffic_type': '4',
315                                       'topology': 'nsb_test_case.yaml'}
316         acl_approx_vnf._run()
317         acl_approx_vnf.ssh_helper.run.assert_called_once()
318
319     @mock.patch.object(utils, 'find_relative_file')
320     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
321     @mock.patch(SSH_HELPER)
322     def test_instantiate(self, ssh, *args):
323         mock_ssh(ssh)
324
325         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
326         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
327         acl_approx_vnf.deploy_helper = mock.MagicMock()
328         acl_approx_vnf.resource_helper = mock.MagicMock()
329         acl_approx_vnf._build_config = mock.MagicMock()
330         self.scenario_cfg['vnf_options'] = {'acl': {'cfg': "",
331                                                     'rules': ""}}
332         acl_approx_vnf.q_out.put("pipeline>")
333         acl_approx_vnf.WAIT_TIME = 0
334         self.scenario_cfg.update({"nodes": {"vnf__1": ""}})
335         self.assertIsNone(acl_approx_vnf.instantiate(self.scenario_cfg,
336                                                      self.context_cfg))
337
338     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
339     @mock.patch(SSH_HELPER)
340     def test_terminate(self, ssh, *args):
341         mock_ssh(ssh)
342
343         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
344         acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd, 'task_id')
345         acl_approx_vnf._vnf_process = mock.MagicMock()
346         acl_approx_vnf._vnf_process.terminate = mock.Mock()
347         acl_approx_vnf.used_drivers = {"01:01.0": "i40e",
348                                        "01:01.1": "i40e"}
349         acl_approx_vnf.vnf_execute = mock.MagicMock()
350         acl_approx_vnf.dpdk_devbind = "dpdk-devbind.py"
351         acl_approx_vnf._resource_collect_stop = mock.Mock()
352         self.assertIsNone(acl_approx_vnf.terminate())
353
354
355 class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
356
357     ACL_CONFIG = {"access-list-entries": [{
358                      "actions": [
359                        "count",
360                        {"fwd": {
361                            "port": 0
362                          }
363                        }
364                      ],
365                      "matches": {
366                        "destination-ipv4-network": "152.16.0.0/24",
367                        "destination-port-range": {
368                          "lower-port": 0,
369                          "upper-port": 65535
370                        },
371                        "source-ipv4-network": "0.0.0.0/0",
372                        "source-port-range": {
373                          "lower-port": 0,
374                          "upper-port": 65535
375                        },
376                        "protocol-mask": 255,
377                        "protocol": 127,
378                        "priority": 1
379                      },
380                      "rule-name": "rule1588"
381                    }
382                  ]}
383
384     def test_get_default_flows(self):
385         """Check if default ACL SampleVNF CLI commands are
386         generated correctly"""
387         ssh_helper = mock.Mock()
388         vnfd_helper = VnfdHelper({'vdu': [
389             {'external-interface': [
390                 {
391                     'virtual-interface': {
392                         'local_ip': '152.16.100.19',
393                         'netmask': '255.255.255.0',
394                         'dpdk_port_num': 0,
395                         'dst_ip': '152.16.100.20',
396                         'vld_id': 'uplink_0',
397                         'ifname': 'xe0',
398                     },
399                     'vnfd-connection-point-ref': 'xe0',
400                     'name': 'xe0'
401                 },
402                 {
403                     'virtual-interface': {
404                         'local_ip': '152.16.40.19',
405                         'netmask': '255.255.255.0',
406                         'dpdk_port_num': 1,
407                         'dst_ip': '152.16.40.20',
408                         'vld_id': 'downlink_0',
409                         'ifname': 'xe1',
410                     },
411                     'vnfd-connection-point-ref': 'xe1',
412                     'name': 'xe1'
413                 }
414             ]}
415         ]})
416         setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper, ssh_helper, None)
417         self.check_acl_commands(setup_helper.get_flows_config(), [
418             # format: (<cli pattern>, <number of expected matches>)
419             ("^p action add [0-9]+ accept$", 2),
420             ("^p action add [0-9]+ count$", 2),
421             ("^p action add [0-9]+ fwd 1$", 1),
422             ("^p action add [0-9]+ fwd 0$", 1),
423             ("^p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
424             ("^p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
425             ("^p acl applyruleset$", 1)
426         ])
427
428     @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
429     def test_get_flows_config(self, get_default_flows):
430         """Check if provided ACL config can be converted to
431         ACL SampleVNF CLI commands correctly"""
432         ssh_helper = mock.Mock()
433         setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
434         get_default_flows.return_value = ({}, [])
435         self.check_acl_commands(setup_helper.get_flows_config(self.ACL_CONFIG), [
436             # format: (<cli pattern>, <number of expected matches>)
437             ("^p action add [0-9]+ count$", 1),
438             ("^p action add [0-9]+ fwd 0$", 1),
439             ("^p acl add 1 0.0.0.0 0 152.16.0.0 24 0 65535 0 65535 127 0 [0-9]+$", 1),
440             ("^p acl applyruleset$", 1)
441         ])
442
443     @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
444     def test_get_flows_config_invalid_action(self, get_default_flows):
445         """Check if incorrect ACL config fails to convert
446         to ACL SampleVNF CLI commands"""
447         ssh_helper = mock.Mock()
448         setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
449         get_default_flows.return_value = ({}, [])
450         # duplicate config and add invald action
451         acl_config = copy.deepcopy(self.ACL_CONFIG)
452         acl_config['access-list-entries'][0]["actions"].append({"xnat": {}})
453         self.assertRaises(exceptions.AclUknownActionTemplate,
454             setup_helper.get_flows_config, acl_config)
455
456     @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
457     def test_get_flows_config_invalid_action_param(self, get_default_flows):
458         """Check if ACL config with invalid action parameter fails to convert
459         to ACL SampleVNF CLI commands"""
460         ssh_helper = mock.Mock()
461         setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
462         get_default_flows.return_value = ({}, [])
463         # duplicate config and add action with invalid parameter
464         acl_config = copy.deepcopy(self.ACL_CONFIG)
465         acl_config['access-list-entries'][0]["actions"].append(
466             {"nat": {"xport": 0}})
467         self.assertRaises(exceptions.AclMissingActionArguments,
468             setup_helper.get_flows_config, acl_config)
469
470     def check_acl_commands(self, config, expected_cli_patterns):
471         """Check if expected ACL CLI commands (given as a list of patterns,
472         `expected_cli_patterns` parameter) present in SampleVNF ACL
473         configuration (given as a multiline string, `config` parameter)"""
474         # Example of expected config:
475         # ---------------------------
476         # p action add 1 accept
477         # p action add 1 fwd 1
478         # p action add 2 accept
479         # p action add 2 count
480         # p action add 2 fwd 0
481         # p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 1
482         # p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 2
483         # p acl applyruleset
484         # ---------------------------
485         # NOTE: The config above consists of actions ids, which are actually
486         # unknown (generated at runtime), thus it's incorrect just to compare
487         # the example ACL config above with the configuration returned by
488         # get_flows_config() function. It's more correct to use CLI patterns
489         # (RE) to find the required SampleVNF CLI commands in the multiline
490         # string (SampleVNF ACL configuration).
491         for pattern, num_of_match in expected_cli_patterns:
492             # format: (<cli pattern>, <number of expected matches>)
493             result = re.findall(pattern, config, re.MULTILINE)
494             self.assertEqual(len(result), num_of_match)
495
496     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
497     @mock.patch.object(utils, 'find_relative_file')
498     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
499     @mock.patch.object(utils, 'open_relative_file')
500     def test_build_config(self, *args):
501         vnfd_helper = mock.Mock()
502         ssh_helper = mock.Mock()
503         scenario_helper = mock.Mock()
504         scenario_helper.vnf_cfg = {'lb_config': 'HW'}
505         scenario_helper.options = {}
506         scenario_helper.all_options = {}
507
508         acl_approx_setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper,
509                                                                   ssh_helper,
510                                                                   scenario_helper)
511
512         acl_approx_setup_helper.get_flows_config = mock.Mock()
513         acl_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
514         acl_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
515         acl_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
516         expected = 'sudo tool_path -p 0x3 -f /tmp/acl_config -s /tmp/acl_script  --hwlb 3'
517         self.assertEqual(acl_approx_setup_helper.build_config(), expected)
518         acl_approx_setup_helper.get_flows_config.assert_called_once()