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