Пример #1
0
    def test_parse_lscpu_output(self, _):
        """
        Test model name parsing from `lscpu` output.

        See issue #29 (ARM architectures).
        `/proc/cpuinfo` will not contain `model name` info.
        `lscpu` output will be used instead.
        """
        with self.subTest('Simple unique CPU.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 4
                }])

        with self.subTest('Two CPUs, 1 socket.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 2
                }, {
                    'ANOTHER-CPU-MODEL': 4
                }])

        with self.subTest('1 CPU, 2 sockets.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 8
                }, {
                    'CPU-MODEL-NAME': 8
                }])
Пример #2
0
 def test_parse_sysctl_machdep(self, _):
     """Check `_parse_sysctl_machdep` behavior"""
     # pylint: disable=protected-access
     self.assertListEmpty(CPU._parse_sysctl_machdep())
     self.assertListEqual(CPU._parse_sysctl_machdep(),
                          [{
                              'Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz': 8
                          }])
Пример #3
0
 def test_parse_system_profiler(self, _):
     """Check `_parse_system_profiler` behavior"""
     # pylint: disable=protected-access
     self.assertListEmpty(CPU._parse_system_profiler())
     self.assertListEqual(CPU._parse_system_profiler(),
                          [{
                              'Dual-Core Intel Core i5 @ 3.1 GHz': 4
                          }])
Пример #4
0
 def test_parse_proc_cpuinfo_one_entry(self):
     """Test `/proc/cpuinfo` parsing"""
     self.assertListEqual(
         CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
         [{
             'CPU-MODEL-NAME': 1
         }])
Пример #5
0
    def test_model_name_match_lscpu(self, _):
        """
        Test model name parsing from `lscpu` output.

        See issue #29 (ARM architectures).
        `/proc/cpuinfo` will not contain `model name` info.
        `lscpu` output will be used instead.
        """
        self.assertEqual(CPU().value, 'CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO')
Пример #6
0
 def test_parse_proc_cpuinfo_one_cpu_dual_socket(self):
     """Test `/proc/cpuinfo` parsing for same CPU model across two sockets"""
     self.assertListEqual(
         CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
         [{
             'CPU-MODEL-NAME': 2
         }, {
             'CPU-MODEL-NAME': 2
         }])
Пример #7
0
 def test_parse_proc_cpuinfo_multiple_entries(self):
     """Test `/proc/cpuinfo` parsing"""
     self.assertListEqual(
         CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
         [{
             'CPU-MODEL-NAME': 1
         }, {
             'ANOTHER-CPU-MODEL': 2
         }])
Пример #8
0
    def test_various_output_configuration(self):
        """Test `output` overloading based on user preferences combination"""
        cpu_instance_mock = HelperMethods.entry_mock(CPU)
        output_mock = MagicMock()

        cpu_instance_mock.value = [{
            'CPU-MODEL-NAME': 1
        }, {
            'ANOTHER-CPU-MODEL': 2
        }]

        with self.subTest('Single-line combined output.'):
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, 2 x ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Single-line combined output (no count).'):
            cpu_instance_mock.options['show_cores'] = False
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Multi-lines output (with counts).'):
            cpu_instance_mock.options['show_cores'] = True
            cpu_instance_mock.options['one_line'] = False

            CPU.output(cpu_instance_mock, output_mock)
            self.assertEqual(output_mock.append.call_count, 2)
            output_mock.append.assert_has_calls(
                [
                    call('CPU', 'CPU-MODEL-NAME'),
                    call('CPU', '2 x ANOTHER-CPU-MODEL')
                ],
                any_order=
                True  # Since Python < 3.6 doesn't have definite `dict` ordering.
            )

        output_mock.reset_mock()

        with self.subTest('No CPU detected output.'):
            cpu_instance_mock.value = {}

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', DEFAULT_CONFIG['default_strings']['not_detected'])
Пример #9
0
 def test_parse_proc_cpuinfo_multiple_inconsistent_entries(self):
     """
     Test `/proc/cpuinfo` parsing with multiple CPUs sharing same physical ids (unlikely).
     Also check our model name normalizations applied on white characters.
     """
     self.assertListEqual(
         CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
         [{
             'CPU-MODEL-NAME': 1,
             'ANOTHER-CPU-MODEL': 1
         }, {
             'ANOTHER CPU MODEL WITH STRANGE S P A C E S': 2
         }])
Пример #10
0
class TestCPUEntry(unittest.TestCase):
    """
    Here, we mock the `open` call on `/proc/cpuinfo` with fake content.
    """
    @patch(
        'archey.entries.cpu.open',
        mock_open(
            read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
"""),
        create=True
    )
    def test_model_name_match_cpuinfo(self):
        """Test `/proc/cpuinfo` parsing"""
        self.assertEqual(CPU().value, 'CPU-MODEL-NAME')

    @patch(
        'archey.entries.cpu.open',
        mock_open(
            read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
"""),
        create=True
    )
    @patch(
        'archey.entries.cpu.check_output',
        return_value="""\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  X
Core(s) per socket:  Y
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO
""")
    def test_model_name_match_lscpu(self, _):
        """
        Test model name parsing from `lscpu` output.

        See issue #29 (ARM architectures).
        `/proc/cpuinfo` will not contain `model name` info.
        `lscpu` output will be used instead.
        """
        self.assertEqual(CPU().value, 'CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO')

    @patch(
        'archey.entries.cpu.open',
        mock_open(
            read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU  MODEL\t  NAME
"""),
        create=True
    )
    def test_spaces_squeezing(self):
        """Test name sanitizing, needed on some platforms"""
        self.assertEqual(CPU().value, 'CPU MODEL NAME')

    @patch(
        'archey.entries.cpu.open',
        side_effect=PermissionError(),
        create=True
    )
    @patch(
        'archey.entries.cpu.check_output',
        return_value="""\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  X
Core(s) per socket:  Y
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO
""")
    def test_proc_cpuinfo_unreadable(self, _, __):
        """Check Archey does not crash when `/proc/cpuinfo` is not readable"""
        self.assertEqual(CPU().value, 'CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO')
Пример #11
0
 def test_spaces_squeezing(self):
     """Test name sanitizing, needed on some platforms"""
     self.assertEqual(CPU().value, 'CPU MODEL NAME')
Пример #12
0
 def test_model_name_match_cpuinfo(self):
     """Test `/proc/cpuinfo` parsing"""
     self.assertEqual(CPU().value, 'CPU-MODEL-NAME')
Пример #13
0
 def test_proc_cpuinfo_unreadable(self, _, __):
     """Check Archey does not crash when `/proc/cpuinfo` is not readable"""
     self.assertEqual(CPU().value, 'CPU-MODEL-NAME-WITHOUT-PROC-CPUINFO')
Пример #14
0
 def test_parse_proc_cpuinfo_unreadable_file(self, _):
     """Check behavior when `/proc/cpuinfo` could not be read from disk"""
     self.assertListEmpty(CPU._parse_proc_cpuinfo())  # pylint: disable=protected-access
Пример #15
0
class TestCPUEntry(unittest.TestCase, CustomAssertions):
    """
    Here, we mock the `open` call on `/proc/cpuinfo` with fake content.
    In some cases, `lscpu` output is being mocked too.
    """
    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0
"""))
    def test_parse_proc_cpuinfo_one_entry(self):
        """Test `/proc/cpuinfo` parsing"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 1

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_multiple_entries(self):
        """Test `/proc/cpuinfo` parsing"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1
            }, {
                'ANOTHER-CPU-MODEL': 2
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 1

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 3
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_one_cpu_dual_socket(self):
        """Test `/proc/cpuinfo` parsing for same CPU model across two sockets"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 2
            }, {
                'CPU-MODEL-NAME': 2
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 0

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER\tCPU   MODEL WITH STRANGE S P  A   C     E     S
physical id\t: 1

processor\t: 3
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER\tCPU   MODEL WITH STRANGE S P  A   C     E     S
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_multiple_inconsistent_entries(self):
        """
        Test `/proc/cpuinfo` parsing with multiple CPUs sharing same physical ids (unlikely).
        Also check our model name normalizations applied on white characters.
        """
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1,
                'ANOTHER-CPU-MODEL': 1
            }, {
                'ANOTHER CPU MODEL WITH STRANGE S P A C E S': 2
            }])

    @patch('archey.entries.cpu.open', side_effect=PermissionError())
    def test_parse_proc_cpuinfo_unreadable_file(self, _):
        """Check behavior when `/proc/cpuinfo` could not be read from disk"""
        self.assertListEmpty(CPU._parse_proc_cpuinfo())  # pylint: disable=protected-access

    @patch('archey.entries.cpu.check_output',
           side_effect=[
               """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME
""", """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              2
On-line CPU(s) list: 0-1
Thread(s) per core:  1
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  2
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          ANOTHER-CPU-MODEL
""", """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              16
On-line CPU(s) list: 0-15
Thread(s) per core:  2
Core(s) per socket:  4
Socket(s):           2
NUMA node(s):        2
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME
"""
           ])
    def test_parse_lscpu_output(self, _):
        """
        Test model name parsing from `lscpu` output.

        See issue #29 (ARM architectures).
        `/proc/cpuinfo` will not contain `model name` info.
        `lscpu` output will be used instead.
        """
        with self.subTest('Simple unique CPU.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 4
                }])

        with self.subTest('Two CPUs, 1 socket.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 2
                }, {
                    'ANOTHER-CPU-MODEL': 4
                }])

        with self.subTest('1 CPU, 2 sockets.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 8
                }, {
                    'CPU-MODEL-NAME': 8
                }])

    @HelperMethods.patch_clean_configuration
    def test_various_output_configuration(self):
        """Test `output` overloading based on user preferences combination"""
        cpu_instance_mock = HelperMethods.entry_mock(CPU)
        output_mock = MagicMock()

        cpu_instance_mock.value = [{
            'CPU-MODEL-NAME': 1
        }, {
            'ANOTHER-CPU-MODEL': 2
        }]

        with self.subTest('Single-line combined output.'):
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, 2 x ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Single-line combined output (no count).'):
            cpu_instance_mock.options['show_cores'] = False
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Multi-lines output (with counts).'):
            cpu_instance_mock.options['show_cores'] = True
            cpu_instance_mock.options['one_line'] = False

            CPU.output(cpu_instance_mock, output_mock)
            self.assertEqual(output_mock.append.call_count, 2)
            output_mock.append.assert_has_calls(
                [
                    call('CPU', 'CPU-MODEL-NAME'),
                    call('CPU', '2 x ANOTHER-CPU-MODEL')
                ],
                any_order=
                True  # Since Python < 3.6 doesn't have definite `dict` ordering.
            )

        output_mock.reset_mock()

        with self.subTest('No CPU detected output.'):
            cpu_instance_mock.value = {}

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', DEFAULT_CONFIG['default_strings']['not_detected'])
Пример #16
0
class TestCPUEntry(unittest.TestCase, CustomAssertions):
    """
    Here, we mock the `open` call on `/proc/cpuinfo` with fake content.
    In some cases, `lscpu` output is being mocked too.
    """
    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0
"""))
    def test_parse_proc_cpuinfo_one_entry(self):
        """Test `/proc/cpuinfo` parsing"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 1

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_multiple_entries(self):
        """Test `/proc/cpuinfo` parsing"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1
            }, {
                'ANOTHER-CPU-MODEL': 2
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 1

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 3
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_one_cpu_dual_socket(self):
        """Test `/proc/cpuinfo` parsing for same CPU model across two sockets"""
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 2
            }, {
                'CPU-MODEL-NAME': 2
            }])

    @patch('archey.entries.cpu.open',
           mock_open(read_data="""\
processor\t: 0
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: CPU-MODEL-NAME
physical id\t: 0

processor\t: 1
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER-CPU-MODEL
physical id\t: 0

processor\t: 2
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER\tCPU   MODEL WITH STRANGE S P  A   C     E     S
physical id\t: 1

processor\t: 3
vendor_id\t: CPU-VENDOR-NAME
cpu family\t: X
model\t\t: YY
model name\t: ANOTHER\tCPU   MODEL WITH STRANGE S P  A   C     E     S
physical id\t: 1
"""))
    def test_parse_proc_cpuinfo_multiple_inconsistent_entries(self):
        """
        Test `/proc/cpuinfo` parsing with multiple CPUs sharing same physical ids (unlikely).
        Also check our model name normalizations applied on white characters.
        """
        self.assertListEqual(
            CPU._parse_proc_cpuinfo(),  # pylint: disable=protected-access
            [{
                'CPU-MODEL-NAME': 1,
                'ANOTHER-CPU-MODEL': 1
            }, {
                'ANOTHER CPU MODEL WITH STRANGE S P A C E S': 2
            }])

    @patch('archey.entries.cpu.open', side_effect=PermissionError())
    def test_parse_proc_cpuinfo_unreadable_file(self, _):
        """Check behavior when `/proc/cpuinfo` could not be read from disk"""
        self.assertListEmpty(CPU._parse_proc_cpuinfo())  # pylint: disable=protected-access

    @patch('archey.entries.cpu.check_output',
           side_effect=[
               FileNotFoundError(), """\
{
  "SPHardwareDataType" : [
    {
      "_name" : "hardware_overview",
      "cpu_type" : "Dual-Core Intel Core i5",
      "current_processor_speed" : "3,1 GHz",
      "machine_model" : "MacBookPro00OOooOO00",
      "machine_name" : "MacBook Pro",
      "number_processors" : 2,
      "packages" : 1,
      "platform_cpu_htt" : "htt_enabled",
      "platform_UUID" : "XXXXXXXX-YYYY-ZZZZ-TTTT-UUUUUUUUUUUU",
      "provisioning_UDID" : "XXXXXXXX-YYYY-ZZZZ-TTTT-UUUUUUUUUUUU",
      "serial_number" : "XX00YY11ZZ22"
    }
  ]
}
"""
           ])
    def test_parse_system_profiler(self, _):
        """Check `_parse_system_profiler` behavior"""
        # pylint: disable=protected-access
        self.assertListEmpty(CPU._parse_system_profiler())
        self.assertListEqual(CPU._parse_system_profiler(),
                             [{
                                 'Dual-Core Intel Core i5 @ 3.1 GHz': 4
                             }])
        # pylint: enable=protected-access

    @patch('archey.entries.cpu.check_output',
           side_effect=[
               FileNotFoundError(), """\
Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz
8
"""
           ])
    def test_parse_sysctl_machdep(self, _):
        """Check `_parse_sysctl_machdep` behavior"""
        # pylint: disable=protected-access
        self.assertListEmpty(CPU._parse_sysctl_machdep())
        self.assertListEqual(CPU._parse_sysctl_machdep(),
                             [{
                                 'Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz': 8
                             }])
        # pylint: enable=protected-access

    @patch('archey.entries.cpu.check_output',
           side_effect=[
               """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME
""", """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              2
On-line CPU(s) list: 0-1
Thread(s) per core:  1
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  2
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          ANOTHER-CPU-MODEL
""", """\
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              16
On-line CPU(s) list: 0-15
Thread(s) per core:  2
Core(s) per socket:  4
Socket(s):           2
NUMA node(s):        2
Vendor ID:           CPU-VENDOR-NAME
CPU family:          Z
Model:               \xde\xad\xbe\xef
Model name:          CPU-MODEL-NAME
"""
           ])
    def test_parse_lscpu_output(self, _):
        """
        Test model name parsing from `lscpu` output.

        See issue #29 (ARM architectures).
        `/proc/cpuinfo` will not contain `model name` info.
        `lscpu` output will be used instead.
        """
        with self.subTest('Simple unique CPU.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 4
                }])

        with self.subTest('Two CPUs, 1 socket.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 2
                }, {
                    'ANOTHER-CPU-MODEL': 4
                }])

        with self.subTest('1 CPU, 2 sockets.'):
            self.assertListEqual(
                CPU._parse_lscpu_output(),  # pylint: disable=protected-access
                [{
                    'CPU-MODEL-NAME': 8
                }, {
                    'CPU-MODEL-NAME': 8
                }])

    @HelperMethods.patch_clean_configuration
    def test_various_output_configuration(self):
        """Test `output` overloading based on user preferences combination"""
        cpu_instance_mock = HelperMethods.entry_mock(CPU)
        output_mock = MagicMock()

        cpu_instance_mock.value = [{
            'CPU-MODEL-NAME': 1
        }, {
            'ANOTHER-CPU-MODEL': 2
        }]

        with self.subTest('Single-line combined output.'):
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, 2 x ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Single-line combined output (no count).'):
            cpu_instance_mock.options['show_cores'] = False
            cpu_instance_mock.options['one_line'] = True

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', 'CPU-MODEL-NAME, ANOTHER-CPU-MODEL')

        output_mock.reset_mock()

        with self.subTest('Multi-lines output (with counts).'):
            cpu_instance_mock.options['show_cores'] = True
            cpu_instance_mock.options['one_line'] = False

            CPU.output(cpu_instance_mock, output_mock)
            self.assertEqual(output_mock.append.call_count, 2)
            output_mock.append.assert_has_calls([
                call('CPU', 'CPU-MODEL-NAME'),
                call('CPU', '2 x ANOTHER-CPU-MODEL')
            ])

        output_mock.reset_mock()

        with self.subTest('No CPU detected output.'):
            cpu_instance_mock.value = []

            CPU.output(cpu_instance_mock, output_mock)
            output_mock.append.assert_called_once_with(
                'CPU', DEFAULT_CONFIG['default_strings']['not_detected'])