From 77b84c8cdff92cb65fdac2ebd4060f180a5f938c Mon Sep 17 00:00:00 2001 From: Jonathan Cave Date: Wed, 21 Aug 2024 14:14:56 +0100 Subject: [PATCH] Handle no installed dkms modules (BugFix) (#1426) * Handle no installed dkms modules * more testing --- providers/sru/bin/dkms_build_validation.py | 13 +- .../sru/tests/test_dkms_build_validation.py | 175 ++++++++++++++---- 2 files changed, 154 insertions(+), 34 deletions(-) diff --git a/providers/sru/bin/dkms_build_validation.py b/providers/sru/bin/dkms_build_validation.py index e7eaf5f79..31532fd74 100755 --- a/providers/sru/bin/dkms_build_validation.py +++ b/providers/sru/bin/dkms_build_validation.py @@ -78,6 +78,11 @@ def parse_dkms_status(dkms_status: str, ubuntu_release: str) -> List[Dict]: else: kernel_ver = details.split(", ")[2] kernel_info.append({"version": kernel_ver, "status": status}) + print( + "Found module {}, status {} for kernel version {}".format( + details, status, kernel_ver + ) + ) sorted_kernel_info = sorted( kernel_info, key=lambda x: parse_version(x["version"]) @@ -177,6 +182,12 @@ def main(): # Parse and sort the DKMS status and sort the kernel versions sorted_kernel_info = parse_dkms_status(dkms_status, ubuntu_release) + # if there are no built or installed dkms modules there is nothing + # to check + if not sorted_kernel_info: + print("No installed dkms modules found, nothing to check") + return 0 + # kernel_ver_max should be the same as kernel_ver_current kernel_ver_current = run_command(["uname", "-r"]) if check_kernel_version( @@ -184,7 +195,7 @@ def main(): ): return 1 - # Count the occurernces of the latest and the oldest kernel version and + # Count the occurrences of the latest and the oldest kernel version and # compare the number of DKMS modules for min and max kernel versions check_dkms_module_count(sorted_kernel_info, dkms_status) diff --git a/providers/sru/tests/test_dkms_build_validation.py b/providers/sru/tests/test_dkms_build_validation.py index cb8260bec..fb0087e8d 100644 --- a/providers/sru/tests/test_dkms_build_validation.py +++ b/providers/sru/tests/test_dkms_build_validation.py @@ -23,6 +23,10 @@ class TestDKMSValidation(unittest.TestCase): "fwts/24.01.00, 6.5.0-15-generic, x86_64: installed" ) + dkms_status_empty = "" + + dkms_status_added_only = "fwts-efi-runtime-dkms/24.07.00: added" + # Example output of `dkms status` on machine # in which efi_test driver is used rather than # fwts dkms driver @@ -47,11 +51,25 @@ class TestDKMSValidation(unittest.TestCase): "(WARNING! Diff between built and installed module!)" ) + dkms_status_oem_focal = ( + "fwts-efi-runtime-dkms, 24.07.00, 5.14.0-1042-oem, x86_64: installed\n" + "fwts-efi-runtime-dkms, 24.07.00, 5.15.0-117-generic, x86_64: installed" + ) + + dkms_status_stock_noble = ( + "fwts-efi-runtime-dkms/24.07.00: added\n" + "nvidia/550.107.02, 6.8.0-44-generic, x86_64: installed" + ) + sorted_kernel_info = [ {"version": "6.5.0-15-generic", "status": "installed"}, {"version": "6.5.0-17-generic", "status": "installed"}, ] + sorted_kernel_info_empty = [] + + sorted_kernel_info_added_only = [] + sorted_kernel_info_efi_test_driver = [ {"version": "6.1.0-1028-oem", "status": "installed"}, {"version": "6.1.0-1032-oem", "status": "installed"}, @@ -66,6 +84,10 @@ class TestDKMSValidation(unittest.TestCase): {"version": "6.8.0-40-generic", "status": "installed"}, ] + sorted_kernel_info_with_warning = [ + {"version": "6.0.0-1011-oem", "status": "installed"} + ] + @patch("dkms_build_validation.subprocess.check_output") def test_run_command(self, mock_check_output): mock_check_output.return_value = "output" @@ -98,6 +120,20 @@ def test_parse_dkms_status(self): ] self.assertEqual(kernel_info, expected_kernel_info) + def test_parse_dkms_status_empty(self): + ubuntu_release = "20.04" + kernel_info = parse_dkms_status(self.dkms_status_empty, ubuntu_release) + expected_kernel_info = [] + self.assertEqual(kernel_info, expected_kernel_info) + + def test_parse_dkms_status_added_only(self): + ubuntu_release = "22.04" + kernel_info = parse_dkms_status( + self.dkms_status_added_only, ubuntu_release + ) + expected_kernel_info = [] + self.assertEqual(kernel_info, expected_kernel_info) + def test_parse_dkms_status_efi_test(self): ubuntu_release = "22.04" kernel_info = parse_dkms_status( @@ -181,6 +217,7 @@ def test_check_kernel_version(self): 1, ) + def test_check_kernel_version_efi_test_driver(self): self.assertEqual( check_kernel_version( "6.1.0-1028-oem", @@ -208,6 +245,16 @@ def test_check_kernel_version(self): 0, ) + def test_check_kernel_version_with_warning(self): + self.assertEqual( + check_kernel_version( + "6.0.0-1011-oem", + self.sorted_kernel_info_with_warning, + self.dkms_status_with_warning, + ), + 0, + ) + def test_check_dkms_module_count(self): # Test with the same number of modules self.assertEqual( @@ -268,46 +315,108 @@ def test_has_dkms_build_errors(self): self.assertEqual(has_dkms_build_errors(kernel_ver_current), True) @patch("dkms_build_validation.run_command") - @patch("dkms_build_validation.parse_dkms_status") - @patch("dkms_build_validation.check_kernel_version") - @patch("dkms_build_validation.check_dkms_module_count") @patch("dkms_build_validation.has_dkms_build_errors") - def test_main( - self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command - ): - mock_run_command.return_value = "output" - mock_parse.return_value = [] - mock_ver.return_value = 0 - mock_count.return_value = 0 + def test_main(self, mock_err, mock_run_command): + # 0: lsb_release -r + # 1: dkms status + # 2: uname -r + mock_run_command.side_effect = [ + "Release: 22.04", + self.dkms_status, + "6.5.0-17-generic", + ] + mock_err.return_value = 0 + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 0) + + @patch("dkms_build_validation.run_command") + @patch("dkms_build_validation.has_dkms_build_errors") + def test_main_empty(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 22.04", + "", + "6.8.0-40-generic", + ] + mock_err.return_value = 0 + result = main() + self.assertEqual(mock_err.call_count, 0) + self.assertEqual(result, 0) + + @patch("dkms_build_validation.run_command") + @patch("dkms_build_validation.has_dkms_build_errors") + def test_main_added_only(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 22.04", + self.dkms_status_added_only, + "6.8.0-40-generic", + ] + mock_err.return_value = 0 + result = main() + self.assertEqual(mock_err.call_count, 0) + self.assertEqual(result, 0) + + @patch("dkms_build_validation.run_command") + @patch("dkms_build_validation.has_dkms_build_errors") + def test_main_efi_test_driver(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 22.04", + self.dkms_status_efi_test_driver, + "6.8.0-40-generic", + ] mock_err.return_value = 0 - self.assertEqual(main(), 0) + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 0) @patch("dkms_build_validation.run_command") - @patch("dkms_build_validation.parse_dkms_status") - @patch("dkms_build_validation.check_kernel_version") - @patch("dkms_build_validation.check_dkms_module_count") @patch("dkms_build_validation.has_dkms_build_errors") - def test_main_different_kernel_version( - self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command - ): - mock_run_command.return_value = "output" - mock_parse.return_value = [] - mock_ver.return_value = 1 - mock_count.return_value = 0 + def test_main_with_warning(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 22.04", + self.dkms_status_with_warning, + "6.0.0-1011-oem", + ] mock_err.return_value = 0 - self.assertEqual(main(), 1) + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 0) @patch("dkms_build_validation.run_command") - @patch("dkms_build_validation.parse_dkms_status") - @patch("dkms_build_validation.check_kernel_version") - @patch("dkms_build_validation.check_dkms_module_count") @patch("dkms_build_validation.has_dkms_build_errors") - def test_main_with_dkms_build_errors( - self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command - ): - mock_run_command.return_value = "output" - mock_parse.return_value = [] - mock_ver.return_value = 0 - mock_count.return_value = 0 + def test_main_with_dkms_build_errors(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 22.04", + self.dkms_status, + "6.5.0-17-generic", + ] mock_err.return_value = 1 - self.assertEqual(main(), 1) + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 1) + + @patch("dkms_build_validation.run_command") + @patch("dkms_build_validation.has_dkms_build_errors") + def test_main_oem_focal(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "Release: 20.04", + self.dkms_status_oem_focal, + "5.15.0-117-generic", + ] + mock_err.return_value = 0 + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 0) + + @patch("dkms_build_validation.run_command") + @patch("dkms_build_validation.has_dkms_build_errors") + def test_main_stock_noble(self, mock_err, mock_run_command): + mock_run_command.side_effect = [ + "No LSB modules are available.\nRelease: 24.04", + self.dkms_status_stock_noble, + "6.8.0-44-generic", + ] + mock_err.return_value = 0 + result = main() + self.assertEqual(mock_err.call_count, 1) + self.assertEqual(result, 0)