def test_output(self): """Simple test for `output` base method""" user_instance_mock = HelperMethods.entry_mock(User) output_mock = MagicMock() User.output(user_instance_mock, output_mock) self.assertEqual(output_mock.append.call_args[0][1], DEFAULT_CONFIG['default_strings']['not_detected'])
def test_no_match(self): """Test when no information could be retrieved""" model_instance_mock = HelperMethods.entry_mock(Model) output_mock = MagicMock() Model.output(model_instance_mock, output_mock) self.assertIsNone(model_instance_mock.value) self.assertEqual(output_mock.append.call_args[0][1], DEFAULT_CONFIG['default_strings']['not_detected'])
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'])
def test_unknown_distro_output(self): """Test for `output` method when distribution name couldn't be found""" distro_intance_mock = HelperMethods.entry_mock(Distro) output_mock = MagicMock() distro_intance_mock.value = {'name': None, 'arch': 'ARCHITECTURE'} Distro.output(distro_intance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], f"{DEFAULT_CONFIG['default_strings']['not_detected']} [ARCHITECTURE]" )
def test_various_output_configuration(self): """Test `output` overloading based on user preferences""" ram_instance_mock = HelperMethods.entry_mock(RAM) output_mock = MagicMock() with self.subTest('Output in case of non-detection.'): RAM.output(ram_instance_mock, output_mock) self.assertEqual(output_mock.append.call_args[0][1], DEFAULT_CONFIG['default_strings']['not_detected']) output_mock.reset_mock() with self.subTest('"Normal" output (green).'): ram_instance_mock.value = { 'used': 2043.0, 'total': 15658.0, 'unit': 'MiB' } ram_instance_mock.options = { 'warning_use_percent': 33.3, 'danger_use_percent': 66.7 } RAM.output(ram_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], f'{Colors.GREEN_NORMAL}2043 MiB{Colors.CLEAR} / 15658 MiB') output_mock.reset_mock() with self.subTest('"Danger" output (red).'): ram_instance_mock.value = { 'used': 7830.0, 'total': 15658.0, 'unit': 'MiB' } ram_instance_mock.options = { 'warning_use_percent': 25, 'danger_use_percent': 50 } RAM.output(ram_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], f'{Colors.RED_NORMAL}7830 MiB{Colors.CLEAR} / 15658 MiB')
def test_output_coloration(self): """Test `output` coloration based on user preferences""" load_average_mock = HelperMethods.entry_mock(LoadAverage) output_mock = MagicMock() load_average_mock.value = (0.5, 1.25, 2.5) load_average_mock.options = { "warning_threshold": 0.75, "danger_threshold": 2.25, } LoadAverage.output(load_average_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], f"{Colors.GREEN_NORMAL}0.5{Colors.CLEAR} " f"{Colors.YELLOW_NORMAL}1.25{Colors.CLEAR} " f"{Colors.RED_NORMAL}2.5{Colors.CLEAR}", )
def test_various_output_configuration(self): """Test `output` overloading based on user preferences""" gpu_instance_mock = HelperMethods.entry_mock(GPU) output_mock = MagicMock() gpu_instance_mock.value = [ '3D GPU-MODEL-NAME TAKES ADVANTAGE', 'GPU-MODEL-NAME', 'ANOTHER-MATCHING-VIDEO' ] with self.subTest('Single-line combined output.'): gpu_instance_mock.options['one_line'] = True GPU.output(gpu_instance_mock, output_mock) output_mock.append.assert_called_once_with( 'GPU', '3D GPU-MODEL-NAME TAKES ADVANTAGE, GPU-MODEL-NAME, ANOTHER-MATCHING-VIDEO' ) output_mock.reset_mock() with self.subTest('Multi-lines output.'): gpu_instance_mock.options['one_line'] = False GPU.output(gpu_instance_mock, output_mock) self.assertEqual(output_mock.append.call_count, 3) output_mock.append.assert_has_calls([ call('GPU', '3D GPU-MODEL-NAME TAKES ADVANTAGE'), call('GPU', 'GPU-MODEL-NAME'), call('GPU', 'ANOTHER-MATCHING-VIDEO') ]) output_mock.reset_mock() with self.subTest('No GPU detected output.'): gpu_instance_mock.value = [] GPU.output(gpu_instance_mock, output_mock) output_mock.append.assert_called_once_with( 'GPU', DEFAULT_CONFIG['default_strings']['not_detected'])
def setUp(self): """We use these mocks so often, it's worth defining them here.""" self.wan_ip_mock = HelperMethods.entry_mock(WanIP) self.output_mock = MagicMock()
def test_fetch_virtual_env_info(self, check_output_mock, getuid_mock): """Test `_fetch_virtual_env_info` method""" model_mock = HelperMethods.entry_mock(Model) with self.subTest('Detected virtual environment.'): check_output_mock.side_effect = [ FileNotFoundError(), # `systemd-detect-virt` is not available. 'xen\nxen-domU\n', # `virt-what` example output. 'HYPERVISOR-NAME\n' # `dmidecode` example output. ] getuid_mock.return_value = 0 self.assertEqual( Model._fetch_virtual_env_info(model_mock), # pylint: disable=protected-access 'HYPERVISOR-NAME (xen, xen-domU)') with self.subTest('Virtual environment without `dmidecode`.'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = [ FileNotFoundError(), # `systemd-detect-virt` is not available. 'xen\nxen-domU\n', # `virt-what` example output. FileNotFoundError() # `dmidecode` will fail. ] getuid_mock.return_value = 0 self.assertEqual( Model._fetch_virtual_env_info(model_mock), # pylint: disable=protected-access DEFAULT_CONFIG['default_strings']['virtual_environment'] + ' (xen, xen-domU)') with self.subTest('Virtual environment with systemd only.'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = [ 'systemd-nspawn\n' # `systemd-detect-virt` output. ] getuid_mock.return_value = 1000 # `virt-what` and `dmidecode` won't be called. self.assertEqual( Model._fetch_virtual_env_info(model_mock), # pylint: disable=protected-access DEFAULT_CONFIG['default_strings']['virtual_environment'] + ' (systemd-nspawn)') with self.subTest('Virtual environment with systemd and `dmidecode`.'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = [ 'systemd-nspawn\n', # `systemd-detect-virt` example output. # `virt-what` won't be called (systemd call succeeded). 'HYPERVISOR-NAME\n' # `dmidecode` example output. ] getuid_mock.return_value = 0 self.assertEqual( Model._fetch_virtual_env_info(model_mock), # pylint: disable=protected-access 'HYPERVISOR-NAME (systemd-nspawn)') with self.subTest('Not a virtual environment (systemd).'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = CalledProcessError( 1, 'systemd-detect-virt', 'none\n') self.assertIsNone( Model._fetch_virtual_env_info(model_mock) # pylint: disable=protected-access ) with self.subTest('Not a virtual environment (virt-what).'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = [ FileNotFoundError( ), # `systemd-detect-virt` won't be available. '\n' # `virt-what` won't detect anything. # `dmidecode` won't even be called. ] getuid_mock.return_value = 0 self.assertIsNone( Model._fetch_virtual_env_info(model_mock) # pylint: disable=protected-access ) with self.subTest('Not a virtual environment (no tools, no root)'): check_output_mock.reset_mock() getuid_mock.reset_mock() check_output_mock.side_effect = [ FileNotFoundError( ) # `systemd-detect-virt` won't be available. ] getuid_mock.return_value = 1000 # `virt-what` and `dmidecode` won't be called. self.assertIsNone( Model._fetch_virtual_env_info(model_mock) # pylint: disable=protected-access )
def setUp(self): """We use these mocks so often, it's worth defining them here.""" self.disk_instance_mock = HelperMethods.entry_mock(Disk) self.output_mock = MagicMock()
def setUp(self): self.temperature_mock = HelperMethods.entry_mock(Temperature) self.temperature_mock._temps = [] # pylint: disable=protected-access
def test_parse_uptime_cmd(self, check_output_mock): """Test `_parse_uptime_cmd` static method""" # Create an uptime instance to perform testing. # It doesn't matter that its `__init__` will be called. uptime_instance_mock = HelperMethods.entry_mock(Uptime) # Keys: `uptime` outputs; values: expected `timedelta` instances. # We will test these with various time formats (and various numbers of users). # pylint: disable=line-too-long test_uptime_cases = { # Recently booted: '{time} up 0 sec, {user_loadavg}': timedelta(seconds=0), # BSD, just booted '{time} up 1 sec, {user_loadavg}': timedelta(seconds=1), # BSD, < 1 min uptime '{time} up 12 secs, {user_loadavg}': timedelta(seconds=12), # BSD, < 1 min uptime '{time} up 0 min, {user_loadavg}': timedelta(minutes=0), # Linux, < 1 min uptime '{time} up 1 min, {user_loadavg}': timedelta(minutes=1), # 1 min to 1 day '{time} up 12 mins, {user_loadavg}': timedelta(minutes=12), '{time} up 12 min, {user_loadavg}': timedelta(minutes=12), # Variation without plural minutes '{time} up 1:00, {user_loadavg}': timedelta(hours=1), '{time} up 1:01, {user_loadavg}': timedelta(hours=1, minutes=1), '{time} up 1:23, {user_loadavg}': timedelta(hours=1, minutes=23), '{time} up 12:34, {user_loadavg}': timedelta(hours=12, minutes=34), # 1 day to 2 days '{time} up 1 day, 0 sec, {user_loadavg}': timedelta(days=1), # BSD '{time} up 1 day, 1 sec, {user_loadavg}': timedelta(days=1, seconds=1), # BSD '{time} up 1 day, 12 secs, {user_loadavg}': timedelta(days=1, seconds=12), # BSD '{time} up 1 day, 0 min, {user_loadavg}': timedelta(days=1), # Linux '{time} up 1 day, 1 min, {user_loadavg}': timedelta(days=1, minutes=1), '{time} up 1 day, 12 mins, {user_loadavg}': timedelta(days=1, minutes=12), '{time} up 1 day, 12 min, {user_loadavg}': timedelta(days=1, minutes=12), # Variation without plural minutes '{time} up 1 day, 1:00, {user_loadavg}': timedelta(days=1, hours=1), '{time} up 1 day, 1:01, {user_loadavg}': timedelta(days=1, hours=1, minutes=1), '{time} up 1 day, 1:23, {user_loadavg}': timedelta(days=1, hours=1, minutes=23), '{time} up 1 day, 12:34, {user_loadavg}': timedelta(days=1, hours=12, minutes=34), # 2 days onwards '{time} up 12 days, 0 sec, {user_loadavg}': timedelta(days=12), # BSD '{time} up 12 days, 1 sec, {user_loadavg}': timedelta(days=12, seconds=1), # BSD '{time} up 12 days, 12 secs, {user_loadavg}': timedelta(days=12, seconds=12), # BSD '{time} up 12 days, 0 min, {user_loadavg}': timedelta(days=12), # Linux '{time} up 12 days, 1 min, {user_loadavg}': timedelta(days=12, minutes=1), '{time} up 12 days, 12 mins, {user_loadavg}': timedelta(days=12, minutes=12), '{time} up 12 day, 12 min, {user_loadavg}': timedelta(days=12, minutes=12), # Variation without plural minutes '{time} up 12 days, 1:00, {user_loadavg}': timedelta(days=12, hours=1), '{time} up 12 days, 1:01, {user_loadavg}': timedelta(days=12, hours=1, minutes=1), '{time} up 12 days, 1:23, {user_loadavg}': timedelta(days=12, hours=1, minutes=23), '{time} up 12 days, 12:34, {user_loadavg}': timedelta(days=12, hours=12, minutes=34), # Very long uptimes - sanity check :) '{time} up 500 days, 0 sec, {user_loadavg}': timedelta(days=500), # BSD '{time} up 500 days, 1 sec, {user_loadavg}': timedelta(days=500, seconds=1), # BSD '{time} up 500 days, 12 secs, {user_loadavg}': timedelta(days=500, seconds=12), # BSD '{time} up 500 days, 0 min, {user_loadavg}': timedelta(days=500), # Linux '{time} up 500 days, 1 min, {user_loadavg}': timedelta(days=500, minutes=1), '{time} up 500 days, 12 mins, {user_loadavg}': timedelta(days=500, minutes=12), '{time} up 500 day, 12 min, {user_loadavg}': timedelta(days=500, minutes=12), # Variation without plural minutes '{time} up 500 days, 1:00, {user_loadavg}': timedelta(days=500, hours=1), '{time} up 500 days, 1:01, {user_loadavg}': timedelta(days=500, hours=1, minutes=1), '{time} up 500 days, 1:23, {user_loadavg}': timedelta(days=500, hours=1, minutes=23), '{time} up 500 days, 12:34, {user_loadavg}': timedelta(days=500, hours=12, minutes=34) } # pylint: enable=line-too-long # Variations of the time in the `{time}` section. # These _should_ be avoided when we set the locale in `check_output`, # however let's check we can handle them anyway, just in case. time_variations = ( '0:00', '9:43 ', '11:37 ', '19:21', '23:59', '12:00am', '1:10am', '1:10pm ', '6:43pm ', '8:26am ', '03:14:15', '09:26:12 ', '23:19:20 ', 'nonsense_time ', 'hopefully_works_anyway ', ' even with strange spacing!' ) # Variations of the user count and load average section. # For this, we'll just combine user variations with a few load average variations. user_variations = ( '1 user ', '1 user ', ' 1 user, ', ' 1 user, ', '2 users ', '2 users ', ' 2 users, ', ' 2 users, ', '15 users ', '15 users ', ' 15 users, ', ' 15 users, ', '150 users ', '150 users ', '150 users, ', '150 users, ' ) loadavg_variations = ( 'load averages: 1.95 1.28 2.10', 'load average: 0.13, 0.17, 0.13', 'we never match this part so the content here', ' should not affect our parsing' ) user_loadavg_variations = [ user + loadavg for user in user_variations for loadavg in loadavg_variations ] for uptime_output, expected_delta in test_uptime_cases.items(): # We use `itertools.product` to get the permutations of our variations # since there are a lot of them! (a list comprehension would be slower) for variations in product(time_variations, user_loadavg_variations): check_output_mock.return_value = uptime_output.format( time=variations[0], user_loadavg=variations[1] ).encode() self.assertEqual( uptime_instance_mock._parse_uptime_cmd(), # pylint: disable=protected-access expected_delta, msg='`uptime` output: "{}"'.format( uptime_output.format( time=variations[0], user_loadavg=variations[1] ) ) ) # Check that our internal exception is correctly raised when `uptime` is not available. check_output_mock.side_effect = FileNotFoundError() self.assertRaises( ArcheyException, uptime_instance_mock._parse_uptime_cmd # pylint: disable=protected-access )
def test_various_output_cases(self): """Test when the device has just been started...""" uptime_instance_mock = HelperMethods.entry_mock(Uptime) output_mock = MagicMock() with self.subTest('Output in case of hours and minutes.'): uptime_instance_mock.value = { 'days': 0, 'hours': 2, 'minutes': 1, 'seconds': 0 } Uptime.output(uptime_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], '2 hours and 1 minute' ) output_mock.reset_mock() with self.subTest('Output in case of days, hours and minutes.'): uptime_instance_mock.value = { 'days': 1, 'hours': 1, 'minutes': 2, 'seconds': 0 } Uptime.output(uptime_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], '1 day, 1 hour and 2 minutes' ) output_mock.reset_mock() with self.subTest('Output in case of days and minutes.'): uptime_instance_mock.value = { 'days': 3, 'hours': 0, 'minutes': 3, 'seconds': 0 } Uptime.output(uptime_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], '3 days and 3 minutes' ) output_mock.reset_mock() with self.subTest('Output in case of very early execution.'): uptime_instance_mock.value = { 'days': 0, 'hours': 0, 'minutes': 0, 'seconds': 0 } Uptime.output(uptime_instance_mock, output_mock) self.assertEqual( output_mock.append.call_args[0][1], '< 1 minute' )