Merge "Add unit test file for ArithmeticRunner"
[yardstick.git] / yardstick / tests / unit / network_services / libs / ixia_libs / test_ixnet_api.py
1 # Copyright (c) 2018 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 mock
16 import IxNetwork
17 import unittest
18
19 from yardstick.common import exceptions
20 from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
21
22
23 UPLINK = 'uplink'
24 DOWNLINK = 'downlink'
25
26 TRAFFIC_PARAMETERS = {
27     UPLINK: {
28         'id': 1,
29         'bidir': 'False',
30         'duration': 60,
31         'rate': 10000.5,
32         'rate_unit': 'fps',
33         'outer_l2': {
34             'framesize': {'64B': '25', '256B': '75'}
35         },
36         'outer_l3': {
37             'count': 512,
38             'seed': 1,
39             'dscp': 0,
40             'proto': 'udp',
41             'ttl': 32,
42             'dstip': '152.16.40.20',
43             'srcip': '152.16.100.20',
44             'dstmask': 24,
45             'srcmask': 24
46         },
47         'outer_l4': {
48             'seed': 1,
49             'count': 1,
50             'dstport': 2001,
51             'srcport': 1234,
52             'srcportmask': 0,
53             'dstportmask': 0
54         },
55         'traffic_type': 'continuous'
56     },
57     DOWNLINK: {
58         'id': 2,
59         'bidir': 'False',
60         'duration': 60,
61         'rate': 75.2,
62         'rate_unit': '%',
63         'outer_l2': {
64             'framesize': {'128B': '35', '1024B': '65'}
65         },
66         'outer_l3': {
67             'count': 1024,
68             'seed': 1,
69             'dscp': 0,
70             'proto': 'udp',
71             'ttl': 32,
72             'dstip': '2001::10',
73             'srcip': '2021::10',
74             'dstmask': 64,
75             'srcmask': 64
76         },
77         'outer_l4': {
78             'seed': 1,
79             'count': 1,
80             'dstport': 1234,
81             'srcport': 2001,
82             'srcportmask': 0,
83             'dstportmask': 0
84         },
85         'traffic_type': 'continuous'
86     }
87 }
88
89
90 class TestIxNextgen(unittest.TestCase):
91
92     def setUp(self):
93         self.ixnet = mock.Mock()
94         self.ixnet.execute = mock.Mock()
95         self.ixnet.getRoot.return_value = 'my_root'
96         self.ixnet_gen = ixnet_api.IxNextgen()
97         self.ixnet_gen._ixnet = self.ixnet
98
99     def test_get_config(self):
100         tg_cfg = {
101             'vdu': [
102                 {
103                     'external-interface': [
104                         {'virtual-interface': {'vpci': '0000:07:00.1'}},
105                         {'virtual-interface': {'vpci': '0001:08:01.2'}}
106                     ]
107                 },
108             ],
109             'mgmt-interface': {
110                 'ip': 'test1',
111                 'tg-config': {
112                     'dut_result_dir': 'test2',
113                     'version': 'test3',
114                     'ixchassis': 'test4',
115                     'tcl_port': 'test5',
116                 },
117             }
118         }
119
120         expected = {
121             'machine': 'test1',
122             'port': 'test5',
123             'chassis': 'test4',
124             'cards': ['0000', '0001'],
125             'ports': ['07', '08'],
126             'output_dir': 'test2',
127             'version': 'test3',
128             'bidir': True,
129         }
130
131         result = ixnet_api.IxNextgen.get_config(tg_cfg)
132         self.assertEqual(result, expected)
133
134     def test__get_config_element_by_flow_group_name(self):
135         self.ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
136                                                      ['fg_01']]
137         self.ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_01'
138         output = self.ixnet_gen._get_config_element_by_flow_group_name(
139             'flow_group_01')
140         self.assertEqual('traffic_item/configElement:flow_group_01', output)
141
142     def test__get_config_element_by_flow_group_name_no_match(self):
143         self.ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
144                                                      ['fg_01']]
145         self.ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_02'
146         output = self.ixnet_gen._get_config_element_by_flow_group_name(
147             'flow_group_01')
148         self.assertIsNone(output)
149
150     def test__get_stack_item(self):
151         self.ixnet_gen._ixnet.getList.return_value = ['tcp1', 'tcp2', 'udp']
152         with mock.patch.object(
153                 self.ixnet_gen, '_get_config_element_by_flow_group_name') as \
154                 mock_get_cfg_element:
155             mock_get_cfg_element.return_value = 'cfg_element'
156             output = self.ixnet_gen._get_stack_item(mock.ANY, ixnet_api.PROTO_TCP)
157         self.assertEqual(['tcp1', 'tcp2'], output)
158
159     def test__get_stack_item_no_config_element(self):
160         with mock.patch.object(
161                 self.ixnet_gen, '_get_config_element_by_flow_group_name',
162                 return_value=None):
163             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
164                 self.ixnet_gen._get_stack_item(mock.ANY, mock.ANY)
165
166     def test__get_field_in_stack_item(self):
167         self.ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
168         output = self.ixnet_gen._get_field_in_stack_item(mock.ANY, 'field2')
169         self.assertEqual('field2', output)
170
171     def test__get_field_in_stack_item_no_field_present(self):
172         self.ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
173         with self.assertRaises(exceptions.IxNetworkFieldNotPresentInStackItem):
174             self.ixnet_gen._get_field_in_stack_item(mock.ANY, 'field3')
175
176     def test__parse_framesize(self):
177         framesize = {'64B': '75', '512b': '25'}
178         output = self.ixnet_gen._parse_framesize(framesize)
179         self.assertEqual(2, len(output))
180         self.assertIn([64, 64, 75], output)
181         self.assertIn([512, 512, 25], output)
182
183     @mock.patch.object(IxNetwork, 'IxNet')
184     def test_connect(self, mock_ixnet):
185         mock_ixnet.return_value = self.ixnet
186         with mock.patch.object(self.ixnet_gen, 'get_config') as mock_config:
187             mock_config.return_value = {'machine': 'machine_fake',
188                                         'port': 'port_fake',
189                                         'version': 12345}
190             self.ixnet_gen.connect(mock.ANY)
191
192         self.ixnet.connect.assert_called_once_with(
193             'machine_fake', '-port', 'port_fake', '-version', '12345')
194         mock_config.assert_called_once()
195
196     def test_connect_invalid_config_no_machine(self):
197         self.ixnet_gen.get_config = mock.Mock(return_value={
198             'port': 'port_fake',
199             'version': '12345'})
200         self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
201         self.ixnet.connect.assert_not_called()
202
203     def test_connect_invalid_config_no_port(self):
204         self.ixnet_gen.get_config = mock.Mock(return_value={
205             'machine': 'machine_fake',
206             'version': '12345'})
207         self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
208         self.ixnet.connect.assert_not_called()
209
210     def test_connect_invalid_config_no_version(self):
211         self.ixnet_gen.get_config = mock.Mock(return_value={
212             'machine': 'machine_fake',
213             'port': 'port_fake'})
214         self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
215         self.ixnet.connect.assert_not_called()
216
217     def test_connect_no_config(self):
218         self.ixnet_gen.get_config = mock.Mock(return_value={})
219         self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
220         self.ixnet.connect.assert_not_called()
221
222     def test_clear_config(self):
223         self.ixnet_gen.clear_config()
224         self.ixnet.execute.assert_called_once_with('newConfig')
225
226     @mock.patch.object(ixnet_api, 'log')
227     def test_assign_ports_2_ports(self, *args):
228         self.ixnet.getAttribute.side_effect = ['up', 'down']
229         config = {
230             'chassis': '1.1.1.1',
231             'cards': ['1', '2'],
232             'ports': ['2', '2']}
233         self.ixnet_gen._cfg = config
234
235         self.assertIsNone(self.ixnet_gen.assign_ports())
236         self.assertEqual(self.ixnet.execute.call_count, 2)
237         self.assertEqual(self.ixnet.commit.call_count, 4)
238         self.assertEqual(self.ixnet.getAttribute.call_count, 2)
239
240     @mock.patch.object(ixnet_api, 'log')
241     def test_assign_ports_port_down(self, mock_log):
242         self.ixnet.getAttribute.return_value = 'down'
243         config = {
244             'chassis': '1.1.1.1',
245             'cards': ['1', '2'],
246             'ports': ['3', '4']}
247         self.ixnet_gen._cfg = config
248         self.ixnet_gen.assign_ports()
249         mock_log.warning.assert_called()
250
251     def test_assign_ports_no_config(self):
252         self.ixnet_gen._cfg = {}
253         self.assertRaises(KeyError, self.ixnet_gen.assign_ports)
254
255     def test__create_traffic_item(self):
256         self.ixnet.add.return_value = 'my_new_traffic_item'
257         self.ixnet.remapIds.return_value = ['my_traffic_item_id']
258
259         self.ixnet_gen._create_traffic_item()
260         self.ixnet.add.assert_called_once_with(
261             'my_root/traffic', 'trafficItem')
262         self.ixnet.setMultiAttribute.assert_called_once_with(
263             'my_new_traffic_item', '-name', 'RFC2544', '-trafficType', 'raw')
264         self.assertEqual(2, self.ixnet.commit.call_count)
265         self.ixnet.remapIds.assert_called_once_with('my_new_traffic_item')
266         self.ixnet.setAttribute('my_traffic_item_id/tracking',
267                                 '-trackBy', 'trafficGroupId0')
268
269     def test__create_flow_groups(self):
270         self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
271         self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
272         self.ixnet_gen._create_flow_groups()
273         self.ixnet_gen.ixnet.add.assert_has_calls([
274             mock.call('traffic_item', 'endpointSet'),
275             mock.call('traffic_item', 'endpointSet')])
276         self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
277             mock.call('endp1', '-name', '1', '-sources', ['1/protocols'],
278                       '-destinations', ['2/protocols']),
279             mock.call('endp2', '-name', '2', '-sources', ['2/protocols'],
280                       '-destinations', ['1/protocols'])])
281
282     def test__append_protocol_to_stack(self):
283
284         self.ixnet_gen._append_procotol_to_stack('my_protocol', 'prev_element')
285         self.ixnet.execute.assert_called_with(
286             'append', 'prev_element',
287             'my_root/traffic/protocolTemplate:"my_protocol"')
288
289     def test__setup_config_elements(self):
290         self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'],
291                                                ['cfg_element']]
292         with mock.patch.object(self.ixnet_gen, '_append_procotol_to_stack') as \
293                 mock_append_proto:
294             self.ixnet_gen._setup_config_elements()
295         mock_append_proto.assert_has_calls([
296             mock.call(ixnet_api.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'),
297             mock.call(ixnet_api.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')])
298         self.ixnet_gen.ixnet.setAttribute.assert_has_calls([
299             mock.call('cfg_element/frameRateDistribution', '-portDistribution',
300                       'splitRateEvenly'),
301             mock.call('cfg_element/frameRateDistribution',
302                       '-streamDistribution', 'splitRateEvenly')])
303
304     @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
305     @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
306     @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
307     def test_create_traffic_model(self, mock__setup_config_elements,
308                                   mock__create_flow_groups,
309                                   mock__create_traffic_item):
310
311         self.ixnet_gen.create_traffic_model()
312         mock__create_traffic_item.assert_called_once()
313         mock__create_flow_groups.assert_called_once()
314         mock__setup_config_elements.assert_called_once()
315
316     def test__update_frame_mac(self):
317         with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item') as \
318                 mock_get_field:
319             mock_get_field.return_value = 'field_descriptor'
320             self.ixnet_gen._update_frame_mac('ethernet_descriptor', 'field', 'mac')
321         mock_get_field.assert_called_once_with('ethernet_descriptor', 'field')
322         self.ixnet_gen.ixnet.setMultiAttribute(
323             'field_descriptor', '-singleValue', 'mac', '-fieldValue', 'mac',
324             '-valueType', 'singleValue')
325         self.ixnet_gen.ixnet.commit.assert_called_once()
326
327     def test_update_frame(self):
328         with mock.patch.object(
329                 self.ixnet_gen, '_get_config_element_by_flow_group_name',
330                 return_value='cfg_element'), \
331                 mock.patch.object(self.ixnet_gen, '_update_frame_mac') as \
332                 mock_update_frame, \
333                 mock.patch.object(self.ixnet_gen, '_get_stack_item') as \
334                 mock_get_stack_item:
335             mock_get_stack_item.side_effect = [['item1'], ['item2'],
336                                                ['item3'], ['item4']]
337             self.ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 50)
338
339         self.assertEqual(6, len(self.ixnet_gen.ixnet.setMultiAttribute.mock_calls))
340         self.assertEqual(4, len(mock_update_frame.mock_calls))
341
342     def test_update_frame_flow_not_present(self):
343         with mock.patch.object(
344                 self.ixnet_gen, '_get_config_element_by_flow_group_name',
345                 return_value=None):
346             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
347                 self.ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 40)
348
349     def test_get_statistics(self):
350         port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"'
351         flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"'
352         with mock.patch.object(self.ixnet_gen, '_build_stats_map') as \
353                 mock_build_stats:
354             self.ixnet_gen.get_statistics()
355
356         mock_build_stats.assert_has_calls([
357             mock.call(port_statistics, self.ixnet_gen.PORT_STATS_NAME_MAP),
358             mock.call(flow_statistics, self.ixnet_gen.LATENCY_NAME_MAP)])
359
360     def test__update_ipv4_address(self):
361         with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
362                                return_value='field_desc'):
363             self.ixnet_gen._update_ipv4_address(mock.ANY, mock.ANY, '192.168.1.1',
364                                            100, 26, 25)
365         self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
366             'field_desc', '-seed', 100, '-fixedBits', '192.168.1.1',
367             '-randomMask', '0.0.0.63', '-valueType', 'random',
368             '-countValue', 25)
369
370     def test__update_udp_port(self):
371         with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
372                                return_value='field_desc'):
373             self.ixnet_gen._update_udp_port(mock.ANY, mock.ANY, 1234,
374                                             2, 0, 2)
375
376         self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
377             'field_desc',
378             '-auto', 'false',
379             '-seed', 1,
380             '-fixedBits', 1234,
381             '-randomMask', 0,
382             '-valueType', 'random',
383             '-countValue', 1)
384
385     def test_update_ip_packet(self):
386         with mock.patch.object(self.ixnet_gen, '_update_ipv4_address') as \
387                 mock_update_add, \
388                 mock.patch.object(self.ixnet_gen, '_get_stack_item'), \
389                 mock.patch.object(self.ixnet_gen,
390                 '_get_config_element_by_flow_group_name', return_value='celm'):
391             self.ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
392
393         self.assertEqual(4, len(mock_update_add.mock_calls))
394
395     def test_update_ip_packet_exception_no_config_element(self):
396         with mock.patch.object(self.ixnet_gen,
397                                '_get_config_element_by_flow_group_name',
398                                return_value=None):
399             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
400                 self.ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
401
402     def test_update_l4(self):
403         with mock.patch.object(self.ixnet_gen, '_update_udp_port') as \
404                 mock_update_udp, \
405                 mock.patch.object(self.ixnet_gen, '_get_stack_item'), \
406                 mock.patch.object(self.ixnet_gen,
407                 '_get_config_element_by_flow_group_name', return_value='celm'):
408             self.ixnet_gen.update_l4(TRAFFIC_PARAMETERS)
409
410         self.assertEqual(4, len(mock_update_udp.mock_calls))
411
412     def test_update_l4_exception_no_config_element(self):
413         with mock.patch.object(self.ixnet_gen,
414                                '_get_config_element_by_flow_group_name',
415                                return_value=None):
416             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
417                 self.ixnet_gen.update_l4(TRAFFIC_PARAMETERS)
418
419     def test_update_l4_exception_no_supported_proto(self):
420         traffic_parameters = {
421             UPLINK: {
422                 'id': 1,
423                 'outer_l3': {
424                     'proto': 'unsupported',
425                 },
426             },
427         }
428         with mock.patch.object(self.ixnet_gen,
429                                '_get_config_element_by_flow_group_name',
430                                return_value='celm'):
431             with self.assertRaises(exceptions.IXIAUnsupportedProtocol):
432                 self.ixnet_gen.update_l4(traffic_parameters)
433
434     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
435     def test_start_traffic(self, mock_ixnextgen_get_traffic_state):
436         self.ixnet_gen._ixnet.getList.return_value = [0]
437
438         mock_ixnextgen_get_traffic_state.side_effect = [
439             'stopped', 'started', 'started', 'started']
440
441         result = self.ixnet_gen.start_traffic()
442         self.assertIsNone(result)
443         self.ixnet.getList.assert_called_once()
444         self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
445
446     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
447     def test_start_traffic_traffic_running(
448             self, mock_ixnextgen_get_traffic_state):
449         self.ixnet_gen._ixnet.getList.return_value = [0]
450         mock_ixnextgen_get_traffic_state.side_effect = [
451             'started', 'stopped', 'started']
452
453         result = self.ixnet_gen.start_traffic()
454         self.assertIsNone(result)
455         self.ixnet.getList.assert_called_once()
456         self.assertEqual(4, self.ixnet_gen._ixnet.execute.call_count)
457
458     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
459     def test_start_traffic_wait_for_traffic_to_stop(
460             self, mock_ixnextgen_get_traffic_state):
461         self.ixnet_gen._ixnet.getList.return_value = [0]
462         mock_ixnextgen_get_traffic_state.side_effect = [
463             'started', 'started', 'started', 'stopped', 'started']
464
465         result = self.ixnet_gen.start_traffic()
466         self.assertIsNone(result)
467         self.ixnet.getList.assert_called_once()
468         self.assertEqual(4, self.ixnet_gen._ixnet.execute.call_count)
469
470     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
471     def test_start_traffic_wait_for_traffic_start(
472             self, mock_ixnextgen_get_traffic_state):
473         self.ixnet_gen._ixnet.getList.return_value = [0]
474         mock_ixnextgen_get_traffic_state.side_effect = [
475             'stopped', 'stopped', 'stopped', 'started']
476
477         result = self.ixnet_gen.start_traffic()
478         self.assertIsNone(result)
479         self.ixnet.getList.assert_called_once()
480         self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)