Merge "NSB: Improve get_url in ansible scripts"
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_tg_landslide.py
1 # Copyright (c) 2018-2019 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 copy
16 import mock
17 import requests
18 import time
19 import unittest
20
21 from yardstick.benchmark.contexts import base as ctx_base
22 from yardstick.common import exceptions
23 from yardstick.common import utils as common_utils
24 from yardstick.common import yaml_loader
25 from yardstick.network_services import utils as net_serv_utils
26 from yardstick.network_services.traffic_profile import landslide_profile
27 from yardstick.network_services.vnf_generic.vnf import sample_vnf
28 from yardstick.network_services.vnf_generic.vnf import tg_landslide
29 from yardstick.network_services.vnf_generic.vnf import base as vnf_base
30
31 NAME = "tg__0"
32
33 EXAMPLE_URL = 'http://example.com/'
34 TCL_SUCCESS_RESPONSE = 'ls_ok'
35
36 TEST_SERVERS = [
37     {'ip': '192.168.122.101',
38      'phySubnets': [
39          {'mask': '/24',
40           'base': '10.42.32.100',
41           'numIps': 20,
42           'name': 'eth1'}
43      ],
44      'role': 'SGW_Node',
45      'name': 'TestServer_1'},
46     {'ip': '192.168.122.102',
47      'phySubnets': [
48          {'mask': '/24',
49           'base': '10.42.32.1',
50           'numIps': 100,
51           'name': 'eth1'
52           },
53          {'mask': '/24',
54           'base': '10.42.33.1',
55           'numIps': 100,
56           'name': 'eth2'}
57      ],
58      'preResolvedArpAddress': [
59          {'NumNodes': 1,
60           'StartingAddress': '10.42.33.5'}
61      ],
62      'role': 'SGW_Nodal',
63      'name': 'TestServer_2',
64      'thread_model': 'Fireball'
65      }
66 ]
67
68 TS1_SUTS = [
69     {'name': 'SGW - C TestNode',
70      'role': 'SgwControlAddr',
71      'managementIp': '12.0.1.1',
72      'ip': '10.42.32.100',
73      'phy': 'eth5',
74      'nextHop': '10.42.32.5'
75      },
76     {'name': 'SGW - U TestNode',
77      'role': 'SgwUserAddr',
78      'managementIp': '12.0.1.2',
79      'ip': '10.42.32.101',
80      'phy': 'eth5',
81      'nextHop': '10.42.32.5'
82      }
83 ]
84
85 TS2_SUTS = [
86     {'name': 'eNodeB TestNode',
87      'role': 'EnbUserAddr',
88      'managementIp': '12.0.2.1',
89      'ip': '10.42.32.2',
90      'phy': 'eth5',
91      'nextHop': '10.42.32.5'
92      },
93     {'name': 'MME TestNode',
94      'role': 'MmeControlAddr',
95      'managementIp': '12.0.3.1',
96      'ip': '10.42.32.1',
97      'phy': 'eth5',
98      'nextHop': '10.42.32.5'
99      },
100     {'name': 'NetHost TestNode',
101      'role': 'NetworkHostAddrLocal',
102      'managementIp': '12.0.4.1',
103      'ip': '10.42.33.1',
104      'phy': 'eth5',
105      'nextHop': '10.42.32.5'
106      },
107     {'name': 'PGW TestNode',
108      'role': 'PgwV4Sut',
109      'managementIp': '12.0.5.1',
110      'ip': '10.42.32.105',
111      'phy': 'eth5',
112      'nextHop': '10.42.32.5'
113      },
114     {'name': 'SGW - C SUT',
115      'role': 'SgwSut',
116      'managementIp': '12.0.6.1',
117      'ip': '10.42.32.100'
118      },
119     {'name': 'SGW - U SUT',
120      'role': 'SgwUserSut',
121      'managementIp': '12.0.6.2',
122      'ip': '10.42.32.101'}
123 ]
124
125 VNFD = {
126     'vnfd:vnfd-catalog': {
127         'vnfd': [{
128             'short-name': 'landslide',
129             'vdu': [{
130                 'description': 'AB client interface details',
131                 'name': 'abclient-baremetal',
132                 'id': 'abclient-baremetal',
133                 'external-interface': []}],
134             'description': 'Spirent Landslide traffic generator',
135             'config': [{'test_server': TEST_SERVERS[0], 'suts': TS1_SUTS},
136                        {'test_server': TEST_SERVERS[1], 'suts': TS2_SUTS}],
137             'mgmt-interface': {
138                 'vdu-id': 'landslide-tas',
139                 'user': 'user',
140                 'password': 'user',
141                 'super-user': 'super-user',
142                 'super-user-password': 'super-user-password',
143                 'cfguser_password': 'cfguser_password',
144                 'license': 48,
145                 'proto': 'http',
146                 'ip': '1.1.1.1'},
147             'benchmark': {
148                 'kpi': [
149                     'tx_throughput_mbps',
150                     'rx_throughput_mbps',
151                     'in_packets',
152                     'out_packets',
153                     'activation_rate_sessps',
154                     'deactivation_rate_sessps']},
155             'id': 'LandslideTrafficGen',
156             'name': 'LandslideTrafficGen'}]}}
157
158 TAS_INFO = VNFD['vnfd:vnfd-catalog']['vnfd'][0]['mgmt-interface']
159
160 DMF_CFG = {
161     "dmf": {
162         "library": "test",
163         "name": "Basic UDP"
164     },
165     "clientPort": {
166         "clientPort": 2002,
167         "isClientPortRange": "false"
168     },
169     "dataProtocol": "udp",
170     "serverPort": 2003
171 }
172
173 RESERVATIONS = [
174     {'tsName': TEST_SERVERS[0]['name'],
175      'phySubnets': TEST_SERVERS[0]['phySubnets'],
176      'tsId': TEST_SERVERS[0]['name'],
177      'tsIndex': 0},
178     {'tsName': TEST_SERVERS[1]['name'],
179      'phySubnets': TEST_SERVERS[1]['phySubnets'],
180      'tsId': TEST_SERVERS[1]['name'],
181      'tsIndex': 1}]
182
183 SESSION_PROFILE = {
184     'keywords': '',
185     'duration': 60,
186     'iterations': 1,
187     'description': 'UE default bearer creation test case',
188     'name': 'default_bearer_capacity',
189     'reportOptions': {'format': 'CSV'},
190     'reservePorts': 'false',
191     'tsGroups': [
192         {
193             'testCases': [{
194                 'type': 'SGW_Node',
195                 'name': '',
196                 'linked': "false",
197                 'AssociatedPhys': '',
198                 'parameters': {
199                     'SgiPtpTunnelEn': 'false',
200                     'Gtp2Imsi': '505024101215074',
201                     'Sessions': '100000',
202                     'S5Protocol': 'GTPv2',
203                     'TrafficMtu': '1500',
204                     'Gtp2Version': '13.6.0',
205                     'BearerV4AddrPool': '1.0.0.1',
206                     'Gtp2Imei': '50502410121507',
207                     'PgwNodeEn': 'true',
208                     'DedicatedsPerDefaultBearer': '0',
209                     'DefaultBearers': '1',
210                     'SgwUserAddr': {
211                         'numLinksOrNodes': 1,
212                         'phy': 'eth1',
213                         'forcedEthInterface': '',
214                         'ip': 'SGW_USER_IP',
215                         'class': 'TestNode',
216                         'ethStatsEnabled': "false",
217                         'mtu': 1500
218                     },
219                     'SgwControlAddr': {
220                         'numLinksOrNodes': 1,
221                         'phy': 'eth1',
222                         'forcedEthInterface': '',
223                         'ip': 'SGW_CONTROL_IP',
224                         'class': 'TestNode',
225                         'ethStatsEnabled': "false",
226                         'mtu': 1500,
227                         'nextHop': 'SGW_CONTROL_NEXT_HOP'
228                     },
229                     'BearerAddrPool': '2001::1',
230                     'TestType': 'SGW-NODE'
231                 }
232             }],
233             'tsId': TEST_SERVERS[0]['name']},
234         {
235             'testCases': [{
236                 'type': 'SGW_Nodal',
237                 'name': '',
238                 'parameters': {
239                     'DataTraffic': 'Continuous',
240                     'TrafficStartType': 'When All Sessions Established',
241                     'NetworkHost': 'Local',
242                     'Gtp2Imsi': '505024101215074',
243                     'Dmf': {
244                         'mainflows': [
245                             {
246                                 'name': 'Basic UDP',
247                                 'library': 'test'
248                             }
249                         ],
250                         'class': 'Dmf',
251                         'instanceGroups': [
252                             {
253                                 'startPaused': "false",
254                                 'rate': 0,
255                                 'mainflowIdx': 0,
256                                 'mixType': ''
257                             }
258                         ]
259                     },
260                     'S5Protocol': 'GTPv2',
261                     'DataUserCfgFileEn': 'false',
262                     'PgwUserSutEn': 'false',
263                     'MmeControlAddr': {
264                         'numLinksOrNodes': 1,
265                         'phy': 'eth1',
266                         'forcedEthInterface': '',
267                         'ip': 'MME_CONTROL_IP',
268                         'class': 'TestNode',
269                         'ethStatsEnabled': "false",
270                         'mtu': 1500
271                     },
272                     'SgwUserSut': {
273                         'class': 'Sut',
274                         'name': 'SGW_USER_NAME'
275                     },
276                     'TestActivity': 'Capacity Test',
277                     'NetworkHostAddrLocal': {
278                         'numLinksOrNodes': 1,
279                         'phy': 'eth2',
280                         'forcedEthInterface': '',
281                         'ip': 'NET_HOST_IP',
282                         'class': 'TestNode',
283                         'ethStatsEnabled': "false",
284                         'mtu': 1500
285                     },
286                     'DedicatedsPerDefaultBearer': '0',
287                     'DisconnectRate': '1000.0',
288                     'Sessions': '100000',
289                     'SgwSut': {
290                         'class': 'Sut',
291                         'name': 'SGW_CONTROL_NAME'
292                     },
293                     'TrafficMtu': '1500',
294                     'Gtp2Version': '13.6.0',
295                     'Gtp2Imei': '50502410121507',
296                     'PgwNodeEn': 'false',
297                     'StartRate': '1000.0',
298                     'PgwV4Sut': {
299                         'class': 'Sut',
300                         'name': 'PGW_SUT_NAME'
301                     },
302                     'DefaultBearers': '1',
303                     'EnbUserAddr': {
304                         'numLinksOrNodes': 1,
305                         'phy': 'eth1',
306                         'forcedEthInterface': '',
307                         'ip': 'ENB_USER_IP',
308                         'class': 'TestNode',
309                         'ethStatsEnabled': "false",
310                         'mtu': 1500
311                     },
312                     'TestType': 'SGW-NODAL'
313                 }
314             }],
315             'tsId': TEST_SERVERS[1]['name']
316         }
317     ]
318 }
319
320
321 class TestLandslideTrafficGen(unittest.TestCase):
322     SCENARIO_CFG = {
323         'session_profile': '/traffic_profiles/landslide/'
324                            'landslide_session_default_bearer.yaml',
325         'task_path': '',
326         'runner': {
327             'type': 'Iteration',
328             'iterations': 1
329         },
330         'nodes': {
331             'tg__0': 'tg__0.traffic_gen',
332             'vnf__0': 'vnf__0.vnf_epc'
333         },
334         'topology': 'landslide_tg_topology.yaml',
335         'type': 'NSPerf',
336         'traffic_profile': '../../traffic_profiles/landslide/'
337                            'landslide_dmf_udp.yaml',
338         'options': {
339             'traffic_duration': 71,
340             'test_cases': [
341                 {
342                     'BearerAddrPool': '2002::2',
343                     'type': 'SGW_Node',
344                     'BearerV4AddrPool': '2.0.0.2',
345                     'Sessions': '90000'
346                 },
347                 {
348                     'StartRate': '900.0',
349                     'type': 'SGW_Nodal',
350                     'DisconnectRate': '900.0',
351                     'Sessions': '90000'
352                 }
353             ],
354             'dmf':
355                 {
356                     'transactionRate': 1000,
357                     'packetSize': 512
358                 }
359         }
360     }
361
362     CONTEXT_CFG = {
363         'contexts': [
364             {
365                 'type': 'Node',
366                 'name': 'traffic_gen',
367                 'file': '/etc/yardstick/nodes/pod_landslide.yaml'
368             },
369             {
370                 'type': 'Node',
371                 'name': 'vnf_epc',
372                 'file': '/etc/yardstick/nodes/pod_vepc_sut.yaml'
373             }
374         ]
375     }
376
377     TRAFFIC_PROFILE = {
378         "schema": "nsb:traffic_profile:0.1",
379         "name": "LandslideProfile",
380         "description": "Spirent Landslide traffic profile",
381         "traffic_profile": {
382             "traffic_type": "LandslideProfile"
383         },
384         "dmf_config": {
385             "dmf": {
386                 "library": "test",
387                 "name": "Basic UDP"
388             },
389             "description": "Basic data flow using UDP/IP",
390             "keywords": "UDP",
391             "dataProtocol": "udp"
392         }
393     }
394
395     SUCCESS_CREATED_CODE = 201
396     SUCCESS_OK_CODE = 200
397     SUCCESS_RECORD_ID = 5
398     TEST_USER_ID = 11
399
400     def setUp(self):
401         self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
402         self.mock_lsapi.start()
403
404         self.mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
405         self.mock_ssh_helper.start()
406         self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
407         self.ls_tg = tg_landslide.LandslideTrafficGen(
408             NAME, self.vnfd)
409         self.session_profile = copy.deepcopy(SESSION_PROFILE)
410         self.ls_tg.session_profile = self.session_profile
411
412         self.addCleanup(self._cleanup)
413
414     def _cleanup(self):
415         self.mock_lsapi.stop()
416         self.mock_ssh_helper.stop()
417
418     @mock.patch.object(net_serv_utils, 'get_nsb_option')
419     def test___init__(self, mock_get_nsb_option, *args):
420         _path_to_nsb = 'path/to/nsb'
421         mock_get_nsb_option.return_value = _path_to_nsb
422         ls_tg = tg_landslide.LandslideTrafficGen(NAME, self.vnfd)
423         self.assertIsInstance(ls_tg.resource_helper,
424                               tg_landslide.LandslideResourceHelper)
425         mock_get_nsb_option.assert_called_once_with('bin_path')
426         self.assertEqual(_path_to_nsb, ls_tg.bin_path)
427         self.assertEqual(NAME, ls_tg.name)
428         self.assertTrue(ls_tg.runs_traffic)
429         self.assertFalse(ls_tg.traffic_finished)
430         self.assertIsNone(ls_tg.session_profile)
431
432     def test_listen_traffic(self):
433         _traffic_profile = {}
434         self.assertIsNone(self.ls_tg.listen_traffic(_traffic_profile))
435
436     def test_terminate(self, *args):
437         self.ls_tg.resource_helper._tcl = mock.Mock()
438         self.assertIsNone(self.ls_tg.terminate())
439         self.ls_tg.resource_helper._tcl.disconnect.assert_called_once()
440
441     @mock.patch.object(ctx_base.Context, 'get_context_from_server',
442                        return_value='fake_context')
443     def test_instantiate(self, *args):
444         self.ls_tg._tg_process = mock.Mock()
445         self.ls_tg._tg_process.start = mock.Mock()
446         self.ls_tg.resource_helper.connect = mock.Mock()
447         self.ls_tg.resource_helper.create_test_servers = mock.Mock()
448         self.ls_tg.resource_helper.create_suts = mock.Mock()
449         self.ls_tg._load_session_profile = mock.Mock()
450         self.assertIsNone(self.ls_tg.instantiate(self.SCENARIO_CFG,
451                                                  self.CONTEXT_CFG))
452         self.ls_tg.resource_helper.connect.assert_called_once()
453         self.ls_tg.resource_helper.create_test_servers.assert_called_once()
454         _suts_blocks_num = len([item['suts'] for item in self.vnfd['config']])
455         self.assertEqual(_suts_blocks_num,
456                          self.ls_tg.resource_helper.create_suts.call_count)
457         self.ls_tg._load_session_profile.assert_called_once()
458
459     @mock.patch.object(tg_landslide.LandslideResourceHelper,
460                        'get_running_tests')
461     def test_run_traffic(self, mock_get_tests, *args):
462         self.ls_tg.resource_helper._url = EXAMPLE_URL
463         self.ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
464         mock_traffic_profile = mock.Mock(
465             spec=landslide_profile.LandslideProfile)
466         mock_traffic_profile.dmf_config = {
467             'keywords': 'UDP',
468             'dataProtocol': 'udp',
469             'dmf': {'library': 'test', 'name': 'name'}}
470         mock_traffic_profile.params = self.TRAFFIC_PROFILE
471         self.ls_tg.resource_helper._user_id = self.TEST_USER_ID
472         mock_get_tests.return_value = [{'id': self.SUCCESS_RECORD_ID,
473                                         'testStateOrStep': 'COMPLETE'}]
474         mock_post = mock.Mock()
475         mock_post.status_code = self.SUCCESS_CREATED_CODE
476         mock_post.json.return_value = {'id': self.SUCCESS_RECORD_ID}
477         mock_session = mock.Mock(spec=requests.Session)
478         mock_session.post.return_value = mock_post
479         self.ls_tg.resource_helper.session = mock_session
480         self.ls_tg.resource_helper._tcl = mock.Mock()
481         _tcl = self.ls_tg.resource_helper._tcl
482         self.assertIsNone(self.ls_tg.run_traffic(mock_traffic_profile))
483         self.assertEqual(self.SUCCESS_RECORD_ID,
484                          self.ls_tg.resource_helper.run_id)
485         mock_traffic_profile.update_dmf.assert_called_with(
486             self.ls_tg.scenario_helper.all_options)
487         _tcl.create_dmf.assert_called_with(mock_traffic_profile.dmf_config)
488         _tcl.create_test_session.assert_called_with(self.session_profile)
489
490     @mock.patch.object(tg_landslide.LandslideResourceHelper,
491                        'check_running_test_state')
492     def test_collect_kpi(self, mock_check_running_test_state, *args):
493         self.ls_tg.resource_helper.run_id = self.SUCCESS_RECORD_ID
494         mock_check_running_test_state.return_value = 'COMPLETE'
495         self.assertEqual({'done': True}, self.ls_tg.collect_kpi())
496         mock_check_running_test_state.assert_called_once()
497
498     def test_wait_for_instantiate(self):
499         self.assertIsNone(self.ls_tg.wait_for_instantiate())
500         self.ls_tg.wait_for_instantiate()
501
502     def test__update_session_suts_no_tc_role(self, *args):
503         _suts = [{'role': 'epc_role'}]
504         _testcase = {'parameters': {'diff_epc_role': {'class': 'Sut'}}}
505         res = self.ls_tg._update_session_suts(_suts, _testcase)
506         self.assertEqual(_testcase, res)
507
508     def test__update_session_suts(self, *args):
509
510         def get_testnode_param(role, key, session_prof):
511             """ Get value by key from the deep nested dict to avoid calls like:
512             e.g. session_prof['tsGroups'][0]['testCases'][1]['parameters'][key]
513             """
514             for group in session_prof['tsGroups']:
515                 for tc in group['testCases']:
516                     tc_params = tc['parameters']
517                     if tc_params.get(role):
518                         return tc_params[role][key]
519
520         def get_sut_param(role, key, suts):
521             """ Search list of dicts for one with specific role.
522             Return the value of related dict by key. Expect key presence.
523             """
524             for sut in suts:
525                 if sut.get('role') == role:
526                     return sut[key]
527
528         # TestNode to verify
529         testnode_role = 'SgwControlAddr'
530         # SUT to verify
531         sut_role = 'SgwUserSut'
532
533         config_suts = [config['suts'] for config in self.vnfd['config']]
534         session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
535                        for _tc in _ts_group['testCases']]
536         for suts, tc in zip(config_suts, session_tcs):
537             self.assertEqual(tc, self.ls_tg._update_session_suts(suts, tc))
538
539         # Verify TestNode class objects keys were updated
540         for _key in {'ip', 'phy', 'nextHop'}:
541             self.assertEqual(
542                 get_testnode_param(testnode_role, _key, self.ls_tg.session_profile),
543                 get_sut_param(testnode_role, _key, TS1_SUTS))
544         # Verify Sut class objects name was updated
545         self.assertEqual(
546             get_testnode_param(sut_role, 'name', self.ls_tg.session_profile),
547             get_sut_param(sut_role, 'name', TS2_SUTS))
548
549     def test__update_session_test_servers(self, *args):
550         for ts_index, ts in enumerate(TEST_SERVERS):
551             self.assertIsNone(
552                 self.ls_tg._update_session_test_servers(ts, ts_index))
553         # Verify preResolvedArpAddress key was added
554         self.assertTrue(any(
555             _item.get('preResolvedArpAddress')
556             for _item in self.ls_tg.session_profile['tsGroups']))
557         # Verify reservations key was added to session profile
558         self.assertEqual(RESERVATIONS,
559                          self.ls_tg.session_profile.get('reservations'))
560         self.assertEqual('true',
561                          self.ls_tg.session_profile.get('reservePorts'))
562
563     def test__update_session_tc_params_assoc_phys(self):
564         _tc_options = {'AssociatedPhys': 'eth1'}
565         _testcase = {}
566         _testcase_orig = copy.deepcopy(_testcase)
567         res = self.ls_tg._update_session_tc_params(_tc_options, _testcase)
568         self.assertNotEqual(_testcase_orig, res)
569         self.assertEqual(_tc_options, _testcase)
570
571     def test__update_session_tc_params(self, *args):
572
573         def get_session_tc_param_value(param, tc_type, session_prof):
574             """ Get param value from the deep nested dict to avoid calls like:
575             session_prof['tsGroups'][0]['testCases'][0]['parameters'][key]
576             """
577             for test_group in session_prof['tsGroups']:
578                 session_tc = test_group['testCases'][0]
579                 if session_tc['type'] == tc_type:
580                     return session_tc['parameters'].get(param)
581
582         session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
583                        for _tc in _ts_group['testCases']]
584         scenario_tcs = [_tc for _tc in
585                         self.SCENARIO_CFG['options']['test_cases']]
586         for tc_options, tc in zip(scenario_tcs, session_tcs):
587             self.assertEqual(
588                 tc,
589                 self.ls_tg._update_session_tc_params(tc_options, tc))
590
591         # Verify that each test case parameter was updated
592         # Params been compared are deeply nested. Using loops to ease access.
593         for _tc in self.SCENARIO_CFG['options']['test_cases']:
594             for _key, _val in _tc.items():
595                 if _key != 'type':
596                     self.assertEqual(
597                         _val,
598                         get_session_tc_param_value(_key, _tc.get('type'),
599                                                    self.ls_tg.session_profile))
600
601     def test__update_session_library_name(self, *args):
602         _session = copy.deepcopy(SESSION_PROFILE)
603         _session['tsGroups'].pop(0)
604         self.ls_tg.vnfd_helper = mock.MagicMock()
605         self.ls_tg.vnfd_helper.mgmt_interface.__getitem__.side_effect = {
606             'user': TAS_INFO['user']}
607         self.ls_tg._update_session_library_name(_session)
608         _dmf = _session['tsGroups'][0]['testCases'][0]['parameters']['Dmf']
609         # Expect DMF library name updated in Nodal test types
610         self.assertEqual(TAS_INFO['user'], _dmf['mainflows'][0]['library'])
611
612     def test__update_session_library_name_wrong_tc_type(self, *args):
613         _session = copy.deepcopy(SESSION_PROFILE)
614         _session['tsGroups'].pop(1)
615         self.ls_tg.vnfd_helper = mock.MagicMock()
616         self.ls_tg.vnfd_helper.mgmt_interface.__getitem__.side_effect = {
617             'user': TAS_INFO['user']}
618         # Expect DMF library name not updated in Node test types
619         self.assertNotIn('Dmf',
620                          _session['tsGroups'][0]['testCases'][0]['parameters'])
621         self.ls_tg._update_session_library_name(_session)
622
623     @mock.patch.object(common_utils, 'open_relative_file')
624     @mock.patch.object(yaml_loader, 'yaml_load')
625     @mock.patch.object(tg_landslide.LandslideTrafficGen,
626                        '_update_session_test_servers')
627     @mock.patch.object(tg_landslide.LandslideTrafficGen,
628                        '_update_session_suts')
629     @mock.patch.object(tg_landslide.LandslideTrafficGen,
630                        '_update_session_tc_params')
631     def test__load_session_profile(self, mock_upd_ses_tc_params,
632                                    mock_upd_ses_suts, mock_upd_ses_ts,
633                                    mock_yaml_load, *args):
634         self.ls_tg.scenario_helper.scenario_cfg = \
635             copy.deepcopy(self.SCENARIO_CFG)
636         mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
637         self.assertIsNone(self.ls_tg._load_session_profile())
638         self.assertIsNotNone(self.ls_tg.session_profile)
639         # Number of blocks in configuration files
640         # Number of test servers, suts and tc params blocks should be equal
641         _config_files_blocks_num = len([item['test_server']
642                                         for item in self.vnfd['config']])
643         self.assertEqual(_config_files_blocks_num,
644                          mock_upd_ses_ts.call_count)
645         self.assertEqual(_config_files_blocks_num,
646                          mock_upd_ses_suts.call_count)
647         self.assertEqual(_config_files_blocks_num,
648                          mock_upd_ses_tc_params.call_count)
649
650     @mock.patch.object(common_utils, 'open_relative_file')
651     @mock.patch.object(yaml_loader, 'yaml_load')
652     def test__load_session_profile_unequal_num_of_cfg_blocks(
653             self, mock_yaml_load, *args):
654         vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
655         ls_traffic_gen = tg_landslide.LandslideTrafficGen(NAME, vnfd)
656         ls_traffic_gen.scenario_helper.scenario_cfg = self.SCENARIO_CFG
657         mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
658         # Delete test_servers item from pod file to make it not valid
659         ls_traffic_gen.vnfd_helper['config'].pop()
660         with self.assertRaises(RuntimeError):
661             ls_traffic_gen._load_session_profile()
662
663     @mock.patch.object(common_utils, 'open_relative_file')
664     @mock.patch.object(yaml_loader, 'yaml_load')
665     def test__load_session_profile_test_type_mismatch(self, mock_yaml_load,
666                                                       *args):
667         vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
668         # Swap test servers data in pod file
669         vnfd['config'] = list(reversed(vnfd['config']))
670         ls_tg = tg_landslide.LandslideTrafficGen(NAME, vnfd)
671         ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
672         mock_yaml_load.return_value = SESSION_PROFILE
673         with self.assertRaises(RuntimeError):
674             ls_tg._load_session_profile()
675
676
677 class TestLandslideResourceHelper(unittest.TestCase):
678
679     PROTO_PORT = 8080
680     EXAMPLE_URL = ''.join([TAS_INFO['proto'], '://', TAS_INFO['ip'], ':',
681                            str(PROTO_PORT), '/api/'])
682     SUCCESS_CREATED_CODE = 201
683     SUCCESS_OK_CODE = 200
684     INVALID_REST_CODE = '400'
685     NOT_MODIFIED_CODE = 500810
686     ERROR_CODE = 500800
687     SUCCESS_RECORD_ID = 11
688     EXPIRE_DATE = '2020/01/01 12:00 FLE Standard Time'
689     TEST_USER = 'test'
690     TEST_TERMINATED = 1
691     AUTH_DATA = {'user': TAS_INFO['user'], 'password': TAS_INFO['password']}
692     TEST_SESSION_NAME = 'default_bearer_capacity'
693
694     USERS_DATA = {
695         "users": [{
696             "url": ''.join([EXAMPLE_URL, 'users/', str(SUCCESS_RECORD_ID)]),
697             "id": SUCCESS_RECORD_ID,
698             "level": 1,
699             "username": TEST_USER
700         }]
701     }
702
703     CREATE_USER_DATA = {'username': TAS_INFO['user'],
704                         'expiresOn': EXPIRE_DATE,
705                         'level': 1,
706                         'contactInformation': '',
707                         'fullName': 'Test User',
708                         'password': TAS_INFO['password'],
709                         'isActive': 'true'}
710
711     SUTS_DATA = {
712         "suts": [
713             {
714                 "url": ''.join([EXAMPLE_URL, 'suts/', str(SUCCESS_RECORD_ID)]),
715                 "id": SUCCESS_RECORD_ID,
716                 "name": "10.41.32.1"
717             }]}
718
719     TEST_SERVERS_DATA = {
720         "testServers": [
721             {
722                 "url": ''.join([EXAMPLE_URL, "testServers/1"]),
723                 "id": 1,
724                 "name": TEST_SERVERS[0]['name'],
725                 "state": "READY",
726                 "version": "16.4.0.10"
727             },
728             {
729                 "url": ''.join([EXAMPLE_URL, "testServers/2"]),
730                 "id": 2,
731                 "name": TEST_SERVERS[1]['name'],
732                 "state": "READY",
733                 "version": "16.4.0.10"
734             }
735
736         ]
737     }
738
739     RUN_ID = 3
740
741     RUNNING_TESTS_DATA = {
742         "runningTests": [{
743             "url": ''.join([EXAMPLE_URL, "runningTests/{}".format(RUN_ID)]),
744             "measurementsUrl": ''.join(
745                 [EXAMPLE_URL,
746                  "runningTests/{}/measurements".format(RUN_ID)]),
747             "criteriaUrl": ''.join(
748                 [EXAMPLE_URL,
749                  "runningTests/{}/criteria".format(RUN_ID)]),
750             "noteToUser": "",
751             "id": RUN_ID,
752             "library": SUCCESS_RECORD_ID,
753             "name": "default_bearer_capacity",
754             "user": TEST_USER,
755             "criteriaStatus": "NA",
756             "testStateOrStep": "COMPLETE"
757         }]}
758
759     TEST_RESULTS_DATA = {
760         "interval": 0,
761         "elapsedTime": 138,
762         "actualTime": 1521548057296,
763         "iteration": 1,
764         "tabs": {
765             "Test Summary": {
766                 "Start Time": "Tue Mar 20 07:11:55 CDT 2018",
767                 "Actual Dedicated Bearer Session Connects": "100",
768                 "Actual Dedicated Bearer Session Disconnects": "100",
769                 "Actual Disconnect Rate(Sessions / Second)(P - I)": "164.804",
770                 "Average Session Disconnect Time(P - I)": "5.024 s",
771                 "Total Data Sent + Received Packets / Sec(P - I)": "1,452.294"
772             }}}
773
774     def setUp(self):
775         self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
776         self.mock_lsapi.start()
777
778         mock_env_helper = mock.Mock()
779         self.res_helper = tg_landslide.LandslideResourceHelper(mock_env_helper)
780         self.res_helper._url = EXAMPLE_URL
781
782         self.addCleanup(self._cleanup)
783
784     def _cleanup(self):
785         self.mock_lsapi.stop()
786         self.res_helper._url = None
787
788     def test___init__(self, *args):
789         self.assertIsInstance(self.res_helper,
790                               tg_landslide.LandslideResourceHelper)
791         self.assertEqual({}, self.res_helper._result)
792         self.assertIsNone(self.res_helper.run_id)
793
794     @mock.patch.object(tg_landslide.LandslideResourceHelper,
795                        'stop_running_tests')
796     @mock.patch.object(tg_landslide.LandslideResourceHelper,
797                        'get_running_tests')
798     def test_abort_running_tests_no_running_tests(self, mock_get_tests,
799                                                   mock_stop_tests, *args):
800         tests_data = [{'id': self.SUCCESS_RECORD_ID,
801                        'testStateOrStep': 'COMPLETE'}]
802         mock_get_tests.return_value = tests_data
803         self.assertIsNone(self.res_helper.abort_running_tests())
804         mock_stop_tests.assert_not_called()
805
806     @mock.patch.object(time, 'sleep')
807     @mock.patch.object(tg_landslide.LandslideResourceHelper,
808                        'stop_running_tests')
809     @mock.patch.object(tg_landslide.LandslideResourceHelper,
810                        'get_running_tests')
811     def test_abort_running_tests(self, mock_get_tests, mock_stop_tests, *args):
812         test_states_seq = iter(['RUNNING', 'COMPLETE'])
813
814         def configure_mock(*args):
815             return [{'id': self.SUCCESS_RECORD_ID,
816                      'testStateOrStep': next(test_states_seq)}]
817
818         mock_get_tests.side_effect = configure_mock
819         self.assertIsNone(self.res_helper.abort_running_tests())
820         mock_stop_tests.assert_called_once_with(
821             running_test_id=self.SUCCESS_RECORD_ID,
822             force=True)
823         self.assertEqual(2, mock_get_tests.call_count)
824
825     @mock.patch.object(tg_landslide.LandslideResourceHelper,
826                        'stop_running_tests')
827     @mock.patch.object(tg_landslide.LandslideResourceHelper,
828                        'get_running_tests')
829     def test_abort_running_tests_error(self, mock_get_tests, mock_stop_tests,
830                                        *args):
831         tests_data = {'id': self.SUCCESS_RECORD_ID,
832                       'testStateOrStep': 'RUNNING'}
833         mock_get_tests.return_value = [tests_data]
834         with self.assertRaises(RuntimeError):
835             self.res_helper.abort_running_tests(timeout=1, delay=1)
836         mock_stop_tests.assert_called_with(
837             running_test_id=self.SUCCESS_RECORD_ID,
838             force=True)
839
840     def test__build_url(self, *args):
841         resource = 'users'
842         action = {'action': 'userCreate'}
843         expected_url = ''.join([EXAMPLE_URL, 'users?action=userCreate'])
844         self.assertEqual(expected_url,
845                          self.res_helper._build_url(resource, action))
846
847     def test__build_url_error(self, *args):
848         resource = ''
849         action = {'action': 'userCreate'}
850
851         with self.assertRaises(ValueError):
852             self.res_helper._build_url(resource, action)
853
854     def test_get_response_params(self, *args):
855         method = 'get'
856         resource = 'users'
857         mock_session = mock.Mock(spec=requests.Session)
858         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
859                          'json.return_value': self.USERS_DATA}
860         mock_session.get.return_value.configure_mock(**get_resp_data)
861         self.res_helper.session = mock_session
862         resp = self.res_helper.get_response_params(method, resource)
863         self.assertTrue(resp)
864
865     @mock.patch.object(tg_landslide.LandslideResourceHelper, '_get_users')
866     @mock.patch.object(time, 'time')
867     def test__create_user(self, mock_time, mock_get_users, *args):
868         mock_time.strftime.return_value = self.EXPIRE_DATE
869         post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
870                           'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
871         mock_session = mock.Mock(spec=requests.Session)
872         mock_session.post.return_value.configure_mock(**post_resp_data)
873         self.res_helper.session = mock_session
874         self.assertEqual(self.SUCCESS_RECORD_ID,
875                          self.res_helper._create_user(self.AUTH_DATA))
876         mock_get_users.assert_not_called()
877
878     @mock.patch.object(tg_landslide.LandslideResourceHelper, '_modify_user')
879     @mock.patch.object(time, 'time')
880     def test__create_user_username_exists(self, mock_time, mock_modify_user,
881                                           *args):
882         mock_time.strftime.return_value = self.EXPIRE_DATE
883         mock_modify_user.return_value = {'id': self.SUCCESS_RECORD_ID,
884                                          'result': 'No changes requested'}
885         post_resp_data = {
886             'status_code': self.ERROR_CODE,
887             'json.return_value': {'id': self.SUCCESS_OK_CODE,
888                                   'apiCode': self.NOT_MODIFIED_CODE}}
889         mock_session = mock.Mock(spec=requests.Session)
890         mock_session.post.return_value.configure_mock(**post_resp_data)
891         self.res_helper.session = mock_session
892         res = self.res_helper._create_user(self.AUTH_DATA)
893         mock_modify_user.assert_called_once_with(TAS_INFO['user'],
894                                                  {'isActive': 'true'})
895         self.assertEqual(self.SUCCESS_RECORD_ID, res)
896
897     @mock.patch.object(time, 'time')
898     def test__create_user_error(self, mock_time, *args):
899         mock_time.strftime.return_value = self.EXPIRE_DATE
900         mock_session = mock.Mock(spec=requests.Session)
901         post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
902                           'json.return_value': {'apiCode': self.ERROR_CODE}}
903         mock_session.post.return_value.configure_mock(**post_resp_data)
904         self.res_helper.session = mock_session
905         with self.assertRaises(exceptions.RestApiError):
906             self.res_helper._create_user(self.AUTH_DATA)
907
908     def test__modify_user(self, *args):
909         post_data = {'username': 'test_user'}
910         mock_session = mock.Mock(spec=requests.Session)
911         post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
912                           'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
913         mock_session.post.return_value.configure_mock(**post_resp_data)
914         self.res_helper.session = mock_session
915         res = self.res_helper._modify_user(username=self.TEST_USER,
916                                            fields=post_data)
917         self.assertEqual(self.SUCCESS_RECORD_ID, res['id'])
918
919     def test__modify_user_rest_resp_fail(self, *args):
920         post_data = {'non-existing-key': ''}
921         mock_session = mock.Mock(spec=requests.Session)
922         mock_session.post.ok = False
923         self.res_helper.session = mock_session
924         self.assertRaises(exceptions.RestApiError,
925                           self.res_helper._modify_user,
926                           username=self.TEST_USER, fields=post_data)
927         mock_session.post.assert_called_once()
928
929     def test__delete_user(self, *args):
930         mock_session = mock.Mock(spec=requests.Session)
931         self.res_helper.session = mock_session
932         self.assertIsNone(self.res_helper._delete_user(
933             username=self.TEST_USER))
934
935     def test__get_users(self, *args):
936         mock_session = mock.Mock(spec=requests.Session)
937         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
938                          'json.return_value': self.USERS_DATA}
939         mock_session.get.return_value.configure_mock(**get_resp_data)
940         self.res_helper.session = mock_session
941         self.assertEqual(self.USERS_DATA['users'],
942                          self.res_helper._get_users())
943
944     def test_exec_rest_request(self, *args):
945         resource = 'testServers'
946         action = {'action': 'modify'}
947         expected_url = ''.join([EXAMPLE_URL, 'testServers?action=modify'])
948         post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
949                           'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
950         mock_session = mock.Mock(spec=requests.Session)
951         mock_session.post.return_value.configure_mock(**post_resp_data)
952         self.res_helper.session = mock_session
953         self.res_helper.exec_rest_request('post', resource, action)
954         self.res_helper.session.post.assert_called_once_with(expected_url,
955                                                              json={})
956
957     def test_exec_rest_request_unsupported_method_error(self, *args):
958         resource = 'testServers'
959         action = {'action': 'modify'}
960         with self.assertRaises(ValueError):
961             self.res_helper.exec_rest_request('patch', resource, action)
962
963     def test_exec_rest_request_missed_action_arg(self, *args):
964         resource = 'testServers'
965         with self.assertRaises(ValueError):
966             self.res_helper.exec_rest_request('post', resource)
967
968     def test_exec_rest_request_raise_exc(self):
969         resource = 'users'
970         action = {'action': 'modify'}
971         post_resp_data = {'status_code': self.ERROR_CODE,
972                           'json.return_value': {
973                               'status_code': self.ERROR_CODE}}
974         mock_session = mock.Mock(spec=requests.Session)
975         mock_session.post.return_value.configure_mock(**post_resp_data)
976         self.assertRaises(exceptions.RestApiError,
977                           self.res_helper.exec_rest_request,
978                           'post', resource, action, raise_exc=True)
979
980     @mock.patch.object(time, 'time')
981     def test_connect(self, mock_time, *args):
982         vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
983         mock_time.strftime.return_value = self.EXPIRE_DATE
984         self.res_helper.vnfd_helper = vnfd
985
986         self.res_helper._tcl = mock.Mock()
987         post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
988                           'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
989         mock_session = mock.Mock(spec=requests.Session, headers={})
990         mock_session.post.return_value.configure_mock(**post_resp_data)
991         self.res_helper.session = mock_session
992         self.assertIsInstance(self.res_helper.connect(), requests.Session)
993         self.res_helper._tcl.connect.assert_called_once_with(
994             TAS_INFO['ip'],
995             TAS_INFO['user'],
996             TAS_INFO['password'])
997
998     def test_disconnect(self, *args):
999         self.res_helper._tcl = mock.Mock()
1000         self.assertIsNone(self.res_helper.disconnect())
1001         self.assertIsNone(self.res_helper.session)
1002         self.res_helper._tcl.disconnect.assert_called_once()
1003
1004     def test_terminate(self, *args):
1005         self.assertIsNone(self.res_helper.terminate())
1006         self.assertEqual(self.TEST_TERMINATED,
1007                          self.res_helper._terminated.value)
1008
1009     def test_create_dmf(self, *args):
1010         self.res_helper._tcl = mock.Mock()
1011         self.res_helper.vnfd_helper = mock.Mock(spec=vnf_base.VnfdHelper)
1012         self.res_helper.vnfd_helper.mgmt_interface = {'user': TAS_INFO['user']}
1013         self.assertIsNone(self.res_helper.create_dmf(DMF_CFG))
1014         self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
1015
1016     def test_create_dmf_as_list(self, *args):
1017         self.res_helper._tcl = mock.Mock()
1018         self.res_helper.vnfd_helper = mock.Mock(spec=vnf_base.VnfdHelper)
1019         self.res_helper.vnfd_helper.mgmt_interface = {'user': TAS_INFO['user']}
1020         self.assertIsNone(self.res_helper.create_dmf([DMF_CFG]))
1021         self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
1022
1023     def test_delete_dmf(self, *args):
1024         self.res_helper._tcl = mock.Mock()
1025         self.assertIsNone(self.res_helper.delete_dmf(DMF_CFG))
1026         self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
1027
1028     def test_delete_dmf_as_list(self, *args):
1029         self.res_helper._tcl = mock.Mock()
1030         self.assertIsNone(self.res_helper.delete_dmf([DMF_CFG]))
1031         self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
1032
1033     @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
1034     def test_create_suts(self, mock_configure_sut, *args):
1035         mock_session = mock.Mock(spec=requests.Session)
1036         post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE}
1037         mock_session.post.return_value.configure_mock(**post_resp_data)
1038         self.res_helper.session = mock_session
1039         self.assertIsNone(self.res_helper.create_suts(TS1_SUTS))
1040         mock_configure_sut.assert_not_called()
1041
1042     @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
1043     def test_create_suts_sut_exists(self, mock_configure_sut, *args):
1044         sut_name = 'test_sut'
1045         suts = [
1046             {'name': sut_name,
1047              'role': 'SgwControlAddr',
1048              'managementIp': '12.0.1.1',
1049              'ip': '10.42.32.100'
1050              }
1051         ]
1052         mock_session = mock.Mock(spec=requests.Session)
1053         post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
1054         mock_session.post.return_value.configure_mock(**post_resp_data)
1055         self.res_helper.session = mock_session
1056         self.assertIsNone(self.res_helper.create_suts(suts))
1057         mock_configure_sut.assert_called_once_with(
1058             sut_name=sut_name,
1059             json_data={k: v for k, v in suts[0].items()
1060                        if k not in {'phy', 'nextHop', 'role', 'name'}})
1061
1062     def test_get_suts(self, *args):
1063         mock_session = mock.Mock(spec=requests.Session)
1064         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1065                          'json.return_value': self.SUTS_DATA}
1066         mock_session.get.return_value.configure_mock(**get_resp_data)
1067         self.res_helper.session = mock_session
1068         self.assertIsInstance(self.res_helper.get_suts(), list)
1069
1070     def test_get_suts_single_id(self, *args):
1071         mock_session = mock.Mock(spec=requests.Session)
1072         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1073                          'json.return_value': self.SUTS_DATA['suts'][0]}
1074         mock_session.get.return_value.configure_mock(**get_resp_data)
1075         self.res_helper.session = mock_session
1076         self.assertIsInstance(self.res_helper.get_suts(suts_id=2), dict)
1077
1078     def test_configure_sut(self, *args):
1079         post_data = {'managementIp': '2.2.2.2'}
1080         mock_session = mock.Mock(spec=requests.Session)
1081         post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1082                           'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
1083         mock_session.post.return_value.configure_mock(**post_resp_data)
1084         self.res_helper.session = mock_session
1085         self.assertIsNone(self.res_helper.configure_sut('test_name',
1086                                                         post_data))
1087         mock_session.post.assert_called_once()
1088
1089     def test_configure_sut_error(self, *args):
1090         post_data = {'managementIp': '2.2.2.2'}
1091         mock_session = mock.Mock(spec=requests.Session)
1092         post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
1093         mock_session.post.return_value.configure_mock(**post_resp_data)
1094         self.res_helper.session = mock_session
1095         with self.assertRaises(exceptions.RestApiError):
1096             self.res_helper.configure_sut('test_name', post_data)
1097
1098     def test_delete_suts(self, *args):
1099         mock_session = mock.Mock(spec=requests.Session)
1100         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1101                          'json.return_value': self.SUTS_DATA}
1102         delete_resp_data = {'status_code': self.SUCCESS_OK_CODE}
1103         mock_session.get.return_value.configure_mock(**get_resp_data)
1104         mock_session.delete.return_value.configure_mock(**delete_resp_data)
1105         self.res_helper.session = mock_session
1106         self.assertIsNone(self.res_helper.delete_suts())
1107         mock_session.delete.assert_called_once()
1108
1109     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1110                        'get_test_servers')
1111     def test__check_test_servers_state(self, mock_get_test_servers, *args):
1112         mock_get_test_servers.return_value = \
1113             self.TEST_SERVERS_DATA['testServers']
1114         self.res_helper._check_test_servers_state()
1115         mock_get_test_servers.assert_called_once()
1116
1117     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1118                        'get_test_servers')
1119     def test__check_test_servers_state_server_not_ready(
1120             self, mock_get_test_servers, *args):
1121         test_servers_not_ready = [
1122             {
1123                 "url": ''.join([EXAMPLE_URL, "testServers/1"]),
1124                 "id": 1,
1125                 "name": "TestServer_1",
1126                 "state": "NOT_READY",
1127                 "version": "16.4.0.10"
1128             }
1129         ]
1130
1131         mock_get_test_servers.return_value = test_servers_not_ready
1132         with self.assertRaises(RuntimeError):
1133             self.res_helper._check_test_servers_state(timeout=1, delay=0)
1134
1135     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1136                        '_check_test_servers_state')
1137     def test_create_test_servers(self, mock_check_ts_state, *args):
1138         test_servers_ids = [
1139             ts['id'] for ts in self.TEST_SERVERS_DATA['testServers']]
1140
1141         self.res_helper.license_data['lic_id'] = TAS_INFO['license']
1142         self.res_helper._tcl.create_test_server = mock.Mock()
1143         self.res_helper._tcl.create_test_server.side_effect = test_servers_ids
1144         self.assertIsNone(self.res_helper.create_test_servers(TEST_SERVERS))
1145         mock_check_ts_state.assert_called_once_with(test_servers_ids)
1146
1147     @mock.patch.object(tg_landslide.LandslideTclClient,
1148                        'resolve_test_server_name')
1149     @mock.patch.object(tg_landslide.LsTclHandler, 'execute')
1150     def test_create_test_servers_error(self, mock_execute,
1151                                        mock_resolve_ts_name, *args):
1152         self.res_helper.license_data['lic_id'] = TAS_INFO['license']
1153         # Return message for case test server wasn't created
1154         mock_execute.return_value = 'TS not found'
1155         # Return message for case test server name wasn't resolved
1156         mock_resolve_ts_name.return_value = 'TS not found'
1157         with self.assertRaises(RuntimeError):
1158             self.res_helper.create_test_servers(TEST_SERVERS)
1159
1160     def test_get_test_servers(self, *args):
1161         mock_session = mock.Mock(spec=requests.Session)
1162         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1163                          'json.return_value': self.TEST_SERVERS_DATA}
1164         mock_session.get.return_value.configure_mock(**get_resp_data)
1165         self.res_helper.session = mock_session
1166         res = self.res_helper.get_test_servers()
1167         self.assertEqual(self.TEST_SERVERS_DATA['testServers'], res)
1168
1169     def test_get_test_servers_by_id(self, *args):
1170         mock_session = mock.Mock(spec=requests.Session)
1171
1172         _ts = self.TEST_SERVERS_DATA['testServers'][0]
1173         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1174                          'json.return_value': _ts}
1175         mock_session.get.return_value.configure_mock(**get_resp_data)
1176         self.res_helper.session = mock_session
1177         res = self.res_helper.get_test_servers(test_server_ids=[_ts['id']])
1178         self.assertEqual([_ts], res)
1179
1180     def test_configure_test_servers(self, *args):
1181         mock_session = mock.Mock(spec=requests.Session)
1182         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1183                          'json.return_value': self.TEST_SERVERS_DATA}
1184         mock_session.get.return_value.configure_mock(**get_resp_data)
1185         self.res_helper.session = mock_session
1186         res = self.res_helper.configure_test_servers(
1187             action={'action': 'recycle'})
1188         self.assertEqual(
1189             [x['id'] for x in self.TEST_SERVERS_DATA['testServers']],
1190             res)
1191         self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
1192                          mock_session.post.call_count)
1193
1194     def test_delete_test_servers(self, *args):
1195         mock_session = mock.Mock(spec=requests.Session)
1196         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1197                          'json.return_value': self.TEST_SERVERS_DATA}
1198         mock_session.get.return_value.configure_mock(**get_resp_data)
1199         self.res_helper.session = mock_session
1200         self.assertIsNone(self.res_helper.delete_test_servers())
1201         self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
1202                          mock_session.delete.call_count)
1203
1204     def test_create_test_session_res_helper(self, *args):
1205         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1206         self.res_helper._tcl = mock.Mock()
1207         self.res_helper.scenario_helper.all_options = {'traffic_duration': 71}
1208         _session = {'name': 'test', 'duration': 60}
1209         self.assertIsNone(self.res_helper.create_test_session(_session))
1210         self.res_helper._tcl.create_test_session.assert_called_once_with(
1211             {'name': _session['name'],
1212              'duration': 71,
1213              'library': self.SUCCESS_RECORD_ID})
1214
1215     def test_create_test_session_res_helper_no_traffic_duration(self, *args):
1216         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1217         self.res_helper._tcl = mock.Mock()
1218         self.res_helper.scenario_helper.all_options = {}
1219         _session = {'name': 'test', 'duration': 60}
1220         self.assertIsNone(self.res_helper.create_test_session(_session))
1221         self.res_helper._tcl.create_test_session.assert_called_once_with(
1222             {'name': _session['name'],
1223              'duration': 60,
1224              'library': self.SUCCESS_RECORD_ID})
1225
1226     @mock.patch.object(tg_landslide.LandslideTclClient,
1227                        'resolve_test_server_name',
1228                        return_value='Not Found')
1229     def test_create_test_session_ts_name_not_found(self, *args):
1230         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1231         test_session = {
1232             'duration': 60,
1233             'description': 'UE default bearer creation test case',
1234             'name': 'default_bearer_capacity',
1235             'tsGroups': [{'testCases': [{'type': 'SGW_Node',
1236                                          'name': ''}],
1237                           'tsId': 'TestServer_3'}]
1238         }
1239         with self.assertRaises(RuntimeError):
1240             self.res_helper.create_test_session(test_session)
1241
1242     def test_get_test_session(self, *args):
1243         test_session = {"name": self.TEST_SESSION_NAME}
1244         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1245         mock_session = mock.Mock(spec=requests.Session)
1246         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1247                          'json.return_value': test_session}
1248         mock_session.get.return_value.configure_mock(**get_resp_data)
1249         self.res_helper.session = mock_session
1250         res = self.res_helper.get_test_session(self.TEST_SESSION_NAME)
1251         self.assertEqual(test_session, res)
1252
1253     def test_configure_test_session(self, *args):
1254         test_session = {'name': self.TEST_SESSION_NAME}
1255         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1256         self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
1257             self.res_helper.test_session_uri)
1258         mock_session = mock.Mock(spec=requests.Session)
1259         self.res_helper.session = mock_session
1260         res = self.res_helper.configure_test_session(self.TEST_SESSION_NAME,
1261                                                      test_session)
1262         self.assertIsNotNone(res)
1263         mock_session.post.assert_called_once()
1264
1265     def test_delete_test_session(self, *args):
1266         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1267         self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
1268             self.res_helper.test_session_uri)
1269         mock_session = mock.Mock(spec=requests.Session)
1270         self.res_helper.session = mock_session
1271         res = self.res_helper.delete_test_session(self.TEST_SESSION_NAME)
1272         self.assertIsNotNone(res)
1273         mock_session.delete.assert_called_once()
1274
1275     def test_create_running_tests(self, *args):
1276         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1277         test_session = {'id': self.SUCCESS_RECORD_ID}
1278         mock_session = mock.Mock(spec=requests.Session)
1279         post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
1280                           'json.return_value': test_session}
1281         mock_session.post.return_value.configure_mock(**post_resp_data)
1282         self.res_helper.session = mock_session
1283         self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
1284         self.assertEqual(self.SUCCESS_RECORD_ID, self.res_helper.run_id)
1285
1286     def test_create_running_tests_error(self, *args):
1287         self.res_helper._user_id = self.SUCCESS_RECORD_ID
1288         mock_session = mock.Mock(spec=requests.Session)
1289         post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
1290         mock_session.post.return_value.configure_mock(**post_resp_data)
1291         self.res_helper.session = mock_session
1292         with self.assertRaises(exceptions.RestApiError):
1293             self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
1294
1295     def test_get_running_tests(self, *args):
1296         mock_session = mock.Mock(spec=requests.Session)
1297         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1298                          'json.return_value': self.RUNNING_TESTS_DATA}
1299         mock_session.get.return_value.configure_mock(**get_resp_data)
1300         self.res_helper.session = mock_session
1301         res = self.res_helper.get_running_tests()
1302         self.assertEqual(self.RUNNING_TESTS_DATA['runningTests'], res)
1303
1304     def test_delete_running_tests(self, *args):
1305         mock_session = mock.Mock(spec=requests.Session)
1306         delete_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1307                             'json.return_value': self.RUNNING_TESTS_DATA}
1308         mock_session.delete.return_value.configure_mock(**delete_resp_data)
1309         self.res_helper.session = mock_session
1310         self.assertIsNone(self.res_helper.delete_running_tests())
1311
1312     def test__running_tests_action(self, *args):
1313         action = 'abort'
1314         mock_session = mock.Mock(spec=requests.Session)
1315         self.res_helper.session = mock_session
1316         res = self.res_helper._running_tests_action(self.SUCCESS_RECORD_ID,
1317                                                     action)
1318         self.assertIsNone(res)
1319
1320     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1321                        '_running_tests_action')
1322     def test_stop_running_tests(self, mock_tests_action, *args):
1323         res = self.res_helper.stop_running_tests(self.SUCCESS_RECORD_ID)
1324         self.assertIsNone(res)
1325         mock_tests_action.assert_called_once()
1326
1327     def test_check_running_test_state(self, *args):
1328         mock_session = mock.Mock(spec=requests.Session)
1329         get_resp_data = {
1330             'status_code': self.SUCCESS_OK_CODE,
1331             'json.return_value': self.RUNNING_TESTS_DATA["runningTests"][0]}
1332         mock_session.get.return_value.configure_mock(**get_resp_data)
1333         self.res_helper.session = mock_session
1334         res = self.res_helper.check_running_test_state(self.SUCCESS_RECORD_ID)
1335         self.assertEqual(
1336             self.RUNNING_TESTS_DATA["runningTests"][0]['testStateOrStep'],
1337             res)
1338
1339     def test_get_running_tests_results(self, *args):
1340         mock_session = mock.Mock(spec=requests.Session)
1341         get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
1342                          'json.return_value': self.TEST_RESULTS_DATA}
1343         mock_session.get.return_value.configure_mock(**get_resp_data)
1344         self.res_helper.session = mock_session
1345         res = self.res_helper.get_running_tests_results(
1346             self.SUCCESS_RECORD_ID)
1347         self.assertEqual(self.TEST_RESULTS_DATA, res)
1348
1349     def test__write_results(self, *args):
1350         res = self.res_helper._write_results(self.TEST_RESULTS_DATA)
1351         exp_res = {
1352             "Test Summary::Actual Dedicated Bearer Session Connects": 100.0,
1353             "Test Summary::Actual Dedicated Bearer Session Disconnects": 100.0,
1354             "Test Summary::Actual Disconnect Rate(Sessions / Second)(P - I)": 164.804,
1355             "Test Summary::Average Session Disconnect Time(P - I)": 5.024,
1356             "Test Summary::Total Data Sent + Received Packets / Sec(P - I)": 1452.294
1357         }
1358         self.assertEqual(exp_res, res)
1359
1360     def test__write_results_no_tabs(self, *args):
1361         _res_data = copy.deepcopy(self.TEST_RESULTS_DATA)
1362         del _res_data['tabs']
1363         # Return None if tabs not found in test results dict
1364         self.assertIsNone(self.res_helper._write_results(_res_data))
1365
1366     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1367                        'check_running_test_state')
1368     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1369                        'get_running_tests_results')
1370     def test_collect_kpi_test_running(self, mock_tests_results,
1371                                       mock_tests_state, *args):
1372         self.res_helper.run_id = self.SUCCESS_RECORD_ID
1373         mock_tests_state.return_value = 'RUNNING'
1374         mock_tests_results.return_value = self.TEST_RESULTS_DATA
1375         res = self.res_helper.collect_kpi()
1376         self.assertNotIn('done', res)
1377         mock_tests_state.assert_called_once_with(self.res_helper.run_id)
1378         mock_tests_results.assert_called_once_with(self.res_helper.run_id)
1379
1380     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1381                        'check_running_test_state')
1382     @mock.patch.object(tg_landslide.LandslideResourceHelper,
1383                        'get_running_tests_results')
1384     def test_collect_kpi_test_completed(self, mock_tests_results,
1385                                         mock_tests_state, *args):
1386         self.res_helper.run_id = self.SUCCESS_RECORD_ID
1387         mock_tests_state.return_value = 'COMPLETE'
1388         res = self.res_helper.collect_kpi()
1389         self.assertIsNotNone(res)
1390         mock_tests_state.assert_called_once_with(self.res_helper.run_id)
1391         mock_tests_results.assert_not_called()
1392         self.assertDictContainsSubset({'done': True}, res)
1393
1394
1395 class TestLandslideTclClient(unittest.TestCase):
1396     def setUp(self):
1397         self.mock_tcl_handler = mock.Mock(spec=tg_landslide.LsTclHandler)
1398         self.ls_res_helper = mock.Mock(
1399             spec=tg_landslide.LandslideResourceHelper)
1400         self.ls_tcl_client = tg_landslide.LandslideTclClient(
1401             self.mock_tcl_handler,
1402             self.ls_res_helper)
1403
1404     def test___init__(self, *args):
1405         self.ls_tcl_client = tg_landslide.LandslideTclClient(
1406             self.mock_tcl_handler,
1407             self.ls_res_helper)
1408         self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
1409         self.assertIsNone(self.ls_tcl_client._user)
1410         self.assertIsNone(self.ls_tcl_client._library_id)
1411         self.assertIsNone(self.ls_tcl_client._basic_library_id)
1412         self.assertEqual(set(), self.ls_tcl_client.ts_ids)
1413         self.assertIsInstance(self.ls_tcl_client._tc_types, set)
1414         self.assertIsNotNone(self.ls_tcl_client._tc_types)
1415
1416     def test_connect_login_success(self, *args):
1417         lib_id = '123'
1418         exec_responses = ['java0x2', lib_id, lib_id]
1419         auth = ('user', 'password')
1420         self.mock_tcl_handler.execute.side_effect = exec_responses
1421         self.ls_tcl_client.connect(TAS_INFO['ip'], *auth)
1422         self.assertEqual(lib_id, self.ls_tcl_client._library_id)
1423         self.assertEqual(lib_id, self.ls_tcl_client._basic_library_id)
1424         self.assertEqual(TAS_INFO['ip'], self.ls_tcl_client.tcl_server_ip)
1425         self.assertEqual(auth[0], self.ls_tcl_client._user)
1426         self.assertEqual(len(exec_responses),
1427                          self.mock_tcl_handler.execute.call_count)
1428         self.mock_tcl_handler.execute.assert_has_calls([
1429             mock.call("ls::login 1.1.1.1 user password"),
1430             mock.call("ls::get [ls::query LibraryInfo -userLibraryName user] -Id"),
1431         ])
1432
1433     def test_connect_login_failed(self, *args):
1434         exec_responses = ['Login failed']
1435         auth = ('user', 'password')
1436         self.mock_tcl_handler.execute.side_effect = exec_responses
1437         self.assertRaises(exceptions.LandslideTclException,
1438                           self.ls_tcl_client.connect,
1439                           TAS_INFO['ip'],
1440                           *auth)
1441         self.assertIsNone(self.ls_tcl_client._library_id)
1442         self.assertIsNone(self.ls_tcl_client._basic_library_id)
1443         self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
1444         self.assertIsNone(self.ls_tcl_client._user)
1445         self.assertEqual(len(exec_responses),
1446                          self.mock_tcl_handler.execute.call_count)
1447         self.mock_tcl_handler.execute.assert_called_with(
1448             "ls::login 1.1.1.1 user password")
1449
1450     def test_disconnect(self, *args):
1451         self.ls_tcl_client.disconnect()
1452         self.mock_tcl_handler.execute.assert_called_once_with("ls::logout")
1453         self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
1454         self.assertIsNone(self.ls_tcl_client._user)
1455         self.assertIsNone(self.ls_tcl_client._library_id)
1456         self.assertIsNone(self.ls_tcl_client._basic_library_id)
1457
1458     def test_create_test_server(self, *args):
1459         return_value = '2'
1460         self.ls_tcl_client._ts_context.vnfd_helper = \
1461             VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1462         self.ls_tcl_client._ts_context.license_data = {'lic_id': return_value}
1463         self.mock_tcl_handler.execute.return_value = return_value
1464         self.ls_tcl_client._set_thread_model = mock.Mock()
1465         res = self.ls_tcl_client.create_test_server(TEST_SERVERS[1])
1466         self.assertEqual(3, self.mock_tcl_handler.execute.call_count)
1467         self.mock_tcl_handler.execute.assert_has_calls([
1468             mock.call('ls::query TsId TestServer_2'),
1469             mock.call('set ts [ls::retrieve TsInfo -Name "TestServer_2"]'),
1470             mock.call('ls::get $ts -RequestedLicense'),
1471         ])
1472         self.ls_tcl_client._set_thread_model.assert_called_once_with(
1473             TEST_SERVERS[1]['name'],
1474             TEST_SERVERS[1]['thread_model'])
1475         self.assertEqual(int(return_value), res)
1476
1477     def test_create_test_server_fail_limit_reach(self, *args):
1478         self.mock_tcl_handler.execute.side_effect = ['TS not found',
1479                                                      'Add failed']
1480         self.assertRaises(RuntimeError,
1481                           self.ls_tcl_client.create_test_server,
1482                           TEST_SERVERS[0])
1483         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1484         self.mock_tcl_handler.execute.assert_has_calls([
1485             mock.call('ls::query TsId TestServer_1'),
1486             mock.call('ls::perform AddTs -Name "TestServer_1" '
1487                       '-Ip "192.168.122.101"'),
1488         ])
1489
1490     def test__add_test_server(self):
1491         ts_id = '2'
1492         self.mock_tcl_handler.execute.side_effect = ['TS not found', ts_id]
1493         self.assertEqual(ts_id,
1494                          self.ls_tcl_client._add_test_server('name', 'ip'))
1495         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1496         self.mock_tcl_handler.execute.assert_has_calls([
1497             mock.call('ls::query TsId name'),
1498             mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
1499         ])
1500
1501     def test__add_test_server_failed(self):
1502         self.mock_tcl_handler.execute.side_effect = ['TS not found',
1503                                                      'Add failed']
1504         self.assertRaises(RuntimeError, self.ls_tcl_client._add_test_server,
1505                           'name', 'ip')
1506         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1507         self.mock_tcl_handler.execute.assert_has_calls([
1508             mock.call('ls::query TsId name'),
1509             mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
1510         ])
1511
1512     def test__update_license(self):
1513         curr_lic_id = '111'
1514         new_lic_id = '222'
1515         exec_resp = ['java0x4',
1516                      curr_lic_id,
1517                      TCL_SUCCESS_RESPONSE,
1518                      TCL_SUCCESS_RESPONSE]
1519         self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
1520         self.mock_tcl_handler.execute.side_effect = exec_resp
1521         self.ls_tcl_client._update_license('name')
1522         self.assertEqual(len(exec_resp),
1523                          self.mock_tcl_handler.execute.call_count)
1524
1525         self.mock_tcl_handler.execute.assert_has_calls([
1526             mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
1527             mock.call('ls::get $ts -RequestedLicense'),
1528             mock.call('ls::config $ts -RequestedLicense 222'),
1529             mock.call('ls::perform ModifyTs $ts'),
1530         ])
1531
1532     def test__update_license_same_as_current(self):
1533         curr_lic_id = '111'
1534         new_lic_id = '111'
1535         exec_resp = ['java0x4', curr_lic_id]
1536         self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
1537         self.mock_tcl_handler.execute.side_effect = exec_resp
1538         self.ls_tcl_client._update_license('name')
1539         self.assertEqual(len(exec_resp),
1540                          self.mock_tcl_handler.execute.call_count)
1541         self.mock_tcl_handler.execute.assert_has_calls([
1542             mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
1543             mock.call('ls::get $ts -RequestedLicense'),
1544         ])
1545
1546     def test__set_thread_model_update_needed(self):
1547         self.ls_tcl_client._ts_context.vnfd_helper = {
1548             'mgmt-interface': {
1549                 'cfguser_password': 'cfguser_password'
1550             }
1551         }
1552         exec_resp = ['java0x4', 'V0', '', '']
1553         self.mock_tcl_handler.execute.side_effect = exec_resp
1554         self.ls_tcl_client._set_thread_model('name', 'Fireball')
1555         self.assertEqual(len(exec_resp),
1556                          self.mock_tcl_handler.execute.call_count)
1557         self.mock_tcl_handler.execute.assert_has_calls([
1558             mock.call('set tsc [ls::perform RetrieveTsConfiguration '
1559                       '-name "name" cfguser_password]'),
1560             mock.call('ls::get $tsc -ThreadModel'),
1561             mock.call('ls::config $tsc -ThreadModel "V1_FB3"'),
1562             mock.call('ls::perform ApplyTsConfiguration $tsc cfguser_password'),
1563         ])
1564
1565     def test__set_thread_model_no_update_needed(self):
1566         self.ls_tcl_client._ts_context.vnfd_helper = {
1567             'mgmt-interface': {
1568                 'cfguser_password': 'cfguser_password'
1569             }
1570         }
1571         exec_resp = ['java0x4', 'V0']
1572         self.mock_tcl_handler.execute.side_effect = exec_resp
1573         self.ls_tcl_client._set_thread_model('name', 'Legacy')
1574         self.assertEqual(len(exec_resp),
1575                          self.mock_tcl_handler.execute.call_count)
1576         self.mock_tcl_handler.execute.assert_has_calls([
1577             mock.call('set tsc [ls::perform RetrieveTsConfiguration '
1578                       '-name "name" cfguser_password]'),
1579             mock.call('ls::get $tsc -ThreadModel'),
1580         ])
1581
1582     @mock.patch.object(tg_landslide.LandslideTclClient,
1583                        'resolve_test_server_name', side_effect=['4', '2'])
1584     def test_create_test_session(self, *args):
1585         _session_profile = copy.deepcopy(SESSION_PROFILE)
1586         _session_profile['reservations'] = RESERVATIONS
1587         self.ls_tcl_client._save_test_session = mock.Mock()
1588         self.ls_tcl_client._configure_ts_group = mock.Mock()
1589         self.ls_tcl_client._library_id = 42
1590         self.ls_tcl_client.create_test_session(_session_profile)
1591         self.assertEqual(17, self.mock_tcl_handler.execute.call_count)
1592         self.mock_tcl_handler.execute.assert_has_calls([
1593             mock.call('set test_ [ls::create TestSession]'),
1594             mock.call('ls::config $test_ -Library 42 '
1595                       '-Name "default_bearer_capacity"'),
1596             mock.call('ls::config $test_ -Description ' \
1597                       '"UE default bearer creation test case"'),
1598             mock.call('ls::config $test_ -Keywords ""'),
1599             mock.call('ls::config $test_ -Duration "60"'),
1600             mock.call('ls::config $test_ -Iterations "1"'),
1601             # _configure_reservation
1602             mock.call('set reservation_ [ls::create Reservation -under $test_]'),
1603             mock.call('ls::config $reservation_ -TsIndex 0 '
1604                       '-TsId 4 -TsName "TestServer_1"'),
1605             mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
1606             mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.100" '
1607                       '-Mask "/24" -NumIps 20'),
1608             # _configure_reservation
1609             mock.call('set reservation_ [ls::create Reservation -under $test_]'),
1610             mock.call('ls::config $reservation_ -TsIndex 1 '
1611                       '-TsId 2 -TsName "TestServer_2"'),
1612             mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
1613             mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.1" '
1614                       '-Mask "/24" -NumIps 100'),
1615             mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
1616             mock.call('ls::config $physubnet_ -Name "eth2" -Base "10.42.33.1" '
1617                       '-Mask "/24" -NumIps 100'),
1618             # _configure_report_options
1619             mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
1620         ])
1621
1622     def test_create_dmf(self):
1623         self.mock_tcl_handler.execute.return_value = '2'
1624         self.ls_tcl_client._save_dmf = mock.Mock()
1625         self.ls_tcl_client.create_dmf(copy.deepcopy(DMF_CFG))
1626         self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
1627         # This is needed because the dictionary is unordered and the arguments
1628         # can come in either order
1629         call1 = mock.call(
1630             'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
1631         call2 = mock.call(
1632             'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
1633         self.assertTrue(
1634             call1 in self.mock_tcl_handler.execute.mock_calls or
1635             call2 in self.mock_tcl_handler.execute.mock_calls)
1636
1637         self.mock_tcl_handler.execute.assert_has_calls([
1638             mock.call('set dmf_ [ls::create Dmf]'),
1639             mock.call(
1640                 'ls::get [ls::query LibraryInfo -systemLibraryName user] -Id'),
1641             mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
1642             mock.call('ls::config $dmf_ -dataProtocol "udp"'),
1643             # mock.call(
1644             #    'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
1645             mock.call('ls::config $dmf_ -serverPort 2003'),
1646         ], any_order=True)
1647
1648     def test_configure_dmf(self):
1649         self.mock_tcl_handler.execute.return_value = '2'
1650         self.ls_tcl_client._save_dmf = mock.Mock()
1651         self.ls_tcl_client.configure_dmf(DMF_CFG)
1652         self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
1653         # This is need because the dictionary is unordered and the arguments
1654         # can come in either order
1655         call1 = mock.call(
1656             'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
1657         call2 = mock.call(
1658             'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
1659         self.assertTrue(
1660             call1 in self.mock_tcl_handler.execute.mock_calls or
1661             call2 in self.mock_tcl_handler.execute.mock_calls)
1662
1663         self.mock_tcl_handler.execute.assert_has_calls([
1664             mock.call('set dmf_ [ls::create Dmf]'),
1665             mock.call(
1666                 'ls::get [ls::query LibraryInfo -systemLibraryName user] -Id'),
1667             mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
1668             mock.call('ls::config $dmf_ -dataProtocol "udp"'),
1669             # mock.call(
1670             #    'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
1671             mock.call('ls::config $dmf_ -serverPort 2003'),
1672         ], any_order=True)
1673
1674     def test_delete_dmf(self):
1675         self.assertRaises(NotImplementedError,
1676                           self.ls_tcl_client.delete_dmf,
1677                           DMF_CFG)
1678
1679     def test__save_dmf_valid(self):
1680         exec_resp = [TCL_SUCCESS_RESPONSE, TCL_SUCCESS_RESPONSE]
1681         self.mock_tcl_handler.execute.side_effect = exec_resp
1682         self.ls_tcl_client._save_dmf()
1683         self.assertEqual(len(exec_resp),
1684                          self.mock_tcl_handler.execute.call_count)
1685         self.mock_tcl_handler.execute.assert_has_calls([
1686            mock.call('ls::perform Validate -Dmf $dmf_'),
1687            mock.call('ls::save $dmf_ -overwrite'),
1688         ])
1689
1690     def test__save_dmf_invalid(self):
1691         exec_resp = ['Invalid', 'List of errors and warnings']
1692         self.mock_tcl_handler.execute.side_effect = exec_resp
1693         self.assertRaises(exceptions.LandslideTclException,
1694                           self.ls_tcl_client._save_dmf)
1695         self.assertEqual(len(exec_resp),
1696                          self.mock_tcl_handler.execute.call_count)
1697         self.mock_tcl_handler.execute.assert_has_calls([
1698            mock.call('ls::perform Validate -Dmf $dmf_'),
1699            mock.call('ls::get $dmf_ -ErrorsAndWarnings'),
1700         ])
1701
1702     def test__configure_report_options(self):
1703         _options = {'format': 'CSV', 'PerInterval': 'false'}
1704         self.ls_tcl_client._configure_report_options(_options)
1705         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1706         self.mock_tcl_handler.execute.assert_has_calls([
1707            mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
1708            mock.call('ls::config $test_.ReportOptions -PerInterval false'),
1709            ],
1710            any_order=True)
1711
1712     def test___configure_ts_group(self, *args):
1713         _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
1714         self.ls_tcl_client._configure_tc_type = mock.Mock()
1715         self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
1716         self.ls_tcl_client.resolve_test_server_name = mock.Mock(
1717             return_value='2')
1718         self.ls_tcl_client._configure_ts_group(_ts_group, 0)
1719         self.mock_tcl_handler.execute.assert_called_once_with(
1720             'set tss_ [ls::create TsGroup -under $test_ -tsId 2 ]')
1721
1722     def test___configure_ts_group_resolve_ts_fail(self, *args):
1723         _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
1724         self.ls_tcl_client._configure_tc_type = mock.Mock()
1725         self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
1726         self.ls_tcl_client.resolve_test_server_name = mock.Mock(
1727             return_value='TS Not Found')
1728         self.assertRaises(RuntimeError, self.ls_tcl_client._configure_ts_group,
1729                           _ts_group, 0)
1730         self.mock_tcl_handler.execute.assert_not_called()
1731
1732     def test__configure_tc_type(self):
1733         _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
1734         self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
1735         self.ls_tcl_client._configure_parameters = mock.Mock()
1736         self.ls_tcl_client._configure_tc_type(_tc, 0)
1737         self.assertEqual(7, self.mock_tcl_handler.execute.call_count)
1738
1739     def test__configure_tc_type_optional_param_omitted(self):
1740         _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
1741         del _tc['linked']
1742         self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
1743         self.ls_tcl_client._configure_parameters = mock.Mock()
1744         self.ls_tcl_client._configure_tc_type(_tc, 0)
1745         self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
1746
1747     def test__configure_tc_type_wrong_type(self):
1748         _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
1749         _tc['type'] = 'not_supported'
1750         self.ls_tcl_client._configure_parameters = mock.Mock()
1751         self.assertRaises(RuntimeError,
1752                           self.ls_tcl_client._configure_tc_type,
1753                           _tc, 0)
1754         self.mock_tcl_handler.assert_not_called()
1755
1756     def test__configure_tc_type_not_found_basic_lib(self):
1757         _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
1758         self.ls_tcl_client._configure_parameters = mock.Mock()
1759         self.mock_tcl_handler.execute.return_value = 'Invalid'
1760         self.assertRaises(RuntimeError,
1761                           self.ls_tcl_client._configure_tc_type,
1762                           _tc, 0)
1763
1764     def test__configure_parameters(self):
1765         _params = copy.deepcopy(
1766             SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
1767         self.ls_tcl_client._configure_parameters(_params)
1768         self.assertEqual(16, self.mock_tcl_handler.execute.call_count)
1769
1770     def test__configure_array_param(self):
1771         _array = {"class": "Array",
1772                   "array": ["0"]}
1773         self.ls_tcl_client._configure_array_param('name', _array)
1774         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1775         self.mock_tcl_handler.execute.assert_has_calls([
1776             mock.call('ls::create -Array-name -under $p_ ;'),
1777             mock.call('ls::create ArrayItem -under $p_.name -Value "0"'),
1778         ])
1779
1780     def test__configure_test_node_param(self):
1781         _params = copy.deepcopy(
1782             SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
1783         self.ls_tcl_client._configure_test_node_param('SgwUserAddr',
1784                                                       _params['SgwUserAddr'])
1785         cmd = ('ls::create -TestNode-SgwUserAddr -under $p_ -Type "eth" '
1786         '-Phy "eth1" -Ip "SGW_USER_IP" -NumLinksOrNodes 1 '
1787         '-NextHop "SGW_CONTROL_NEXT_HOP" -Mac "" -MTU 1500 '
1788         '-ForcedEthInterface "" -EthStatsEnabled false -VlanId 0 '
1789         '-VlanUserPriority 0 -NumVlan 1 -UniqueVlanAddr false;')
1790         self.mock_tcl_handler.execute.assert_called_once_with(cmd)
1791
1792     def test__configure_sut_param(self):
1793         _params = {'name': 'name'}
1794         self.ls_tcl_client._configure_sut_param('name', _params)
1795         self.mock_tcl_handler.execute.assert_called_once_with(
1796             'ls::create -Sut-name -under $p_ -Name "name";')
1797
1798     def test__configure_dmf_param(self):
1799         _params = {"mainflows": [{"library": '111',
1800                                   "name": "Basic UDP"}],
1801                    "instanceGroups": [{
1802                        "mainflowIdx": 0,
1803                        "mixType": "",
1804                        "rate": 0.0,
1805                        "rows": [{
1806                            "clientPort": 0,
1807                            "context": 0,
1808                            "node": 0,
1809                            "overridePort": "false",
1810                            "ratingGroup": 0,
1811                            "role": 0,
1812                            "serviceId": 0,
1813                            "transport": "Any"}]
1814                    }]}
1815         self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
1816         res = self.ls_tcl_client._configure_dmf_param('name', _params)
1817         self.assertEqual(5, self.mock_tcl_handler.execute.call_count)
1818         self.assertIsNone(res)
1819         self.mock_tcl_handler.execute.assert_has_calls([
1820             mock.call('ls::create -Dmf-name -under $p_ ;'),
1821             mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
1822             mock.call('ls::config $p_.Dmf.InstanceGroup(0) -mixType '),
1823             mock.call('ls::config $p_.Dmf.InstanceGroup(0) -rate 0.0'),
1824             mock.call('ls::config $p_.Dmf.InstanceGroup(0).Row(0) -Node 0 '
1825                       '-OverridePort false -ClientPort 0 -Context 0 -Role 0 '
1826                       '-PreferredTransport Any -RatingGroup 0 '
1827                       '-ServiceID 0'),
1828         ])
1829
1830     def test__configure_dmf_param_no_instance_groups(self):
1831         _params = {"mainflows": [{"library": '111',
1832                                   "name": "Basic UDP"}]}
1833         self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
1834         res = self.ls_tcl_client._configure_dmf_param('name', _params)
1835         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1836         self.assertIsNone(res)
1837         self.mock_tcl_handler.execute.assert_has_calls([
1838             mock.call('ls::create -Dmf-name -under $p_ ;'),
1839             mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
1840         ])
1841
1842     def test__configure_reservation(self):
1843         _reservation = copy.deepcopy(RESERVATIONS[0])
1844         self.ls_tcl_client.resolve_test_server_name = mock.Mock(
1845             return_value='4')
1846         res = self.ls_tcl_client._configure_reservation(_reservation)
1847         self.assertIsNone(res)
1848         self.assertEqual(4, self.mock_tcl_handler.execute.call_count)
1849         self.mock_tcl_handler.execute.assert_has_calls([
1850             mock.call('set reservation_ [ls::create Reservation -under $test_]'),
1851             mock.call('ls::config $reservation_ -TsIndex 0 -TsId 4 ' + \
1852                       '-TsName "TestServer_1"'),
1853             mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
1854             mock.call('ls::config $physubnet_ -Name "eth1" ' + \
1855                       '-Base "10.42.32.100" -Mask "/24" -NumIps 20'),
1856         ])
1857
1858     def test__configure_preresolved_arp(self):
1859         _arp = [{'StartingAddress': '10.81.1.10',
1860                  'NumNodes': 1}]
1861         res = self.ls_tcl_client._configure_preresolved_arp(_arp)
1862         self.mock_tcl_handler.execute.assert_called_once()
1863         self.assertIsNone(res)
1864         self.mock_tcl_handler.execute.assert_called_once_with(
1865             'ls::create PreResolvedArpAddress -under $tss_ ' + \
1866             '-StartingAddress "10.81.1.10" -NumNodes 1')
1867
1868     def test__configure_preresolved_arp_none(self):
1869         res = self.ls_tcl_client._configure_preresolved_arp(None)
1870         self.assertIsNone(res)
1871         self.mock_tcl_handler.execute.assert_not_called()
1872
1873     def test_delete_test_session(self):
1874         self.assertRaises(NotImplementedError,
1875                           self.ls_tcl_client.delete_test_session, {})
1876
1877     def test__save_test_session(self):
1878         self.mock_tcl_handler.execute.side_effect = [TCL_SUCCESS_RESPONSE,
1879                                                      TCL_SUCCESS_RESPONSE]
1880         res = self.ls_tcl_client._save_test_session()
1881         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1882         self.assertIsNone(res)
1883         self.mock_tcl_handler.execute.assert_has_calls([
1884             mock.call('ls::perform Validate -TestSession $test_'),
1885             mock.call('ls::save $test_ -overwrite'),
1886         ])
1887
1888     def test__save_test_session_invalid(self):
1889         self.mock_tcl_handler.execute.side_effect = ['Invalid', 'Errors']
1890         self.assertRaises(exceptions.LandslideTclException,
1891                           self.ls_tcl_client._save_test_session)
1892         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1893         self.mock_tcl_handler.execute.assert_has_calls([
1894             mock.call('ls::perform Validate -TestSession $test_'),
1895             mock.call('ls::get $test_ -ErrorsAndWarnings'),
1896         ])
1897
1898     def test__get_library_id_system_lib(self):
1899         self.mock_tcl_handler.execute.return_value = '111'
1900         res = self.ls_tcl_client._get_library_id('name')
1901         self.mock_tcl_handler.execute.assert_called_once()
1902         self.assertEqual('111', res)
1903         self.mock_tcl_handler.execute.assert_called_with(
1904             'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id')
1905
1906     def test__get_library_id_user_lib(self):
1907         self.mock_tcl_handler.execute.side_effect = ['Not found', '222']
1908         res = self.ls_tcl_client._get_library_id('name')
1909         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1910         self.assertEqual('222', res)
1911         self.mock_tcl_handler.execute.assert_has_calls([
1912             mock.call(
1913                 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
1914             mock.call(
1915                 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
1916         ])
1917
1918     def test__get_library_id_exception(self):
1919         self.mock_tcl_handler.execute.side_effect = ['Not found', 'Not found']
1920         self.assertRaises(exceptions.LandslideTclException,
1921                           self.ls_tcl_client._get_library_id,
1922                           'name')
1923         self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
1924         self.mock_tcl_handler.execute.assert_has_calls([
1925             mock.call(
1926                 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
1927             mock.call(
1928                 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
1929         ])
1930
1931
1932 class TestLsTclHandler(unittest.TestCase):
1933
1934     def setUp(self):
1935         self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
1936         self.mock_lsapi.start()
1937
1938         self.addCleanup(self._cleanup)
1939
1940     def _cleanup(self):
1941         self.mock_lsapi.stop()
1942
1943     def test___init__(self, *args):
1944         self.ls_tcl_handler = tg_landslide.LsTclHandler()
1945         self.assertEqual({}, self.ls_tcl_handler.tcl_cmds)
1946         self.ls_tcl_handler._ls.tcl.assert_called_once()
1947
1948     def test_execute(self, *args):
1949         self.ls_tcl_handler = tg_landslide.LsTclHandler()
1950         self.ls_tcl_handler.execute('command')
1951         self.assertIn('command', self.ls_tcl_handler.tcl_cmds)