Merge "Define several containers per pod in a replication controller"
[yardstick.git] / yardstick / tests / unit / common / test_utils.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 from copy import deepcopy
11 import errno
12 import importlib
13 import ipaddress
14 from itertools import product, chain
15 import mock
16 import os
17 import six
18 from six.moves import configparser
19 import time
20 import unittest
21
22 import yardstick
23 from yardstick import ssh
24 from yardstick.common import constants
25 from yardstick.common import utils
26 from yardstick.common import exceptions
27 from yardstick.tests.unit import base as ut_base
28
29
30 class IterSubclassesTestCase(ut_base.BaseUnitTestCase):
31     # Disclaimer: this class is a modified copy from
32     # rally/tests/unit/common/plugin/test_discover.py
33     # Copyright 2015: Mirantis Inc.
34
35     def test_itersubclasses(self):
36         class A(object):
37             pass
38
39         class B(A):
40             pass
41
42         class C(A):
43             pass
44
45         class D(C):
46             pass
47
48         self.assertEqual([B, C, D], list(utils.itersubclasses(A)))
49
50
51 class ImportModulesFromPackageTestCase(ut_base.BaseUnitTestCase):
52
53     @mock.patch('yardstick.common.utils.os.walk')
54     def test_import_modules_from_package_no_mod(self, mock_walk):
55         yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__))
56         mock_walk.return_value = ([
57             (os.path.join(yardstick_root, 'foo'), ['bar'], ['__init__.py']),
58             (os.path.join(yardstick_root, 'foo', 'bar'), [], ['baz.txt', 'qux.rst'])
59         ])
60
61         utils.import_modules_from_package('foo.bar')
62
63     @mock.patch('yardstick.common.utils.os.walk')
64     @mock.patch.object(importlib, 'import_module')
65     def test_import_modules_from_package(self, mock_import_module, mock_walk):
66
67         yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__))
68         mock_walk.return_value = ([
69             (os.path.join(yardstick_root, 'foo', os.pardir, 'bar'), [], ['baz.py'])
70         ])
71
72         utils.import_modules_from_package('foo.bar')
73         mock_import_module.assert_called_once_with('bar.baz')
74
75
76 class GetParaFromYaml(ut_base.BaseUnitTestCase):
77
78     @mock.patch('yardstick.common.utils.os.environ.get')
79     def test_get_param_para_not_found(self, get_env):
80         file_path = 'config_sample.yaml'
81         get_env.return_value = self._get_file_abspath(file_path)
82         args = 'releng.file'
83         default = 'hello'
84         self.assertTrue(constants.get_param(args, default), default)
85
86     @mock.patch('yardstick.common.utils.os.environ.get')
87     def test_get_param_para_exists(self, get_env):
88         file_path = 'config_sample.yaml'
89         get_env.return_value = self._get_file_abspath(file_path)
90         args = 'releng.dir'
91         para = '/home/opnfv/repos/releng'
92         self.assertEqual(para, constants.get_param(args))
93
94     def _get_file_abspath(self, filename):
95         curr_path = os.path.dirname(os.path.abspath(__file__))
96         file_path = os.path.join(curr_path, filename)
97         return file_path
98
99
100 class CommonUtilTestCase(ut_base.BaseUnitTestCase):
101
102     def setUp(self):
103         self.data = {
104             "benchmark": {
105                 "data": {
106                     "mpstat": {
107                         "cpu0": {
108                             "%sys": "0.00",
109                             "%idle": "99.00"
110                         },
111                         "loadavg": [
112                             "1.09",
113                             "0.29"
114                         ]
115                     },
116                     "rtt": "1.03"
117                 }
118             }
119         }
120
121     def test__dict_key_flatten(self):
122         line = 'mpstat.loadavg1=0.29,rtt=1.03,mpstat.loadavg0=1.09,' \
123                'mpstat.cpu0.%idle=99.00,mpstat.cpu0.%sys=0.00'
124         # need to sort for assert to work
125         line = ",".join(sorted(line.split(',')))
126         flattened_data = utils.flatten_dict_key(
127             self.data['benchmark']['data'])
128         result = ",".join(
129             ("=".join(item) for item in sorted(flattened_data.items())))
130         self.assertEqual(result, line)
131
132     def test_get_key_with_default_negative(self):
133         with self.assertRaises(KeyError):
134             utils.get_key_with_default({}, 'key1')
135
136     @mock.patch('yardstick.common.utils.open', create=True)
137     def test_(self, mock_open):
138         mock_open.side_effect = IOError
139
140         with self.assertRaises(IOError):
141             utils.find_relative_file('my/path', 'task/path')
142
143         self.assertEqual(mock_open.call_count, 2)
144
145     @mock.patch('yardstick.common.utils.open', create=True)
146     def test_open_relative_path(self, mock_open):
147         mock_open_result = mock_open()
148         mock_open_call_count = 1  # initial call to get result
149
150         self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
151
152         mock_open_call_count += 1  # one more call expected
153         self.assertEqual(mock_open.call_count, mock_open_call_count)
154         self.assertIn('foo', mock_open.call_args_list[-1][0][0])
155         self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
156
157         def open_effect(*args, **kwargs):
158             if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
159                 return mock_open_result
160             raise IOError(errno.ENOENT, 'not found')
161
162         mock_open.side_effect = open_effect
163         self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
164
165         mock_open_call_count += 2  # two more calls expected
166         self.assertEqual(mock_open.call_count, mock_open_call_count)
167         self.assertIn('foo', mock_open.call_args_list[-1][0][0])
168         self.assertIn('bar', mock_open.call_args_list[-1][0][0])
169
170         # test an IOError of type ENOENT
171         mock_open.side_effect = IOError(errno.ENOENT, 'not found')
172         with self.assertRaises(IOError):
173             # the second call still raises
174             utils.open_relative_file('foo', 'bar')
175
176         mock_open_call_count += 2  # two more calls expected
177         self.assertEqual(mock_open.call_count, mock_open_call_count)
178         self.assertIn('foo', mock_open.call_args_list[-1][0][0])
179         self.assertIn('bar', mock_open.call_args_list[-1][0][0])
180
181         # test an IOError other than ENOENT
182         mock_open.side_effect = IOError(errno.EBUSY, 'busy')
183         with self.assertRaises(IOError):
184             utils.open_relative_file('foo', 'bar')
185
186         mock_open_call_count += 1  # one more call expected
187         self.assertEqual(mock_open.call_count, mock_open_call_count)
188
189
190 class TestMacAddressToHex(ut_base.BaseUnitTestCase):
191
192     def test_mac_address_to_hex_list(self):
193         self.assertEqual(utils.mac_address_to_hex_list("ea:3e:e1:9a:99:e8"),
194                          ['0xea', '0x3e', '0xe1', '0x9a', '0x99', '0xe8'])
195
196
197 class TranslateToStrTestCase(ut_base.BaseUnitTestCase):
198
199     def test_translate_to_str_unicode(self):
200         input_str = u'hello'
201         output_str = utils.translate_to_str(input_str)
202
203         result = 'hello'
204         self.assertEqual(result, output_str)
205
206     def test_translate_to_str_dict_list_unicode(self):
207         input_str = {
208             u'hello': {u'hello': [u'world']}
209         }
210         output_str = utils.translate_to_str(input_str)
211
212         result = {
213             'hello': {'hello': ['world']}
214         }
215         self.assertEqual(result, output_str)
216
217     def test_translate_to_str_non_string(self):
218         input_value = object()
219         result = utils.translate_to_str(input_value)
220         self.assertIs(input_value, result)
221
222
223 class TestParseCpuInfo(ut_base.BaseUnitTestCase):
224
225     def test_single_socket_no_hyperthread(self):
226         cpuinfo = """\
227 processor       : 2
228 vendor_id       : GenuineIntel
229 cpu family      : 6
230 model           : 60
231 model name      : Intel Core Processor (Haswell, no TSX)
232 stepping        : 1
233 microcode       : 0x1
234 cpu MHz         : 2294.684
235 cache size      : 4096 KB
236 physical id     : 0
237 siblings        : 5
238 core id         : 2
239 cpu cores       : 5
240 apicid          : 2
241 initial apicid  : 2
242 fpu             : yes
243 fpu_exception   : yes
244 cpuid level     : 13
245 wp              : yes
246 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
247 bugs            :
248 bogomips        : 4589.36
249 clflush size    : 64
250 cache_alignment : 64
251 address sizes   : 46 bits physical, 48 bits virtual
252 power management:
253
254 processor       : 3
255 vendor_id       : GenuineIntel
256 cpu family      : 6
257 model           : 60
258 model name      : Intel Core Processor (Haswell, no TSX)
259 stepping        : 1
260 microcode       : 0x1
261 cpu MHz         : 2294.684
262 cache size      : 4096 KB
263 physical id     : 0
264 siblings        : 5
265 core id         : 3
266 cpu cores       : 5
267 apicid          : 3
268 initial apicid  : 3
269 fpu             : yes
270 fpu_exception   : yes
271 cpuid level     : 13
272 wp              : yes
273 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
274 bugs            :
275 bogomips        : 4589.36
276 clflush size    : 64
277 cache_alignment : 64
278 address sizes   : 46 bits physical, 48 bits virtual
279 power management:
280
281 processor       : 4
282 vendor_id       : GenuineIntel
283 cpu family      : 6
284 model           : 60
285 model name      : Intel Core Processor (Haswell, no TSX)
286 stepping        : 1
287 microcode       : 0x1
288 cpu MHz         : 2294.684
289 cache size      : 4096 KB
290 physical id     : 0
291 siblings        : 5
292 core id         : 4
293 cpu cores       : 5
294 apicid          : 4
295 initial apicid  : 4
296 fpu             : yes
297 fpu_exception   : yes
298 cpuid level     : 13
299 wp              : yes
300 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
301 bugs            :
302 bogomips        : 4589.36
303 clflush size    : 64
304 cache_alignment : 64
305 address sizes   : 46 bits physical, 48 bits virtual
306 power management:
307
308 """
309         socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
310         self.assertEqual(sorted(socket_map.keys()), [0])
311         self.assertEqual(sorted(socket_map[0].keys()), [2, 3, 4])
312
313     def test_single_socket_hyperthread(self):
314         cpuinfo = """\
315 processor       : 5
316 vendor_id       : GenuineIntel
317 cpu family      : 6
318 model           : 60
319 model name      : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
320 stepping        : 3
321 microcode       : 0x1d
322 cpu MHz         : 3501.708
323 cache size      : 8192 KB
324 physical id     : 0
325 siblings        : 8
326 core id         : 1
327 cpu cores       : 4
328 apicid          : 3
329 initial apicid  : 3
330 fpu             : yes
331 fpu_exception   : yes
332 cpuid level     : 13
333 wp              : yes
334 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
335 bugs            :
336 bogomips        : 6987.36
337 clflush size    : 64
338 cache_alignment : 64
339 address sizes   : 39 bits physical, 48 bits virtual
340 power management:
341
342 processor       : 6
343 vendor_id       : GenuineIntel
344 cpu family      : 6
345 model           : 60
346 model name      : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
347 stepping        : 3
348 microcode       : 0x1d
349 cpu MHz         : 3531.829
350 cache size      : 8192 KB
351 physical id     : 0
352 siblings        : 8
353 core id         : 2
354 cpu cores       : 4
355 apicid          : 5
356 initial apicid  : 5
357 fpu             : yes
358 fpu_exception   : yes
359 cpuid level     : 13
360 wp              : yes
361 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
362 bugs            :
363 bogomips        : 6987.36
364 clflush size    : 64
365 cache_alignment : 64
366 address sizes   : 39 bits physical, 48 bits virtual
367 power management:
368
369 processor       : 7
370 vendor_id       : GenuineIntel
371 cpu family      : 6
372 model           : 60
373 model name      : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
374 stepping        : 3
375 microcode       : 0x1d
376 cpu MHz         : 3500.213
377 cache size      : 8192 KB
378 physical id     : 0
379 siblings        : 8
380 core id         : 3
381 cpu cores       : 4
382 apicid          : 7
383 initial apicid  : 7
384 fpu             : yes
385 fpu_exception   : yes
386 cpuid level     : 13
387 wp              : yes
388 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
389 bugs            :
390 bogomips        : 6987.24
391 clflush size    : 64
392 cache_alignment : 64
393 address sizes   : 39 bits physical, 48 bits virtual
394 power management:
395
396 """
397         socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
398         self.assertEqual(sorted(socket_map.keys()), [0])
399         self.assertEqual(sorted(socket_map[0].keys()), [1, 2, 3])
400         self.assertEqual(sorted(socket_map[0][1]), [5])
401         self.assertEqual(sorted(socket_map[0][2]), [6])
402         self.assertEqual(sorted(socket_map[0][3]), [7])
403
404     def test_dual_socket_hyperthread(self):
405         cpuinfo = """\
406 processor       : 1
407 vendor_id       : GenuineIntel
408 cpu family      : 6
409 model           : 79
410 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
411 stepping        : 1
412 microcode       : 0xb00001f
413 cpu MHz         : 1200.976
414 cache size      : 56320 KB
415 physical id     : 0
416 siblings        : 44
417 core id         : 1
418 cpu cores       : 22
419 apicid          : 2
420 initial apicid  : 2
421 fpu             : yes
422 fpu_exception   : yes
423 cpuid level     : 20
424 wp              : yes
425 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
426 bugs            :
427 bogomips        : 4401.07
428 clflush size    : 64
429 cache_alignment : 64
430 address sizes   : 46 bits physical, 48 bits virtual
431 power management:
432
433 processor       : 2
434 vendor_id       : GenuineIntel
435 cpu family      : 6
436 model           : 79
437 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
438 stepping        : 1
439 microcode       : 0xb00001f
440 cpu MHz         : 1226.892
441 cache size      : 56320 KB
442 physical id     : 0
443 siblings        : 44
444 core id         : 2
445 cpu cores       : 22
446 apicid          : 4
447 initial apicid  : 4
448 fpu             : yes
449 fpu_exception   : yes
450 cpuid level     : 20
451 wp              : yes
452 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
453 bugs            :
454 bogomips        : 4400.84
455 clflush size    : 64
456 cache_alignment : 64
457 address sizes   : 46 bits physical, 48 bits virtual
458 power management:
459
460 processor       : 43
461 vendor_id       : GenuineIntel
462 cpu family      : 6
463 model           : 79
464 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
465 stepping        : 1
466 microcode       : 0xb00001f
467 cpu MHz         : 1200.305
468 cache size      : 56320 KB
469 physical id     : 1
470 siblings        : 44
471 core id         : 28
472 cpu cores       : 22
473 apicid          : 120
474 initial apicid  : 120
475 fpu             : yes
476 fpu_exception   : yes
477 cpuid level     : 20
478 wp              : yes
479 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
480 bugs            :
481 bogomips        : 4411.31
482 clflush size    : 64
483 cache_alignment : 64
484 address sizes   : 46 bits physical, 48 bits virtual
485 power management:
486
487 processor       : 44
488 vendor_id       : GenuineIntel
489 cpu family      : 6
490 model           : 79
491 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
492 stepping        : 1
493 microcode       : 0xb00001f
494 cpu MHz         : 1200.305
495 cache size      : 56320 KB
496 physical id     : 0
497 siblings        : 44
498 core id         : 0
499 cpu cores       : 22
500 apicid          : 1
501 initial apicid  : 1
502 fpu             : yes
503 fpu_exception   : yes
504 cpuid level     : 20
505 wp              : yes
506 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
507 bugs            :
508 bogomips        : 4410.61
509 clflush size    : 64
510 cache_alignment : 64
511 address sizes   : 46 bits physical, 48 bits virtual
512 power management:
513
514 processor       : 85
515 vendor_id       : GenuineIntel
516 cpu family      : 6
517 model           : 79
518 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
519 stepping        : 1
520 microcode       : 0xb00001f
521 cpu MHz         : 1200.573
522 cache size      : 56320 KB
523 physical id     : 1
524 siblings        : 44
525 core id         : 26
526 cpu cores       : 22
527 apicid          : 117
528 initial apicid  : 117
529 fpu             : yes
530 fpu_exception   : yes
531 cpuid level     : 20
532 wp              : yes
533 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
534 bugs            :
535 bogomips        : 4409.07
536 clflush size    : 64
537 cache_alignment : 64
538 address sizes   : 46 bits physical, 48 bits virtual
539 power management:
540
541 processor       : 86
542 vendor_id       : GenuineIntel
543 cpu family      : 6
544 model           : 79
545 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
546 stepping        : 1
547 microcode       : 0xb00001f
548 cpu MHz         : 1200.305
549 cache size      : 56320 KB
550 physical id     : 1
551 siblings        : 44
552 core id         : 27
553 cpu cores       : 22
554 apicid          : 119
555 initial apicid  : 119
556 fpu             : yes
557 fpu_exception   : yes
558 cpuid level     : 20
559 wp              : yes
560 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
561 bugs            :
562 bogomips        : 4406.62
563 clflush size    : 64
564 cache_alignment : 64
565 address sizes   : 46 bits physical, 48 bits virtual
566 power management:
567
568 processor       : 87
569 vendor_id       : GenuineIntel
570 cpu family      : 6
571 model           : 79
572 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
573 stepping        : 1
574 microcode       : 0xb00001f
575 cpu MHz         : 1200.708
576 cache size      : 56320 KB
577 physical id     : 1
578 siblings        : 44
579 core id         : 28
580 cpu cores       : 22
581 apicid          : 121
582 initial apicid  : 121
583 fpu             : yes
584 fpu_exception   : yes
585 cpuid level     : 20
586 wp              : yes
587 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
588 bugs            :
589 bogomips        : 4413.48
590 clflush size    : 64
591 cache_alignment : 64
592 address sizes   : 46 bits physical, 48 bits virtual
593 power management:
594
595 """
596         socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
597         self.assertEqual(sorted(socket_map.keys()), [0, 1])
598         self.assertEqual(sorted(socket_map[0].keys()), [0, 1, 2])
599         self.assertEqual(sorted(socket_map[1].keys()), [26, 27, 28])
600         self.assertEqual(sorted(socket_map[0][0]), [44])
601         self.assertEqual(sorted(socket_map[0][1]), [1])
602         self.assertEqual(sorted(socket_map[0][2]), [2])
603         self.assertEqual(sorted(socket_map[1][26]), [85])
604         self.assertEqual(sorted(socket_map[1][27]), [86])
605         self.assertEqual(sorted(socket_map[1][28]), [43, 87])
606
607     def test_dual_socket_no_hyperthread(self):
608         cpuinfo = """\
609 processor       : 1
610 vendor_id       : GenuineIntel
611 cpu family      : 6
612 model           : 79
613 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
614 stepping        : 1
615 microcode       : 0xb00001f
616 cpu MHz         : 1200.976
617 cache size      : 56320 KB
618 physical id     : 0
619 siblings        : 44
620 core id         : 1
621 cpu cores       : 22
622 apicid          : 2
623 initial apicid  : 2
624 fpu             : yes
625 fpu_exception   : yes
626 cpuid level     : 20
627 wp              : yes
628 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
629 bugs            :
630 bogomips        : 4401.07
631 clflush size    : 64
632 cache_alignment : 64
633 address sizes   : 46 bits physical, 48 bits virtual
634 power management:
635
636 processor       : 2
637 vendor_id       : GenuineIntel
638 cpu family      : 6
639 model           : 79
640 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
641 stepping        : 1
642 microcode       : 0xb00001f
643 cpu MHz         : 1226.892
644 cache size      : 56320 KB
645 physical id     : 0
646 siblings        : 44
647 core id         : 2
648 cpu cores       : 22
649 apicid          : 4
650 initial apicid  : 4
651 fpu             : yes
652 fpu_exception   : yes
653 cpuid level     : 20
654 wp              : yes
655 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
656 bugs            :
657 bogomips        : 4400.84
658 clflush size    : 64
659 cache_alignment : 64
660 address sizes   : 46 bits physical, 48 bits virtual
661 power management:
662
663 processor       : 43
664 vendor_id       : GenuineIntel
665 cpu family      : 6
666 model           : 79
667 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
668 stepping        : 1
669 microcode       : 0xb00001f
670 cpu MHz         : 1200.305
671 cache size      : 56320 KB
672 physical id     : 1
673 siblings        : 44
674 core id         : 28
675 cpu cores       : 22
676 apicid          : 120
677 initial apicid  : 120
678 fpu             : yes
679 fpu_exception   : yes
680 cpuid level     : 20
681 wp              : yes
682 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
683 bugs            :
684 bogomips        : 4411.31
685 clflush size    : 64
686 cache_alignment : 64
687 address sizes   : 46 bits physical, 48 bits virtual
688 power management:
689
690 processor       : 44
691 vendor_id       : GenuineIntel
692 cpu family      : 6
693 model           : 79
694 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
695 stepping        : 1
696 microcode       : 0xb00001f
697 cpu MHz         : 1200.305
698 cache size      : 56320 KB
699 physical id     : 0
700 siblings        : 44
701 core id         : 0
702 cpu cores       : 22
703 apicid          : 1
704 initial apicid  : 1
705 fpu             : yes
706 fpu_exception   : yes
707 cpuid level     : 20
708 wp              : yes
709 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
710 bugs            :
711 bogomips        : 4410.61
712 clflush size    : 64
713 cache_alignment : 64
714 address sizes   : 46 bits physical, 48 bits virtual
715 power management:
716
717 processor       : 85
718 vendor_id       : GenuineIntel
719 cpu family      : 6
720 model           : 79
721 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
722 stepping        : 1
723 microcode       : 0xb00001f
724 cpu MHz         : 1200.573
725 cache size      : 56320 KB
726 physical id     : 1
727 siblings        : 44
728 core id         : 26
729 cpu cores       : 22
730 apicid          : 117
731 initial apicid  : 117
732 fpu             : yes
733 fpu_exception   : yes
734 cpuid level     : 20
735 wp              : yes
736 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
737 bugs            :
738 bogomips        : 4409.07
739 clflush size    : 64
740 cache_alignment : 64
741 address sizes   : 46 bits physical, 48 bits virtual
742 power management:
743
744 processor       : 86
745 vendor_id       : GenuineIntel
746 cpu family      : 6
747 model           : 79
748 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
749 stepping        : 1
750 microcode       : 0xb00001f
751 cpu MHz         : 1200.305
752 cache size      : 56320 KB
753 physical id     : 1
754 siblings        : 44
755 core id         : 27
756 cpu cores       : 22
757 apicid          : 119
758 initial apicid  : 119
759 fpu             : yes
760 fpu_exception   : yes
761 cpuid level     : 20
762 wp              : yes
763 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
764 bugs            :
765 bogomips        : 4406.62
766 clflush size    : 64
767 cache_alignment : 64
768 address sizes   : 46 bits physical, 48 bits virtual
769 power management:
770
771 processor       : 87
772 vendor_id       : GenuineIntel
773 cpu family      : 6
774 model           : 79
775 model name      : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
776 stepping        : 1
777 microcode       : 0xb00001f
778 cpu MHz         : 1200.708
779 cache size      : 56320 KB
780 physical id     : 1
781 siblings        : 44
782 core id         : 28
783 cpu cores       : 22
784 apicid          : 121
785 initial apicid  : 121
786 fpu             : yes
787 fpu_exception   : yes
788 cpuid level     : 20
789 wp              : yes
790 flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
791 bugs            :
792 bogomips        : 4413.48
793 clflush size    : 64
794 cache_alignment : 64
795 address sizes   : 46 bits physical, 48 bits virtual
796 power management:
797
798 """
799         socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
800         processors = socket_map.processors()
801         self.assertEqual(processors, [1, 2, 43, 44, 85, 86, 87])
802         cores = socket_map.cores()
803         self.assertEqual(cores, [0, 1, 2, 26, 27, 28])
804         sockets = socket_map.sockets()
805         self.assertEqual(sockets, [0, 1])
806
807
808 class ChangeObjToDictTestCase(ut_base.BaseUnitTestCase):
809
810     def test_change_obj_to_dict(self):
811         class A(object):
812             def __init__(self):
813                 self.name = 'yardstick'
814
815         obj = A()
816         obj_r = utils.change_obj_to_dict(obj)
817         obj_s = {'name': 'yardstick'}
818         self.assertEqual(obj_r, obj_s)
819
820
821 class SetDictValueTestCase(ut_base.BaseUnitTestCase):
822
823     def test_set_dict_value(self):
824         input_dic = {
825             'hello': 'world'
826         }
827         output_dic = utils.set_dict_value(input_dic, 'welcome.to', 'yardstick')
828         self.assertEqual(output_dic.get('welcome', {}).get('to'), 'yardstick')
829
830
831 class RemoveFileTestCase(ut_base.BaseUnitTestCase):
832
833     def test_remove_file(self):
834         try:
835             utils.remove_file('notexistfile.txt')
836         except Exception as e:  # pylint: disable=broad-except
837             # NOTE(ralonsoh): to narrow the scope of this exception.
838             self.assertTrue(isinstance(e, OSError))
839
840
841 class ParseIniFileTestCase(ut_base.BaseUnitTestCase):
842
843     def setUp(self):
844         self._mock_config_parser_type = mock.patch.object(configparser,
845                                                           'ConfigParser')
846         self.mock_config_parser_type = self._mock_config_parser_type.start()
847         self.addCleanup(self._stop_mocks)
848
849     def _stop_mocks(self):
850         self._mock_config_parser_type.stop()
851
852     def test_parse_ini_file(self):
853         defaults = {'default1': 'value1',
854                     'default2': 'value2'}
855         s1 = {'key1': 'value11',
856               'key2': 'value22'}
857         s2 = {'key1': 'value123',
858               'key2': 'value234'}
859
860         mock_config_parser = mock.Mock()
861         self.mock_config_parser_type.return_value = mock_config_parser
862         mock_config_parser.read.return_value = True
863         mock_config_parser.sections.return_value = ['s1', 's2']
864         mock_config_parser.items.side_effect = iter([
865             defaults.items(),
866             s1.items(),
867             s2.items(),
868         ])
869
870         expected = {'DEFAULT': defaults,
871                     's1': s1,
872                     's2': s2}
873         result = utils.parse_ini_file('my_path')
874         self.assertDictEqual(expected, result)
875
876     @mock.patch.object(utils, 'logger')
877     def test_parse_ini_file_missing_section_header(self, *args):
878         mock_config_parser = mock.Mock()
879         self.mock_config_parser_type.return_value = mock_config_parser
880         mock_config_parser.read.side_effect = (
881             configparser.MissingSectionHeaderError(
882                 mock.Mock(), 321, mock.Mock()))
883
884         with self.assertRaises(configparser.MissingSectionHeaderError):
885             utils.parse_ini_file('my_path')
886
887     def test_parse_ini_file_no_file(self):
888         mock_config_parser = mock.Mock()
889         self.mock_config_parser_type.return_value = mock_config_parser
890         mock_config_parser.read.return_value = False
891         with self.assertRaises(RuntimeError):
892             utils.parse_ini_file('my_path')
893
894     def test_parse_ini_file_no_default_section_header(self):
895         s1 = {'key1': 'value11',
896               'key2': 'value22'}
897         s2 = {'key1': 'value123',
898               'key2': 'value234'}
899
900         mock_config_parser = mock.Mock()
901         self.mock_config_parser_type.return_value = mock_config_parser
902         mock_config_parser.read.return_value = True
903         mock_config_parser.sections.return_value = ['s1', 's2']
904         mock_config_parser.items.side_effect = iter([
905             configparser.NoSectionError(mock.Mock()),
906             s1.items(),
907             s2.items(),
908         ])
909
910         expected = {'DEFAULT': {},
911                     's1': s1,
912                     's2': s2}
913         result = utils.parse_ini_file('my_path')
914         self.assertDictEqual(expected, result)
915
916
917 class TestUtils(ut_base.BaseUnitTestCase):
918
919     @mock.patch('yardstick.common.utils.os.makedirs')
920     def test_makedirs(self, *_):
921         self.assertIsNone(utils.makedirs('a/b/c/d'))
922
923     @mock.patch('yardstick.common.utils.os.makedirs')
924     def test_makedirs_exists(self, mock_os_makedirs):
925         mock_os_makedirs.side_effect = OSError(errno.EEXIST, 'exists')
926         self.assertIsNone(utils.makedirs('a/b/c/d'))
927
928     @mock.patch('yardstick.common.utils.os.makedirs')
929     def test_makedirs_busy(self, mock_os_makedirs):
930         mock_os_makedirs.side_effect = OSError(errno.EBUSY, 'busy')
931         with self.assertRaises(OSError):
932             utils.makedirs('a/b/c/d')
933
934     @mock.patch('yardstick.common.utils.jsonify')
935     def test_result_handler(self, mock_jsonify):
936         mock_jsonify.return_value = 432
937
938         self.assertEqual(utils.result_handler('x', 234), 432)
939         mock_jsonify.assert_called_once_with({'status': 'x', 'result': 234})
940
941     @mock.patch('random.randint')
942     @mock.patch('socket.socket')
943     def test_get_free_port(self, mock_socket, mock_randint):
944         mock_randint.return_value = 7777
945         s = mock_socket('x', 'y')
946         s.connect_ex.side_effect = iter([0, 1])
947         result = utils.get_free_port('10.20.30.40')
948         self.assertEqual(result, 7777)
949         self.assertEqual(s.connect_ex.call_count, 2)
950
951     @mock.patch('subprocess.check_output')
952     def test_execute_command(self, mock_check_output):
953         expected = ['hello world', '1234']
954         mock_check_output.return_value = os.linesep.join(expected)
955         result = utils.execute_command('my_command arg1 arg2')
956         self.assertEqual(result, expected)
957
958     @mock.patch('subprocess.Popen')
959     def test_source_env(self, mock_popen):
960         base_env = deepcopy(os.environ)
961         mock_process = mock_popen()
962         output_list = [
963             'garbage line before',
964             'NEW_ENV_VALUE=234',
965             'garbage line after',
966         ]
967         mock_process.communicate.return_value = os.linesep.join(output_list), '', 0
968         expected = {'NEW_ENV_VALUE': '234'}
969         result = utils.source_env('my_file')
970         self.assertDictEqual(result, expected)
971         os.environ.clear()
972         os.environ.update(base_env)
973
974     @mock.patch.object(configparser, 'ConfigParser')
975     def test_parse_ini_file(self, mock_config_parser_type):
976         defaults = {
977             'default1': 'value1',
978             'default2': 'value2',
979         }
980         s1 = {
981             'key1': 'value11',
982             'key2': 'value22',
983         }
984         s2 = {
985             'key1': 'value123',
986             'key2': 'value234',
987         }
988
989         mock_config_parser = mock_config_parser_type()
990         mock_config_parser.read.return_value = True
991         mock_config_parser.sections.return_value = ['s1', 's2']
992         mock_config_parser.items.side_effect = iter([
993             defaults.items(),
994             s1.items(),
995             s2.items(),
996         ])
997
998         expected = {
999             'DEFAULT': defaults,
1000             's1': s1,
1001             's2': s2,
1002         }
1003         result = utils.parse_ini_file('my_path')
1004         self.assertDictEqual(result, expected)
1005
1006     @mock.patch.object(utils, 'logger')
1007     @mock.patch.object(configparser, 'ConfigParser')
1008     def test_parse_ini_file_missing_section_header(
1009             self, mock_config_parser_type, *args):
1010         mock_config_parser = mock_config_parser_type()
1011         mock_config_parser.read.side_effect = (
1012             configparser.MissingSectionHeaderError(mock.Mock(), 321,
1013                                                    mock.Mock()))
1014
1015         with self.assertRaises(configparser.MissingSectionHeaderError):
1016             utils.parse_ini_file('my_path')
1017
1018     @mock.patch.object(configparser, 'ConfigParser')
1019     def test_parse_ini_file_no_file(self, mock_config_parser_type):
1020         mock_config_parser = mock_config_parser_type()
1021         mock_config_parser.read.return_value = False
1022         with self.assertRaises(RuntimeError):
1023             utils.parse_ini_file('my_path')
1024
1025     @mock.patch.object(configparser, 'ConfigParser')
1026     def test_parse_ini_file_no_default_section_header(self, mock_config_parser_type):
1027         s1 = {
1028             'key1': 'value11',
1029             'key2': 'value22',
1030         }
1031         s2 = {
1032             'key1': 'value123',
1033             'key2': 'value234',
1034         }
1035
1036         mock_config_parser = mock_config_parser_type()
1037         mock_config_parser.read.return_value = True
1038         mock_config_parser.sections.return_value = ['s1', 's2']
1039         mock_config_parser.items.side_effect = iter([
1040             configparser.NoSectionError(mock.Mock()),
1041             s1.items(),
1042             s2.items(),
1043         ])
1044
1045         expected = {
1046             'DEFAULT': {},
1047             's1': s1,
1048             's2': s2,
1049         }
1050         result = utils.parse_ini_file('my_path')
1051         self.assertDictEqual(result, expected)
1052
1053     def test_join_non_strings(self):
1054         self.assertEqual(utils.join_non_strings(':'), '')
1055         self.assertEqual(utils.join_non_strings(':', 'a'), 'a')
1056         self.assertEqual(utils.join_non_strings(':', 'a', 2, 'c'), 'a:2:c')
1057         self.assertEqual(utils.join_non_strings(':', ['a', 2, 'c']), 'a:2:c')
1058         self.assertEqual(utils.join_non_strings(':', 'abc'), 'abc')
1059
1060     def test_validate_non_string_sequence(self):
1061         self.assertEqual(utils.validate_non_string_sequence([1, 2, 3]), [1, 2, 3])
1062         self.assertIsNone(utils.validate_non_string_sequence('123'))
1063         self.assertIsNone(utils.validate_non_string_sequence(1))
1064
1065         self.assertEqual(utils.validate_non_string_sequence(1, 2), 2)
1066         self.assertEqual(utils.validate_non_string_sequence(1, default=2), 2)
1067
1068         with self.assertRaises(RuntimeError):
1069             utils.validate_non_string_sequence(1, raise_exc=RuntimeError)
1070
1071
1072 class TestUtilsIpAddrMethods(ut_base.BaseUnitTestCase):
1073
1074     GOOD_IP_V4_ADDRESS_STR_LIST = [
1075         u'0.0.0.0',
1076         u'10.20.30.40',
1077         u'127.0.0.1',
1078         u'10.20.30.40',
1079         u'172.29.50.75',
1080         u'192.168.230.9',
1081         u'255.255.255.255',
1082     ]
1083
1084     GOOD_IP_V4_MASK_STR_LIST = [
1085         u'/1',
1086         u'/8',
1087         u'/13',
1088         u'/19',
1089         u'/24',
1090         u'/32',
1091     ]
1092
1093     GOOD_IP_V6_ADDRESS_STR_LIST = [
1094         u'::1',
1095         u'fe80::250:56ff:fe89:91ff',
1096         u'123:4567:89ab:cdef:123:4567:89ab:cdef',
1097     ]
1098
1099     GOOD_IP_V6_MASK_STR_LIST = [
1100         u'/1',
1101         u'/16',
1102         u'/29',
1103         u'/64',
1104         u'/99',
1105         u'/128',
1106     ]
1107
1108     INVALID_IP_ADDRESS_STR_LIST = [
1109         1,
1110         u'w.x.y.z',
1111         u'10.20.30.40/33',
1112         u'123:4567:89ab:cdef:123:4567:89ab:cdef/129',
1113     ]
1114
1115     def test_safe_ip_address(self):
1116         addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
1117         for addr in addr_list:
1118             # test with no mask
1119             expected = ipaddress.ip_address(addr)
1120             self.assertEqual(utils.safe_ip_address(addr), expected, addr)
1121
1122     def test_safe_ip_address_v6_ip(self):
1123         addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
1124         for addr in addr_list:
1125             # test with no mask
1126             expected = ipaddress.ip_address(addr)
1127             self.assertEqual(utils.safe_ip_address(addr), expected, addr)
1128
1129     @mock.patch("yardstick.common.utils.logging")
1130     def test_safe_ip_address_negative(self, *args):
1131         # NOTE(ralonsoh): check the calls to mocked functions.
1132         for value in self.INVALID_IP_ADDRESS_STR_LIST:
1133             self.assertIsNone(utils.safe_ip_address(value), value)
1134
1135         addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
1136         mask_list = self.GOOD_IP_V4_MASK_STR_LIST
1137         for addr_mask_pair in product(addr_list, mask_list):
1138             value = ''.join(addr_mask_pair)
1139             self.assertIsNone(utils.safe_ip_address(value), value)
1140
1141         addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
1142         mask_list = self.GOOD_IP_V6_MASK_STR_LIST
1143         for addr_mask_pair in product(addr_list, mask_list):
1144             value = ''.join(addr_mask_pair)
1145             self.assertIsNone(utils.safe_ip_address(value), value)
1146
1147     def test_get_ip_version(self):
1148         addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
1149         for addr in addr_list:
1150             # test with no mask
1151             self.assertEqual(utils.get_ip_version(addr), 4, addr)
1152
1153     def test_get_ip_version_v6_ip(self):
1154         addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
1155         for addr in addr_list:
1156             # test with no mask
1157             self.assertEqual(utils.get_ip_version(addr), 6, addr)
1158
1159     @mock.patch("yardstick.common.utils.logging")
1160     def test_get_ip_version_negative(self, *args):
1161         # NOTE(ralonsoh): check the calls to mocked functions.
1162         for value in self.INVALID_IP_ADDRESS_STR_LIST:
1163             self.assertIsNone(utils.get_ip_version(value), value)
1164
1165         addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
1166         mask_list = self.GOOD_IP_V4_MASK_STR_LIST
1167         for addr_mask_pair in product(addr_list, mask_list):
1168             value = ''.join(addr_mask_pair)
1169             self.assertIsNone(utils.get_ip_version(value), value)
1170
1171         addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
1172         mask_list = self.GOOD_IP_V6_MASK_STR_LIST
1173         for addr_mask_pair in product(addr_list, mask_list):
1174             value = ''.join(addr_mask_pair)
1175             self.assertIsNone(utils.get_ip_version(value), value)
1176
1177     def test_ip_to_hex(self):
1178         self.assertEqual(utils.ip_to_hex('0.0.0.0'), '00000000')
1179         self.assertEqual(utils.ip_to_hex('10.20.30.40'), '0a141e28')
1180         self.assertEqual(utils.ip_to_hex('127.0.0.1'), '7f000001')
1181         self.assertEqual(utils.ip_to_hex('172.31.90.100'), 'ac1f5a64')
1182         self.assertEqual(utils.ip_to_hex('192.168.254.253'), 'c0a8fefd')
1183         self.assertEqual(utils.ip_to_hex('255.255.255.255'), 'ffffffff')
1184
1185     def test_ip_to_hex_v6_ip(self):
1186         for value in self.GOOD_IP_V6_ADDRESS_STR_LIST:
1187             self.assertEqual(utils.ip_to_hex(value), value)
1188
1189     @mock.patch("yardstick.common.utils.logging")
1190     def test_ip_to_hex_negative(self, *args):
1191         # NOTE(ralonsoh): check the calls to mocked functions.
1192         addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
1193         mask_list = self.GOOD_IP_V4_MASK_STR_LIST
1194         value_iter = (''.join(pair) for pair in product(addr_list, mask_list))
1195         for value in chain(value_iter, self.INVALID_IP_ADDRESS_STR_LIST):
1196             self.assertEqual(utils.ip_to_hex(value), value)
1197
1198
1199 class SafeDecodeUtf8TestCase(ut_base.BaseUnitTestCase):
1200
1201     @unittest.skipIf(six.PY2,
1202                      'This test should only be launched with Python 3.x')
1203     def test_safe_decode_utf8(self):
1204         _bytes = b'this is a byte array'
1205         out = utils.safe_decode_utf8(_bytes)
1206         self.assertIs(type(out), str)
1207         self.assertEqual('this is a byte array', out)
1208
1209
1210 class ReadMeminfoTestCase(ut_base.BaseUnitTestCase):
1211
1212     MEMINFO = (b'MemTotal:       65860500 kB\n'
1213                b'MemFree:        28690900 kB\n'
1214                b'MemAvailable:   52873764 kB\n'
1215                b'Active(anon):    3015676 kB\n'
1216                b'HugePages_Total:       8\n'
1217                b'Hugepagesize:    1048576 kB')
1218     MEMINFO_DICT = {'MemTotal': '65860500',
1219                     'MemFree': '28690900',
1220                     'MemAvailable': '52873764',
1221                     'Active(anon)': '3015676',
1222                     'HugePages_Total': '8',
1223                     'Hugepagesize': '1048576'}
1224
1225     def test_read_meminfo(self):
1226         ssh_client = ssh.SSH('user', 'host')
1227         with mock.patch.object(ssh_client, 'get_file_obj') as \
1228                 mock_get_client, \
1229                 mock.patch.object(six, 'BytesIO',
1230                                   return_value=six.BytesIO(self.MEMINFO)):
1231             output = utils.read_meminfo(ssh_client)
1232             mock_get_client.assert_called_once_with('/proc/meminfo', mock.ANY)
1233         self.assertEqual(self.MEMINFO_DICT, output)
1234
1235
1236 class TimerTestCase(ut_base.BaseUnitTestCase):
1237
1238     def test__getattr(self):
1239         with utils.Timer() as timer:
1240             time.sleep(1)
1241         self.assertEqual(1, round(timer.total_seconds(), 0))
1242         self.assertEqual(1, timer.delta.seconds)
1243
1244     def test__enter_with_timeout(self):
1245         with utils.Timer(timeout=10) as timer:
1246             time.sleep(1)
1247         self.assertEqual(1, round(timer.total_seconds(), 0))
1248
1249     def test__enter_with_timeout_exception(self):
1250         with self.assertRaises(exceptions.TimerTimeout):
1251             with utils.Timer(timeout=1):
1252                 time.sleep(2)
1253
1254     def test__enter_with_timeout_no_exception(self):
1255         with utils.Timer(timeout=1, raise_exception=False):
1256             time.sleep(2)
1257
1258     def test__iter(self):
1259         iterations = []
1260         for i in utils.Timer(timeout=2):
1261             iterations.append(i)
1262             time.sleep(1.1)
1263         self.assertEqual(2, len(iterations))
1264
1265
1266 class WaitUntilTrueTestCase(ut_base.BaseUnitTestCase):
1267
1268     def test_no_timeout(self):
1269         self.assertIsNone(utils.wait_until_true(lambda: True,
1270                                                 timeout=1, sleep=1))
1271
1272     def test_timeout_generic_exception(self):
1273         with self.assertRaises(exceptions.WaitTimeout):
1274             self.assertIsNone(utils.wait_until_true(lambda: False,
1275                                                     timeout=1, sleep=1))
1276
1277     def test_timeout_given_exception(self):
1278         class MyTimeoutException(exceptions.YardstickException):
1279             message = 'My timeout exception'
1280
1281         with self.assertRaises(MyTimeoutException):
1282             self.assertIsNone(
1283                 utils.wait_until_true(lambda: False, timeout=1, sleep=1,
1284                                       exception=MyTimeoutException))