Merge "improve tc055 results"
[yardstick.git] / tests / unit / network_services / vnf_generic / vnf / test_prox_helpers.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016-2017 Intel Corporation
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17
18 from __future__ import absolute_import
19
20 import os
21 import socket
22 import unittest
23 from collections import OrderedDict
24 from itertools import repeat, chain
25 from contextlib import contextmanager
26 import mock
27
28 from tests.unit import STL_MOCKS
29
30
31 STLClient = mock.MagicMock()
32 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
33 stl_patch.start()
34
35 if stl_patch:
36     from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
37     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxSocketHelper
38     from yardstick.network_services.vnf_generic.vnf.prox_helpers import PacketDump
39     from yardstick.network_services.vnf_generic.vnf.prox_helpers import CoreSocketTuple
40     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
41     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDpdkVnfSetupEnvHelper
42     from yardstick.network_services.vnf_generic.vnf.prox_helpers import TotStatsTuple
43     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
44
45
46 class TestCoreTuple(unittest.TestCase):
47
48     def test___init__(self):
49         core_tuple = CoreSocketTuple('core 5s6')
50         self.assertEqual(core_tuple.core_id, 5)
51         self.assertEqual(core_tuple.socket_id, 6)
52         self.assertFalse(core_tuple.is_hyperthread())
53
54         core_tuple = CoreSocketTuple('core 5s6h')
55         self.assertEqual(core_tuple.core_id, 5)
56         self.assertEqual(core_tuple.socket_id, 6)
57         self.assertTrue(core_tuple.is_hyperthread())
58
59     def test___init__negative(self):
60         bad_inputs = [
61             '',
62             '5',
63             '5s',
64             '6h',
65             '5s6',
66             'core',
67             'core h',
68             'core 5',
69             'core 5s',
70             'core 5 6',
71             'core 5 6h',
72             'core 5d6',
73             'core 5d6h',
74             1,
75             2.3,
76             [],
77             {},
78             object(),
79         ]
80
81         for bad_input in bad_inputs:
82             with self.assertRaises(ValueError):
83                 CoreSocketTuple(bad_input)
84
85     def test_find_in_topology(self):
86         topology_in = {
87             6: {
88                 5: {
89                     'key1': ['a', 'b'],
90                     'key2': ['c', 'd'],
91                 },
92             },
93         }
94
95         core_tuple = CoreSocketTuple('core 5s6')
96
97         expected = 'a'
98         result = core_tuple.find_in_topology(topology_in)
99         self.assertEqual(result, expected)
100
101         core_tuple = CoreSocketTuple('core 5s6h')
102
103         expected = 'c'
104         result = core_tuple.find_in_topology(topology_in)
105         self.assertEqual(result, expected)
106
107     def test_find_in_topology_negative(self):
108         core_tuple = CoreSocketTuple('core 6s5')
109         with self.assertRaises(ValueError):
110             # no socket key
111             core_tuple.find_in_topology({})
112
113         with self.assertRaises(ValueError):
114             # no core key
115             core_tuple.find_in_topology({5: {}})
116
117         with self.assertRaises(ValueError):
118             # no first value (as needed by non-hyperthread core)
119             core_tuple.find_in_topology({5: {6: {'key1': []}}})
120
121         core_tuple = CoreSocketTuple('core 6s5h')
122         with self.assertRaises(ValueError):
123             # no second value (as needed by hyperthread core)
124             core_tuple.find_in_topology({5: {6: {'key1': ['e']}}})
125
126
127 class TestTotStatsTuple(unittest.TestCase):
128
129     def test___new___negative(self):
130         with self.assertRaises(TypeError):
131             # no values
132             TotStatsTuple()
133
134         with self.assertRaises(TypeError):
135             # one, non-integer value
136             TotStatsTuple('a')
137
138         with self.assertRaises(TypeError):
139             # too many values
140             TotStatsTuple(3, 4, 5, 6, 7)
141
142
143 class TestProxTestDataTuple(unittest.TestCase):
144
145     def test___init__(self):
146         prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 8, 9)
147         self.assertEqual(prox_test_data.tolerated, 1)
148         self.assertEqual(prox_test_data.tsc_hz, 2)
149         self.assertEqual(prox_test_data.delta_rx, 3)
150         self.assertEqual(prox_test_data.delta_tx, 4)
151         self.assertEqual(prox_test_data.delta_tsc, 5)
152         self.assertEqual(prox_test_data.latency, 6)
153         self.assertEqual(prox_test_data.rx_total, 7)
154         self.assertEqual(prox_test_data.tx_total, 8)
155         self.assertEqual(prox_test_data.pps, 9)
156
157     def test_properties(self):
158         prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 8, 9)
159         self.assertEqual(prox_test_data.pkt_loss, 12.5)
160         self.assertEqual(prox_test_data.mpps, 1.6 / 1e6)
161         self.assertEqual(prox_test_data.can_be_lost, 0)
162         self.assertEqual(prox_test_data.drop_total, 1)
163         self.assertFalse(prox_test_data.success)
164
165         prox_test_data = ProxTestDataTuple(10, 2, 3, 4, 5, 6, 997, 998, 9)
166         self.assertTrue(prox_test_data.success)
167
168     def test_pkt_loss_zero_division(self):
169         prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 0, 9)
170         self.assertEqual(prox_test_data.pkt_loss, 100.0)
171
172     def test_get_samples(self):
173         prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
174
175         expected = {
176             "Throughput": 1.6 / 1e6,
177             "DropPackets": 12.5,
178             "CurrentDropPackets": 12.5,
179             "TxThroughput": 9 / 1e6,
180             "RxThroughput": 1.6 / 1e6,
181             "PktSize": 64,
182             "LatencyMin": 6.1,
183             "LatencyMax": 6.9,
184             "LatencyAvg": 6.4,
185         }
186         result = prox_test_data.get_samples(64)
187         self.assertDictEqual(result, expected)
188
189         expected = {
190             "Throughput": 1.6 / 1e6,
191             "DropPackets": 0.123,
192             "CurrentDropPackets": 0.123,
193             "TxThroughput": 9 / 1e6,
194             "RxThroughput": 1.6 / 1e6,
195             "PktSize": 64,
196             "LatencyMin": 6.1,
197             "LatencyMax": 6.9,
198             "LatencyAvg": 6.4,
199         }
200         result = prox_test_data.get_samples(64, 0.123)
201         self.assertDictEqual(result, expected)
202
203     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.LOG')
204     def test_log_data(self, mock_logger):
205         my_mock_logger = mock.MagicMock()
206         prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
207         prox_test_data.log_data()
208         self.assertEqual(my_mock_logger.debug.call_count, 0)
209         self.assertEqual(mock_logger.debug.call_count, 2)
210
211         mock_logger.debug.reset_mock()
212         prox_test_data.log_data(my_mock_logger)
213         self.assertEqual(my_mock_logger.debug.call_count, 2)
214         self.assertEqual(mock_logger.debug.call_count, 0)
215
216
217 class TestPacketDump(unittest.TestCase):
218
219     PAYLOAD = "payload"
220
221     def test__init__(self):
222         PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
223
224     def test___str__(self):
225         expected = '<PacketDump port: port_id payload: {}>'.format(self.PAYLOAD)
226         dump1 = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
227         self.assertEqual(str(dump1), expected)
228
229     def test_port_id(self):
230         p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
231         self.assertEqual(p.port_id, "port_id")
232
233     def test_data_len(self):
234         p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
235         self.assertEqual(p.data_len, len(self.PAYLOAD))
236
237     def test_payload(self):
238         p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
239         self.assertEqual(p.payload(), self.PAYLOAD)
240
241         self.assertEqual(p.payload(3), self.PAYLOAD[3:])
242
243         self.assertEqual(p.payload(end=3), self.PAYLOAD[:4])
244
245         self.assertEqual(p.payload(2, 4), self.PAYLOAD[2:5])
246
247
248 PACKET_DUMP_1 = """\
249 pktdump,3,11
250 hello world
251 """
252
253 PACKET_DUMP_2 = """\
254 pktdump,3,11
255 hello world
256 pktdump,2,9
257 brown fox jumped over
258 pktdump,4,8
259 lazy
260 dog
261 """
262
263 PACKET_DUMP_NON_1 = """\
264 not_a_dump,1,2
265 other data
266 """
267
268 PACKET_DUMP_MIXED_1 = """\
269 pktdump,3,11
270 hello world
271 not_a_dump,1,2
272 other data
273 """
274
275 PACKET_DUMP_BAD_1 = """\
276 pktdump,one,12
277 bad port id
278 """
279
280 PACKET_DUMP_BAD_2 = """\
281 pktdump,3,twelve
282 bad data length
283 """
284
285 PACKET_DUMP_BAD_3 = """\
286 pktdump,3
287 no data length value
288 """
289
290
291 @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
292 class TestProxSocketHelper(unittest.TestCase):
293
294     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
295     def test___init__(self, mock_socket, mock_time):
296         expected = mock_socket.socket()
297         prox = ProxSocketHelper()
298         result = prox._sock
299         self.assertEqual(result, expected)
300
301     def test_connect(self, mock_time):
302         mock_sock = mock.MagicMock()
303         prox = ProxSocketHelper(mock_sock)
304         prox.connect('10.20.30.40', 23456)
305         self.assertEqual(mock_sock.connect.call_count, 1)
306
307     def test_get_sock(self, mock_time):
308         mock_sock = mock.MagicMock()
309         prox = ProxSocketHelper(mock_sock)
310         result = prox.get_socket()
311         self.assertIs(result, mock_sock)
312
313     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.select')
314     def test_get_data(self, mock_select, mock_time):
315         mock_select.select.side_effect = [[1], [0]]
316         mock_socket = mock.MagicMock()
317         mock_recv = mock_socket.recv()
318         mock_recv.decode.return_value = ""
319         prox = ProxSocketHelper(mock_socket)
320         ret = prox.get_data()
321         self.assertEqual(ret, "")
322         self.assertEqual(len(prox._pkt_dumps), 0)
323
324         mock_select.select.reset_mock()
325         mock_select.select.side_effect = chain([['a'], ['']], repeat([1], 3))
326         mock_recv.decode.return_value = PACKET_DUMP_1
327         ret = prox.get_data()
328         self.assertEqual(mock_select.select.call_count, 2)
329         self.assertEqual(ret, 'pktdump,3,11')
330         self.assertEqual(len(prox._pkt_dumps), 1)
331
332         mock_select.select.reset_mock()
333         mock_select.select.side_effect = chain([[object()], [None]], repeat([1], 3))
334         mock_recv.decode.return_value = PACKET_DUMP_2
335         ret = prox.get_data()
336         self.assertEqual(mock_select.select.call_count, 2)
337         self.assertEqual(ret, 'jumped over')
338         self.assertEqual(len(prox._pkt_dumps), 3)
339
340     def test__parse_socket_data_mixed_data(self, mock_time):
341         prox = ProxSocketHelper(mock.MagicMock())
342         ret = prox._parse_socket_data(PACKET_DUMP_NON_1, False)
343         self.assertEqual(ret, 'not_a_dump,1,2')
344         self.assertEqual(len(prox._pkt_dumps), 0)
345
346         ret = prox._parse_socket_data(PACKET_DUMP_MIXED_1, False)
347         self.assertEqual(ret, 'not_a_dump,1,2')
348         self.assertEqual(len(prox._pkt_dumps), 1)
349
350     def test__parse_socket_data_bad_data(self, mock_time):
351         prox = ProxSocketHelper(mock.MagicMock())
352         with self.assertRaises(ValueError):
353             prox._parse_socket_data(PACKET_DUMP_BAD_1, False)
354
355         with self.assertRaises(ValueError):
356             prox._parse_socket_data(PACKET_DUMP_BAD_2, False)
357
358         ret = prox._parse_socket_data(PACKET_DUMP_BAD_3, False)
359         self.assertEqual(ret, 'pktdump,3')
360
361     def test__parse_socket_data_pkt_dump_only(self, mock_time):
362         prox = ProxSocketHelper(mock.MagicMock())
363         ret = prox._parse_socket_data('', True)
364         self.assertFalse(ret)
365
366         ret = prox._parse_socket_data(PACKET_DUMP_1, True)
367         self.assertTrue(ret)
368
369         ret = prox._parse_socket_data(PACKET_DUMP_2, True)
370         self.assertTrue(ret)
371
372     def test_put_command(self, mock_time):
373         mock_socket = mock.MagicMock()
374         prox = ProxSocketHelper(mock_socket)
375         prox.put_command("data")
376         mock_socket.sendall.assert_called_once()
377
378     def test_get_packet_dump(self, mock_time):
379         mock_socket = mock.MagicMock()
380         prox = ProxSocketHelper(mock_socket)
381         prox._pkt_dumps = []
382         self.assertIsNone(prox.get_packet_dump())
383
384         prox._pkt_dumps = [234]
385         self.assertEqual(prox.get_packet_dump(), 234)
386         self.assertEqual(prox._pkt_dumps, [])
387
388     def test_stop_all_reset(self, mock_time):
389         mock_socket = mock.MagicMock()
390         prox = ProxSocketHelper(mock_socket)
391         prox.stop_all_reset()
392         mock_socket.sendall.assert_called()
393
394     def test_stop_all(self, mock_time):
395         mock_socket = mock.MagicMock()
396         prox = ProxSocketHelper(mock_socket)
397         prox.stop_all()
398         mock_socket.sendall.assert_called()
399
400     def test_stop(self, mock_time):
401         mock_socket = mock.MagicMock()
402         prox = ProxSocketHelper(mock_socket)
403         prox.stop([3, 4, 5], 16)
404         mock_socket.sendall.assert_called()
405
406     def test_start_all(self, mock_time):
407         mock_socket = mock.MagicMock()
408         prox = ProxSocketHelper(mock_socket)
409         prox.start_all()
410         mock_socket.sendall.assert_called()
411
412     def test_start(self, mock_time):
413         mock_socket = mock.MagicMock()
414         prox = ProxSocketHelper(mock_socket)
415         prox.start([3, 4, 5])
416         mock_socket.sendall.assert_called()
417
418     def test_reset_stats(self, mock_time):
419         mock_socket = mock.MagicMock()
420         prox = ProxSocketHelper(mock_socket)
421         prox.reset_stats()
422         mock_socket.sendall.assert_called()
423
424     def test_set_pkt_size(self, mock_time):
425         mock_socket = mock.MagicMock()
426         prox = ProxSocketHelper(mock_socket)
427         prox.set_pkt_size([3, 4, 5], 1024)
428         self.assertEqual(mock_socket.sendall.call_count, 3)
429
430     def test_set_value(self, mock_time):
431         mock_socket = mock.MagicMock()
432         prox = ProxSocketHelper(mock_socket)
433         prox.set_value([3, 4, 5], 10, 20, 30)
434         self.assertEqual(mock_socket.sendall.call_count, 3)
435
436     def test_reset_values(self, mock_time):
437         mock_socket = mock.MagicMock()
438         prox = ProxSocketHelper(mock_socket)
439         prox.reset_values([3, 4, 5])
440         self.assertEqual(mock_socket.sendall.call_count, 3)
441
442     def test_set_speed(self, mock_time):
443         mock_socket = mock.MagicMock()
444         prox = ProxSocketHelper(mock_socket)
445         prox.set_speed([3, 4, 5], 1000)
446         self.assertEqual(mock_socket.sendall.call_count, 3)
447
448     def test_slope_speed(self, mock_time):
449         core_data = [
450             {
451                 'cores': [3, 4, 5],
452                 'speed': 1000,
453             },
454             {
455                 'cores': [9, 10, 11],
456                 'speed': '500.5',
457             },
458         ]
459
460         mock_socket = mock.MagicMock()
461         prox = ProxSocketHelper(mock_socket)
462         prox.set_speed = set_speed = mock.MagicMock()
463         prox.slope_speed(core_data, 5)
464         self.assertEqual(set_speed.call_count, 20)
465
466         set_speed.reset_mock()
467         prox.slope_speed(core_data, 5, 5)
468         self.assertEqual(set_speed.call_count, 10)
469
470     def test_set_pps(self, mock_time):
471         mock_socket = mock.MagicMock()
472         prox = ProxSocketHelper(mock_socket)
473         prox.set_pps([3, 4, 5], 1000, 512)
474         self.assertEqual(mock_socket.sendall.call_count, 3)
475
476     def test_lat_stats(self, mock_time):
477         latency_output = [
478             '1, 2 , 3',       # has white space
479             '4,5',            # too short
480             '7,8,9,10.5,11',  # too long with float, but float is in unused portion
481             'twelve,13,14',   # value as English word
482             '15,16.2,17',     # float in used portion
483         ]
484
485         mock_socket = mock.MagicMock()
486         prox = ProxSocketHelper(mock_socket)
487         prox.get_data = mock.MagicMock(side_effect=latency_output)
488
489         expected = (
490             {
491                 3: 1,
492                 5: 7,
493             },
494             {
495                 3: 2,
496                 5: 8,
497             },
498             {
499                 3: 3,
500                 5: 9,
501             },
502         )
503         result = prox.lat_stats([3, 4, 5, 6, 7], 16)
504         self.assertEqual(mock_socket.sendall.call_count, 5)
505         self.assertEqual(result, expected)
506
507     def test_get_all_tot_stats(self, mock_time):
508         mock_socket = mock.MagicMock()
509         prox = ProxSocketHelper(mock_socket)
510         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
511         expected = 3, 4, 5, 6
512         result = prox.get_all_tot_stats()
513         self.assertEqual(result, expected)
514
515     def test_hz(self, mock_time):
516         mock_socket = mock.MagicMock()
517         prox = ProxSocketHelper(mock_socket)
518         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
519         expected = 6
520         result = prox.hz()
521         self.assertEqual(result, expected)
522
523     def test_rx_stats(self, mock_time):
524         core_stats = [
525             '3,4,5,6',
526             '7,8,9,10,NaN',
527             '11,12,13,14,15',
528         ]
529
530         mock_socket = mock.MagicMock()
531         prox = ProxSocketHelper(mock_socket)
532         prox.get_data = mock.MagicMock(side_effect=core_stats)
533         expected = 21, 24, 27, 14
534         result = prox.rx_stats([3, 4, 5], 16)
535         self.assertEqual(result, expected)
536
537     def test_core_stats(self, mock_time):
538         core_stats = [
539             '3,4,5,6',
540             '7,8,9,10,NaN',
541             '11,12,13,14,15',
542         ]
543
544         mock_socket = mock.MagicMock()
545         prox = ProxSocketHelper(mock_socket)
546         prox.get_data = mock.MagicMock(side_effect=core_stats)
547         expected = 21, 24, 27, 14
548         result = prox.core_stats([3, 4, 5], 16)
549         self.assertEqual(result, expected)
550
551     def test_port_stats(self, mock_time):
552         port_stats = [
553             ','.join(str(n) for n in range(3, 15)),
554             ','.join(str(n) for n in range(8, 32, 2)),
555             ','.join(str(n) for n in range(5, 89, 7)),
556         ]
557
558         mock_socket = mock.MagicMock()
559         prox = ProxSocketHelper(mock_socket)
560         prox.get_data = mock.MagicMock(side_effect=port_stats)
561         expected = [16, 26, 36, 46, 56, 66, 76, 86, 96, 106, 116, 126]
562         result = prox.port_stats([3, 4, 5])
563         self.assertEqual(result, expected)
564
565     def test_measure_tot_stats(self, mock_time):
566         start_tot = 3, 4, 5, 6
567         end_tot = 7, 9, 11, 13
568         delta_tot = 4, 5, 6, 7
569
570         get_data_output = [
571             ','.join(str(n) for n in start_tot),
572             ','.join(str(n) for n in end_tot),
573         ]
574
575         mock_socket = mock.MagicMock()
576         prox = ProxSocketHelper(mock_socket)
577         prox.get_data = mock.MagicMock(side_effect=get_data_output)
578         expected = {
579             'start_tot': start_tot,
580             'end_tot': end_tot,
581             'delta': delta_tot,
582         }
583         with prox.measure_tot_stats() as result:
584             pass
585         self.assertEqual(result, expected)
586
587     def test_tot_stats(self, mock_time):
588         mock_socket = mock.MagicMock()
589         prox = ProxSocketHelper(mock_socket)
590         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
591         expected = 3, 4, 5
592         result = prox.tot_stats()
593         self.assertEqual(result, expected)
594
595     def test_tot_ierrors(self, mock_time):
596         mock_socket = mock.MagicMock()
597         prox = ProxSocketHelper(mock_socket)
598         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
599         expected = 3, 3
600         result = prox.tot_ierrors()
601         self.assertEqual(result, expected)
602
603     def test_set_count(self, mock_time):
604         mock_socket = mock.MagicMock()
605         prox = ProxSocketHelper(mock_socket)
606         prox.set_count(432, [3, 4, 5])
607         self.assertEqual(mock_socket.sendall.call_count, 3)
608
609     def test_dump_rx(self, mock_time):
610         mock_socket = mock.MagicMock()
611         prox = ProxSocketHelper(mock_socket)
612         prox.dump_rx(3, 5, 8)
613         self.assertEqual(mock_socket.sendall.call_count, 1)
614
615     def test_quit(self, mock_time):
616         mock_socket = mock.MagicMock()
617         prox = ProxSocketHelper(mock_socket)
618         prox.quit()
619         mock_socket.sendall.assert_called()
620
621     def test_force_quit(self, mock_time):
622         mock_socket = mock.MagicMock()
623         prox = ProxSocketHelper(mock_socket)
624         prox.force_quit()
625         mock_socket.sendall.assert_called()
626
627
628 class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
629
630     def test_rebind_drivers(self):
631         def find_drivers(*args, **kwargs):
632             setup_helper.used_drivers = used_drivers
633
634         used_drivers = {
635             'a': (1, 'b'),
636             'c': (2, 'd'),
637         }
638
639         vnfd_helper = mock.MagicMock()
640         ssh_helper = mock.MagicMock()
641         scenario_helper = mock.MagicMock()
642         setup_helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
643         setup_helper._find_used_drivers = mock_find = mock.MagicMock(side_effect=find_drivers)
644
645         setup_helper.rebind_drivers()
646         self.assertEqual(mock_find.call_count, 1)
647         self.assertEqual(ssh_helper.execute.call_count, 2)
648         self.assertIn('--force', ssh_helper.execute.call_args[0][0])
649
650         mock_find.reset_mock()
651         ssh_helper.execute.reset_mock()
652         setup_helper.rebind_drivers(False)
653         self.assertEqual(mock_find.call_count, 0)
654         self.assertEqual(ssh_helper.execute.call_count, 2)
655         self.assertNotIn('--force', ssh_helper.execute.call_args[0][0])
656
657
658 class TestProxResourceHelper(unittest.TestCase):
659
660     def test__replace_quoted_with_value(self):
661         # empty string
662         input_str = ''
663         expected = ''
664         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat')
665         self.assertEqual(result, expected)
666
667         # no quoted substring
668         input_str = 'lion tiger bear'
669         expected = 'lion tiger bear'
670         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat')
671         self.assertEqual(result, expected)
672
673         # partially quoted substring
674         input_str = 'lion "tiger bear'
675         expected = 'lion "tiger bear'
676         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat')
677         self.assertEqual(result, expected)
678
679         # one quoted substring
680         input_str = 'lion "tiger" bear'
681         expected = 'lion "cat" bear'
682         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat')
683         self.assertEqual(result, expected)
684
685         # two quoted substrings
686         input_str = 'lion "tiger" bear "shark" whale'
687         expected = 'lion "cat" bear "shark" whale'
688         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat')
689         self.assertEqual(result, expected)
690
691         # two quoted substrings, both replaced
692         input_str = 'lion "tiger" bear "shark" whale'
693         expected = 'lion "cat" bear "cat" whale'
694         result = ProxResourceHelper._replace_quoted_with_value(input_str, 'cat', 2)
695         self.assertEqual(result, expected)
696
697     def test__get_tx_port(self):
698         # no data
699         input_data = {'section1': []}
700         expected = -1
701         result = ProxResourceHelper._get_tx_port('section1', input_data)
702         self.assertEqual(result, expected)
703
704         # data for other section
705         input_data = {
706             'section1': [],
707             'section2': [
708                 ('rx port', '3'),
709                 ('tx port', '4'),
710             ],
711         }
712         expected = -1
713         result = ProxResourceHelper._get_tx_port('section1', input_data)
714         self.assertEqual(result, expected)
715
716         # data for section
717         input_data['section1'] = section1 = [
718             ('rx port', '4', 'more', 432),
719             ('tx port', '3'),
720         ]
721         expected = 3
722         result = ProxResourceHelper._get_tx_port('section1', input_data)
723         self.assertEqual(result, expected)
724
725         # more data for section,
726         section1.extend([
727             ('rx port', '2'),
728             ('tx port', '1', 'and more', 234),
729         ])
730         expected = 1
731         result = ProxResourceHelper._get_tx_port('section1', input_data)
732         self.assertEqual(result, expected)
733
734     def test_line_rate_to_pps(self):
735         expected = 0.25 * 1e8
736         result = ProxResourceHelper.line_rate_to_pps(180, 4)
737         self.assertEqual(result, expected)
738
739     def test_find_pci(self):
740         input_str_list = [
741             'no target here',
742             'nor here',
743             'and still not',
744         ]
745         result = ProxResourceHelper.find_pci('target', input_str_list)
746         self.assertFalse(result)
747
748         input_str_list = [
749             'no target here',
750             'nor here',
751             'this is a target',
752             'did we miss it',
753         ]
754         result = ProxResourceHelper.find_pci('target', input_str_list)
755         self.assertTrue(result)
756
757     def test_write_prox_config(self):
758         input_data = {}
759         expected = ''
760         result = ProxResourceHelper.write_prox_config(input_data)
761         self.assertEqual(result, expected)
762
763         input_data = {
764             'section1': [],
765         }
766         expected = '[section1]'
767         result = ProxResourceHelper.write_prox_config(input_data)
768         self.assertEqual(result, expected)
769
770         input_data = OrderedDict([
771             ('section1', []),
772             (
773                 'section2', [
774                     ('key1', 'value1'),
775                     ('__name__', 'not this one'),
776                     ('key2', None),
777                     ('key3', 234),
778                     ('key4', 'multi-line\nvalue'),
779                 ]
780             )
781         ])
782         expected = os.linesep.join([
783             '[section1]',
784             '[section2]',
785             'key1=value1',
786             'key2',
787             'key3=234',
788             'key4=multi-line\n\tvalue',
789         ])
790         result = ProxResourceHelper.write_prox_config(input_data)
791         self.assertEqual(result, expected)
792
793     def test_sut(self):
794         helper = ProxResourceHelper(mock.MagicMock())
795         self.assertIsNone(helper.client)
796         result = helper.sut
797         self.assertIsNotNone(result)
798         self.assertIs(result, helper.client)
799         self.assertIs(result, helper.sut)
800
801     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.SocketTopology')
802     def test_cpu_topology(self, mock_socket_topology):
803         mock_socket_topology.parse_cpuinfo.return_value = 432
804
805         setup_helper = mock.MagicMock()
806         setup_helper.ssh_helper.execute.return_value = 0, 'output', ''
807
808         helper = ProxResourceHelper(setup_helper)
809         self.assertIsNone(helper._cpu_topology)
810         result = helper.cpu_topology
811         self.assertEqual(result, 432)
812         self.assertIs(result, helper._cpu_topology)
813         self.assertIs(result, helper.cpu_topology)
814
815     def test_vpci_to_if_name_map(self):
816         setup_helper = mock.MagicMock()
817         setup_helper.vnfd_helper.interfaces = []
818
819         helper = ProxResourceHelper(setup_helper)
820         self.assertIsNone(helper._vpci_to_if_name_map)
821         result = helper.vpci_to_if_name_map
822         self.assertEqual(result, {})
823         self.assertIs(result, helper._vpci_to_if_name_map)
824         self.assertIs(result, helper.vpci_to_if_name_map)
825
826         setup_helper.vnfd_helper.interfaces = [
827             {
828                 'name': 'vnf1',
829                 'virtual-interface': {
830                     'vpci': '0000:01.02.03',
831                 },
832             },
833             {
834                 'name': 'vnf2',
835                 'virtual-interface': {
836                     'vpci': '0000:04.05.06',
837                 },
838             },
839         ]
840         expected = {
841             '0000:01.02.03': 'vnf1',
842             '0000:04.05.06': 'vnf2',
843         }
844         helper = ProxResourceHelper(setup_helper)
845         self.assertIsNone(helper._vpci_to_if_name_map)
846         result = helper.vpci_to_if_name_map
847         self.assertDictEqual(result, expected)
848         self.assertIs(result, helper._vpci_to_if_name_map)
849         self.assertIs(result, helper.vpci_to_if_name_map)
850
851     def test_test_cores(self):
852         setup_helper = mock.MagicMock()
853         helper = ProxResourceHelper(setup_helper)
854         helper.prox_config_dict = {}
855         helper._cpu_topology = []
856
857         expected = []
858         result = helper.test_cores
859         self.assertEqual(result, expected)
860
861         helper = ProxResourceHelper(setup_helper)
862         helper.prox_config_dict = OrderedDict([
863             ('section1', []),
864             ('section2', [
865                 ('a', 'b'),
866                 ('c', 'd'),
867             ]),
868             ('core 1s3', []),
869             ('core 2s5', [
870                 ('index', 8),
871                 ('mode', ''),
872             ]),
873             ('core 3s1', [
874                 ('index', 5),
875                 ('mode', 'gen'),
876             ]),
877             ('core 4s9h', [
878                 ('index', 7),
879                 ('mode', 'gen'),
880             ]),
881         ])
882         helper._cpu_topology = {
883             1: {
884                 3: {
885                     'key1': (23, 32),
886                     'key2': (12, 21),
887                     'key3': (44, 33),
888                 },
889             },
890             9: {
891                 4: {
892                     'key1': (44, 32),
893                     'key2': (23, 21),
894                     'key3': (12, 33),
895                 },
896             },
897         }
898
899         self.assertIsNone(helper._test_cores)
900         expected = [12, 23]
901         result = helper.test_cores
902         self.assertEqual(result, expected)
903         self.assertIs(result, helper._test_cores)
904         self.assertIs(result, helper.test_cores)
905
906     def test_latency_cores(self):
907         setup_helper = mock.MagicMock()
908         helper = ProxResourceHelper(setup_helper)
909         helper.prox_config_dict = {}
910         helper._cpu_topology = []
911
912         expected = []
913         result = helper.latency_cores
914         self.assertEqual(result, expected)
915
916         helper = ProxResourceHelper(setup_helper)
917         helper.prox_config_dict = OrderedDict([
918             ('section1', []),
919             ('section2', [
920                 ('a', 'b'),
921                 ('c', 'd'),
922             ]),
923             ('core 1s3', []),
924             ('core 2s5', [
925                 ('index', 8),
926                 ('mode', ''),
927             ]),
928             ('core 3s1', [
929                 ('index', 5),
930                 ('mode', 'lat'),
931             ]),
932             ('core 4s9h', [
933                 ('index', 7),
934                 ('mode', 'lat'),
935             ]),
936         ])
937         helper._cpu_topology = {
938             1: {
939                 3: {
940                     'key1': (23, 32),
941                     'key2': (12, 21),
942                     'key3': (44, 33),
943                 },
944             },
945             9: {
946                 4: {
947                     'key1': (44, 32),
948                     'key2': (23, 21),
949                     'key3': (12, 33),
950                 },
951             },
952         }
953
954         self.assertIsNone(helper._latency_cores)
955         expected = [12, 23]
956         result = helper.latency_cores
957         self.assertEqual(result, expected)
958         self.assertIs(result, helper._latency_cores)
959         self.assertIs(result, helper.latency_cores)
960
961     def test_start_collect(self):
962         setup_helper = mock.MagicMock()
963         helper = ProxResourceHelper(setup_helper)
964         self.assertIsNone(helper.start_collect())
965
966     def test_terminate(self):
967         setup_helper = mock.MagicMock()
968         helper = ProxResourceHelper(setup_helper)
969         self.assertIsNone(helper.terminate())
970
971     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
972     def test_get_process_args_no_additional_file(self, mock_find_path):
973         vnf1 = {
974             'prox_args': 'c',
975             'prox_path': 'd',
976             'prox_config': 'e/f',
977         }
978
979         mock_find_path.side_effect = ['1', '2']
980         setup_helper = mock.MagicMock()
981         setup_helper.scenario_helper = ScenarioHelper('vnf1')
982         setup_helper.scenario_helper.scenario_cfg = {
983             'task_path': 'a/b',
984             'options': {
985                 'vnf1': vnf1,
986             },
987         }
988
989         helper = ProxResourceHelper(setup_helper)
990         helper.copy_to_target = mock.MagicMock(return_value='3')
991         helper.generate_prox_config_file = mock.MagicMock(return_value='4')
992         helper.upload_prox_config = mock.MagicMock(return_value='5')
993
994         expected = 'c', 'd', '5'
995         result = helper.get_process_args()
996         self.assertEqual(result, expected)
997         self.assertFalse(helper.additional_file)
998         self.assertIsNone(helper.remote_prox_file_name)
999
1000     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
1001     def test_get_process_args_additional_file(self, mock_find_path):
1002         vnf1 = {
1003             'prox_args': 'c',
1004             'prox_path': 'd',
1005             'prox_config': 'e/f',
1006             'prox_files': 'g/h',
1007         }
1008
1009         mock_find_path.side_effect = ['1', '2']
1010         setup_helper = mock.MagicMock()
1011         setup_helper.scenario_helper = ScenarioHelper('vnf1')
1012         setup_helper.scenario_helper.scenario_cfg = {
1013             'task_path': 'a/b',
1014             'options': {
1015                 'vnf1': vnf1,
1016             },
1017         }
1018
1019         helper = ProxResourceHelper(setup_helper)
1020         helper.copy_to_target = mock.MagicMock(return_value='33')
1021         helper.generate_prox_config_file = mock.MagicMock(return_value='44')
1022         helper.upload_prox_config = mock.MagicMock(return_value='55')
1023
1024         expected = 'c', 'd', '55'
1025         result = helper.get_process_args()
1026         self.assertEqual(result, expected)
1027         self.assertTrue(helper.additional_file)
1028         self.assertEqual(helper.remote_prox_file_name, '33')
1029
1030     def test_up_post(self):
1031         setup_helper = mock.MagicMock()
1032         helper = ProxResourceHelper(setup_helper)
1033         helper.client = expected = mock.MagicMock()
1034         result = helper.up_post()
1035         self.assertEqual(result, expected)
1036
1037     def test_execute(self):
1038         setup_helper = mock.MagicMock()
1039         helper = ProxResourceHelper(setup_helper)
1040         helper.client = mock.MagicMock()
1041
1042         expected = helper.client.my_command()
1043         result = helper.execute('my_command')
1044         self.assertEqual(result, expected)
1045
1046         helper.client = object()
1047
1048         result = helper.execute('my_command')
1049         self.assertIsNone(result)
1050
1051     def test_copy_to_target(self):
1052         setup_helper = mock.MagicMock()
1053         helper = ProxResourceHelper(setup_helper)
1054         expected = '/tmp/c'
1055         result = helper.copy_to_target('a/b', 'c')
1056         self.assertEqual(result, expected)
1057
1058     def test_upload_prox_config(self):
1059         setup_helper = mock.MagicMock()
1060         helper = ProxResourceHelper(setup_helper)
1061         helper.write_prox_config = mock.MagicMock(return_value='a long string')
1062         expected = '/tmp/a'
1063         result = helper.upload_prox_config('a', {})
1064         self.assertEqual(result, expected)
1065
1066     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
1067     def test_run_test(self, mock_time):
1068         @contextmanager
1069         def measure(*args, **kwargs):
1070             yield stats
1071
1072         setup_helper = mock.MagicMock()
1073         setup_helper.vnfd_helper.interfaces = []
1074
1075         stats = {
1076             'delta': TotStatsTuple(6, 7, 8, 9),
1077         }
1078
1079         client = mock.MagicMock()
1080         client.hz.return_value = 2
1081         client.measure_tot_stats = measure
1082         client.port_stats.return_value = tuple(range(12))
1083
1084         helper = ProxResourceHelper(setup_helper)
1085         helper.client = client
1086         helper.get_latency = mock.MagicMock(return_value=[3.3, 3.6, 3.8])
1087
1088         with self.assertRaises(AssertionError):
1089             helper.run_test(980, 15, 45)
1090
1091         setup_helper.vnfd_helper.interfaces = ['a', 'b', 'c', 'd']
1092         helper._test_cores = [3, 4]
1093
1094         expected = ProxTestDataTuple(0.0, 2.0, 6, 7, 8, [3.3, 3.6, 3.8], 6, 7, 1.3e7)
1095         result = helper.run_test(230, 60, 65)
1096         self.assertEqual(result, expected)
1097
1098     def test_generate_prox_lua_file(self):
1099         setup_helper = mock.MagicMock()
1100         setup_helper.vnfd_helper.interfaces = []
1101
1102         helper = ProxResourceHelper(setup_helper)
1103         helper.LUA_PARAMETER_NAME = 'sut'
1104
1105         expected = ''
1106         result = helper.generate_prox_lua_file()
1107         self.assertEqual(result, expected)
1108
1109         setup_helper.vnfd_helper.interfaces = [
1110             {
1111                 'local_ip': '10.20.30.40',
1112                 'dst_ip': '10.11.12.13',
1113                 'virtual-interface': {
1114                     'dpdk_port_num': 3,
1115                 },
1116             },
1117             {
1118                 'local_ip': '10.20.30.45',
1119                 'dst_ip': '10.11.12.19',
1120                 'virtual-interface': {
1121                     'dpdk_port_num': 7,
1122                 },
1123             },
1124         ]
1125
1126         expected = os.linesep.join([
1127             'sut_hex_ip_port_3:"0a 14 1e 28"',
1128             'sut_ip_port_3:"10.20.30.40"',
1129             'gen_hex_ip_port_3:"0a 0b 0c 0d"',
1130             'gen_ip_port_3:"10.11.12.13"',
1131
1132             'sut_hex_ip_port_7:"0a 14 1e 2d"',
1133             'sut_ip_port_7:"10.20.30.45"',
1134             'gen_hex_ip_port_7:"0a 0b 0c 13"',
1135             'gen_ip_port_7:"10.11.12.19"',
1136         ])
1137         result = helper.generate_prox_lua_file()
1138         self.assertEqual(result, expected)
1139
1140     def test_upload_prox_lua(self):
1141         def identity(*args):
1142             return args
1143
1144         setup_helper = mock.MagicMock()
1145         setup_helper.vnfd_helper.interfaces = []
1146
1147         helper = ProxResourceHelper(setup_helper)
1148         helper.generate_prox_lua_file = mock.MagicMock(return_value=234)
1149         helper.put_string_to_file = identity
1150
1151         expected = ''
1152         result = helper.upload_prox_lua('my_dir', {})
1153         self.assertEqual(result, expected)
1154
1155         input_data = {
1156             'lua': {
1157                 'key1': 'value1 ("inside") tail',
1158                 'key2': 'value2',
1159                 'key3 ("key_side") head': 'value3',
1160             },
1161         }
1162
1163         expected = 234, 'my_dir/key_side'
1164         result = helper.upload_prox_lua('my_dir', input_data)
1165         self.assertEqual(result, expected)
1166
1167     def test_put_string_to_file(self):
1168         setup_helper = mock.MagicMock()
1169         setup_helper.vnfd_helper.interfaces = []
1170
1171         helper = ProxResourceHelper(setup_helper)
1172
1173         expected = 'a/b'
1174         result = helper.put_string_to_file('my long string', 'a/b')
1175         self.assertEqual(result, expected)
1176
1177     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ConfigParser')
1178     def test_generate_prox_config_file(self, mock_parser_type):
1179         def init(*args):
1180             args[-1].update(sections_data)
1181             return mock.MagicMock()
1182
1183         sections_data = {}
1184
1185         mock_parser_type.side_effect = init
1186
1187         setup_helper = mock.MagicMock()
1188         setup_helper.vnfd_helper.interfaces = []
1189
1190         helper = ProxResourceHelper(setup_helper)
1191         helper.additional_file = False
1192
1193         expected = {}
1194         result = helper.generate_prox_config_file('a/b')
1195         self.assertEqual(result, expected)
1196
1197         helper.additional_file = True
1198         helper.remote_prox_file_name = 'remote'
1199         setup_helper.vnfd_helper.interfaces = [
1200             {
1201                 'virtual-interface': {
1202                     'dpdk_port_num': 3,
1203                     'dst_mac': '00:00:00:de:ad:88',
1204                 },
1205             },
1206             {
1207                 'virtual-interface': {
1208                     'dpdk_port_num': 5,
1209                     'dst_mac': '00:00:00:de:ad:ff',
1210                 },
1211             },
1212             {
1213                 'virtual-interface': {
1214                     'dpdk_port_num': 7,
1215                     'dst_mac': '00:00:00:de:ad:ff',
1216                 },
1217             },
1218         ]
1219         sections_data = {
1220             'port 3': [
1221                 ['ip', ''],
1222                 ['mac', 'foo'],
1223                 ['dst mac', ''],
1224                 ['tx port', '1'],
1225             ],
1226             'port 5': [
1227                 ['ip', ''],
1228                 ['dst mac', ''],
1229                 ['tx port', '0'],
1230                 ['single'],
1231                 ['???', 'dofile "here" 23'],
1232             ],
1233         }
1234
1235         expected = {
1236             'port 3': [
1237                 ['ip', ''],
1238                 ['mac', 'hardware'],
1239                 ['dst mac', '00:00:00:de:ad:ff'],
1240                 ['tx port', '1'],
1241             ],
1242             'port 5': [
1243                 ['ip', ''],
1244                 ['dst mac', '00:00:00:de:ad:88'],
1245                 ['tx port', '0'],
1246                 ['single'],
1247                 ['???', 'dofile "remote" 23'],
1248             ],
1249         }
1250         result = helper.generate_prox_config_file('a/b')
1251         self.assertDictEqual(result, expected)
1252
1253     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ConfigParser')
1254     def test_generate_prox_config_file_negative(self, mock_parser_type):
1255         def init(*args):
1256             args[-1].update(sections_data)
1257             return mock.MagicMock()
1258
1259         sections_data = {}
1260
1261         mock_parser_type.side_effect = init
1262
1263         setup_helper = mock.MagicMock()
1264         setup_helper.vnfd_helper.interfaces = []
1265
1266         helper = ProxResourceHelper(setup_helper)
1267         helper.additional_file = False
1268         helper.remote_prox_file_name = 'remote'
1269         setup_helper.vnfd_helper.interfaces = [
1270             {
1271                 'virtual-interface': {
1272                     'dpdk_port_num': 3,
1273                     'dst_mac': '00:00:00:de:ad:88',
1274                 },
1275             },
1276             {
1277                 'virtual-interface': {
1278                     'dpdk_port_num': 5,
1279                     'dst_mac': '00:00:00:de:ad:ff',
1280                 },
1281             },
1282             {
1283                 'virtual-interface': {
1284                     'dpdk_port_num': 7,
1285                     'dst_mac': '00:00:00:de:ad:ff',
1286                 },
1287             },
1288         ]
1289         sections_data = {
1290             'port 3': [
1291                 ['ip', ''],
1292                 ['mac', 'foo'],
1293                 ['dst mac', ''],
1294             ],
1295             'port 5': [
1296                 ['ip', ''],
1297                 ['dst mac', ''],
1298                 ['tx port', '0'],
1299                 ['???', 'dofile "here" 23'],
1300             ],
1301         }
1302
1303         with self.assertRaises(Exception):
1304             helper.generate_prox_config_file('a/b')
1305
1306     def test_get_latency(self):
1307         setup_helper = mock.MagicMock()
1308         setup_helper.vnfd_helper.interfaces = []
1309
1310         helper = ProxResourceHelper(setup_helper)
1311         helper._latency_cores = []
1312
1313         expected = []
1314         result = helper.get_latency()
1315         self.assertEqual(result, expected)
1316
1317         helper._latency_cores = [1, 2]
1318         helper.client = mock.MagicMock()
1319
1320         expected = helper.sut.lat_stats()
1321         result = helper.get_latency()
1322         self.assertIs(result, expected)
1323
1324     def test__get_logical_if_name(self):
1325         setup_helper = mock.MagicMock()
1326         setup_helper.vnfd_helper.interfaces = []
1327
1328         helper = ProxResourceHelper(setup_helper)
1329         helper._vpci_to_if_name_map = {
1330             'key1': 234,
1331             'key2': 432,
1332         }
1333
1334         expected = 234
1335         result = helper._get_logical_if_name('key1')
1336         self.assertEqual(result, expected)
1337
1338     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
1339     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ProxSocketHelper')
1340     def test__connect(self, mock_socket_helper_type, mock_time):
1341         client = mock_socket_helper_type()
1342         client.connect.side_effect = chain(repeat(socket.error, 5), [None])
1343
1344         setup_helper = mock.MagicMock()
1345         setup_helper.vnfd_helper.interfaces = []
1346
1347         helper = ProxResourceHelper(setup_helper)
1348
1349         result = helper._connect()
1350         self.assertIs(result, client)
1351
1352         client.connect.side_effect = chain(repeat(socket.error, 65), [None])
1353
1354         with self.assertRaises(Exception):
1355             helper._connect()