Repository: redhat-cip/hardware

Issue:
Mem benchmark fails with Python 3
MEM benchmarking fails with error "a bytes-like object is required, not 'str'"

```
hardware-detect --benchmark mem
...
Memory Performance: 8 logical CPU to test (ETA: 350 seconds)
Benchmarking memory @1K from CPU 0 for 5 seconds (1 threads)
Traceback (most recent call last):
  File "/usr/bin/hardware-detect", line 10, in <module>
    sys.exit(main())
  File "/usr/lib/python3.6/site-packages/hardware/detect.py", line 981, in main
    bm_mem.mem_perf(hrdw)
  File "/usr/lib/python3.6/site-packages/hardware/benchmark/mem.py", line 152, in mem_perf
    block_size, 1, cpu_nb)
  File "/usr/lib/python3.6/site-packages/hardware/benchmark/mem.py", line 91, in run_sysbench_memory_threaded
    if "transferred" in line:
TypeError: a bytes-like object is required, not 'str'
```

Original report:
https://bugzilla.redhat.com/show_bug.cgi?id=1753653

Comments:

Patch:
diff --git a/hardware/benchmark/disk.py b/hardware/benchmark/disk.py
index 6b987b66..92f779db 100644
--- a/hardware/benchmark/disk.py
+++ b/hardware/benchmark/disk.py
@@ -37,7 +37,8 @@ RAMP_TIME = 5
 
 def is_booted_storage_device(disk):
     """Check if a given disk is booted."""
-    cmdline = "grep -w /ahcexport /proc/mounts | cut -d ' ' -f 1 | sed -e 's/[0-9]*//g'"  # noqa
+    cmdline = ("grep -w /ahcexport /proc/mounts | cut -d ' ' -f 1 | "
+               "sed -e 's/[0-9]*//g'")
     if '/dev/' not in disk:
         disk = '/dev/%s' % disk
     grep_cmd = subprocess.Popen(cmdline,
diff --git a/hardware/benchmark/mem.py b/hardware/benchmark/mem.py
index abd4fd02..1a30ba36 100644
--- a/hardware/benchmark/mem.py
+++ b/hardware/benchmark/mem.py
@@ -22,6 +22,8 @@ import re
 import subprocess
 import sys
 
+import six
+
 from hardware.benchmark import utils
 
 
@@ -88,6 +90,8 @@ def run_sysbench_memory_threaded(hw_lst, max_time, block_size, cpu_count,
                                     shell=True, stdout=subprocess.PIPE)
 
     for line in sysbench_cmd.stdout:
+        if isinstance(line, six.binary_type):
+            line = line.decode()
         if "transferred" in line:
             _, right = line.rstrip('\n').replace(' ', '').split('(')
             perf, _ = right.split('.')
@@ -125,6 +129,8 @@ def run_sysbench_memory_forked(hw_lst, max_time, block_size, cpu_count):
     process = subprocess.Popen(
         sysbench_cmd, shell=True, stdout=subprocess.PIPE)
     for line in process.stdout:
+        if isinstance(line, six.binary_type):
+            line = line.decode()
         if "transferred" in line:
             _, right = line.rstrip('\n').replace(' ', '').split('(')
             perf, _ = right.split('.')
diff --git a/hardware/cardiff/check.py b/hardware/cardiff/check.py
index 92d3fb4d..e935e480 100755
--- a/hardware/cardiff/check.py
+++ b/hardware/cardiff/check.py
@@ -441,19 +441,36 @@ def print_summary(mode, array, array_name, unit, df, item_value=None):
                     min_cpu_perf = perf_cpu_tables.get_cpu_min_perf(mode,
                                                                     item_value)
                     if min_cpu_perf == 0:
-                        perf_status = (": " + ORANGE + "NO PERF ENTRY IN DB" +
-                                       WHITE + " for " + item_value)
+                        perf_status = (": %(orange)sNO PERF ENTRY IN DB"
+                                       "%(white)s for %(item_value)s" %
+                                       {'orange': ORANGE,
+                                        'white': WHITE,
+                                        'item_value': item_value})
                     elif mean >= min_cpu_perf:
-                        perf_status = ": " + GREEN + "PERF OK" + WHITE
+                        perf_status = (": %(green)sPERF OK%(white)s" %
+                                       {'green': GREEN,
+                                        'white': WHITE})
                     else:
-                        perf_status = (": " + RED + "PERF FAIL" + WHITE +
-                                       " as min perf should have been : " +
-                                       str(min_cpu_perf))
-        utils.do_print(
-            mode, utils.Levels.SUMMARY,
-            "%3d %s%-10s%s hosts with %8.2f %-4s as average value and %8.2f "
-            "standard deviation %s", len(array), before, array_name, after,
-            mean, unit, numpy.std(result), perf_status)
+                        perf_status = (": %(red)sPERF FAIL%(white)s as min "
+                                       "perf should have been : "
+                                       "%(min_cpu_perf)s" %
+                                       {'red': RED,
+                                        'white': WHITE,
+                                        'min_cpu_perf': str(min_cpu_perf)})
+
+        msg = ("%(array_length)3d %(before)s%(array_name)-10s%(after)s hosts "
+               "with %(mean)8.2f %(unit)-4s as average value and "
+               "%(result)8.2f standard deviation %(perf_status)s" %
+               {'array_length': len(array),
+                'before': before,
+                'array_name': array_name,
+                'after': after,
+                'mean': mean,
+                'unit': unit,
+                'result': numpy.std(result),
+                'perf_status': perf_status})
+
+        utils.do_print(mode, utils.Levels.SUMMARY, msg)
 
 
 def cpu_perf(system_list, unique_id, group_number, detail_options,


Test patch:
diff --git a/hardware/tests/test_benchmark_mem.py b/hardware/tests/test_benchmark_mem.py
index 1c0e9e2c..445a4c50 100644
--- a/hardware/tests/test_benchmark_mem.py
+++ b/hardware/tests/test_benchmark_mem.py
@@ -41,7 +41,40 @@ Test execution summary:
 
 Threads fairness:
     events (avg/stddev):           1957354.0000/0.00
-    execution time (avg/stddev):   3.0686/0.00""".splitlines()
+    execution time (avg/stddev):   3.0686/0.00"""
+
+EXPECTED_RESULT = [
+    ('cpu', 'logical', 'number', 2),
+    ('cpu', 'physical', 'number', 2),
+    ('cpu', 'logical_0', 'bandwidth_1K', '382'),
+    ('cpu', 'logical_0', 'bandwidth_4K', '382'),
+    ('cpu', 'logical_0', 'bandwidth_1M', '382'),
+    ('cpu', 'logical_0', 'bandwidth_16M', '382'),
+    ('cpu', 'logical_0', 'bandwidth_128M', '382'),
+    ('cpu', 'logical_0', 'bandwidth_1G', '382'),
+    ('cpu', 'logical_0', 'bandwidth_2G', '382'),
+    ('cpu', 'logical_1', 'bandwidth_1K', '382'),
+    ('cpu', 'logical_1', 'bandwidth_4K', '382'),
+    ('cpu', 'logical_1', 'bandwidth_1M', '382'),
+    ('cpu', 'logical_1', 'bandwidth_16M', '382'),
+    ('cpu', 'logical_1', 'bandwidth_128M', '382'),
+    ('cpu', 'logical_1', 'bandwidth_1G', '382'),
+    ('cpu', 'logical_1', 'bandwidth_2G', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_1K', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_4K', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_1M', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_16M', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_128M', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_1G', '382'),
+    ('cpu', 'logical', 'threaded_bandwidth_2G', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_1K', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_4K', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_1M', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_16M', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_128M', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_1G', '382'),
+    ('cpu', 'logical', 'forked_bandwidth_2G', '382')
+]
 
 
 @mock.patch.object(mem, 'get_available_memory')
@@ -54,44 +87,26 @@ class TestBenchmarkMem(unittest.TestCase):
         self.hw_data = [('cpu', 'logical', 'number', 2),
                         ('cpu', 'physical', 'number', 2)]
 
-    def test_mem_perf(self, mock_popen, mock_cpu_socket, mock_get_memory):
+    def test_mem_perf_bytes(self, mock_popen, mock_cpu_socket,
+                            mock_get_memory):
         mock_get_memory.return_value = 123456789012
-        mock_popen.return_value = mock.Mock(stdout=SYSBENCH_OUTPUT)
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.encode().splitlines())
         mock_cpu_socket.return_value = range(2)
         mem.mem_perf(self.hw_data)
 
-        expected = [
-            ('cpu', 'logical', 'number', 2),
-            ('cpu', 'physical', 'number', 2),
-            ('cpu', 'logical_0', 'bandwidth_1K', '382'),
-            ('cpu', 'logical_0', 'bandwidth_4K', '382'),
-            ('cpu', 'logical_0', 'bandwidth_1M', '382'),
-            ('cpu', 'logical_0', 'bandwidth_16M', '382'),
-            ('cpu', 'logical_0', 'bandwidth_128M', '382'),
-            ('cpu', 'logical_0', 'bandwidth_1G', '382'),
-            ('cpu', 'logical_0', 'bandwidth_2G', '382'),
-            ('cpu', 'logical_1', 'bandwidth_1K', '382'),
-            ('cpu', 'logical_1', 'bandwidth_4K', '382'),
-            ('cpu', 'logical_1', 'bandwidth_1M', '382'),
-            ('cpu', 'logical_1', 'bandwidth_16M', '382'),
-            ('cpu', 'logical_1', 'bandwidth_128M', '382'),
-            ('cpu', 'logical_1', 'bandwidth_1G', '382'),
-            ('cpu', 'logical_1', 'bandwidth_2G', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_1K', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_4K', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_1M', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_16M', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_128M', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_1G', '382'),
-            ('cpu', 'logical', 'threaded_bandwidth_2G', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_1K', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_4K', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_1M', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_16M', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_128M', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_1G', '382'),
-            ('cpu', 'logical', 'forked_bandwidth_2G', '382')
-        ]
+        expected = EXPECTED_RESULT
+        self.assertEqual(sorted(expected), sorted(self.hw_data))
+
+    def test_mem_perf_text(self, mock_popen, mock_cpu_socket,
+                           mock_get_memory):
+        mock_get_memory.return_value = 123456789012
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.splitlines())
+        mock_cpu_socket.return_value = range(2)
+        mem.mem_perf(self.hw_data)
+
+        expected = EXPECTED_RESULT
         self.assertEqual(sorted(expected), sorted(self.hw_data))
 
     def test_check_mem_size(self, mock_popen, mock_cpu_socket,
@@ -107,20 +122,47 @@ class TestBenchmarkMem(unittest.TestCase):
         for block_size in block_size_list:
             self.assertFalse(mem.check_mem_size(block_size, 2))
 
-    def test_run_sysbench_memory_forked(self, mock_popen, mock_cpu_socket,
-                                        mock_get_memory):
+    def test_run_sysbench_memory_forked_text(self, mock_popen, mock_cpu_socket,
+                                             mock_get_memory):
         mock_get_memory.return_value = 123456789012
-        mock_popen.return_value = mock.Mock(stdout=SYSBENCH_OUTPUT)
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.splitlines())
 
         hw_data = []
         mem.run_sysbench_memory_forked(hw_data, 10, '1K', 2)
         self.assertEqual([('cpu', 'logical', 'forked_bandwidth_1K', '382')],
                          hw_data)
 
-    def test_run_sysbench_memory_threaded(self, mock_popen, mock_cpu_socket,
-                                          mock_get_memory):
+    def test_run_sysbench_memory_forked_bytes(self, mock_popen,
+                                              mock_cpu_socket,
+                                              mock_get_memory):
+        mock_get_memory.return_value = 123456789012
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.encode().splitlines())
+
+        hw_data = []
+        mem.run_sysbench_memory_forked(hw_data, 10, '1K', 2)
+        self.assertEqual([('cpu', 'logical', 'forked_bandwidth_1K', '382')],
+                         hw_data)
+
+    def test_run_sysbench_memory_threaded_text(self, mock_popen,
+                                               mock_cpu_socket,
+                                               mock_get_memory):
+        mock_get_memory.return_value = 123456789012
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.splitlines())
+
+        hw_data = []
+        mem.run_sysbench_memory_threaded(hw_data, 10, '1K', 2)
+        self.assertEqual([('cpu', 'logical', 'threaded_bandwidth_1K', '382')],
+                         hw_data)
+
+    def test_run_sysbench_memory_threaded_bytes(self, mock_popen,
+                                                mock_cpu_socket,
+                                                mock_get_memory):
         mock_get_memory.return_value = 123456789012
-        mock_popen.return_value = mock.Mock(stdout=SYSBENCH_OUTPUT)
+        mock_popen.return_value = mock.Mock(
+            stdout=SYSBENCH_OUTPUT.encode().splitlines())
 
         hw_data = []
         mem.run_sysbench_memory_threaded(hw_data, 10, '1K', 2)