@@ -2035,3 +2035,76 @@ def test_capture_nvidia_permission_error_on_gpu_file(self, mock_exists, mock_wal
20352035 self .mock_db .record_prereq .assert_called_with (
20362036 "NVIDIA GPU {f} not readable" , "👀"
20372037 )
2038+
2039+ @patch ("amd_debug.prerequisites.os.walk" )
2040+ @patch (
2041+ "builtins.open" ,
2042+ new_callable = unittest .mock .mock_open ,
2043+ read_data = b"C1 state info" ,
2044+ )
2045+ def test_capture_cstates_single_file (self , mock_open , mock_walk ):
2046+ """Test capture_cstates with a single cpuidle file"""
2047+ mock_walk .return_value = [
2048+ ("/sys/bus/cpu/devices/cpu0/cpuidle" , [], ["state1" ]),
2049+ ]
2050+ self .validator .capture_cstates ()
2051+ self .mock_db .record_debug .assert_called_with (
2052+ "ACPI C-state information\n └─/sys/bus/cpu/devices/cpu0/cpuidle/state1: C1 state info"
2053+ )
2054+
2055+ @patch ("amd_debug.prerequisites.os.walk" )
2056+ @patch ("builtins.open" , new_callable = mock_open )
2057+ def test_capture_cstates_multiple_files (self , mock_open_func , mock_walk ):
2058+ """Test capture_cstates with multiple cpuidle files"""
2059+ # Setup mock file reads for two files
2060+ file_contents = {
2061+ "/sys/bus/cpu/devices/cpu0/cpuidle/state1" : b"C1 info" ,
2062+ "/sys/bus/cpu/devices/cpu0/cpuidle/state2" : b"C2 info" ,
2063+ }
2064+
2065+ def side_effect (path , mode = "rb" ):
2066+ mock_file = mock_open (read_data = file_contents [path ])()
2067+ return mock_file
2068+
2069+ mock_open_func .side_effect = side_effect
2070+ mock_walk .return_value = [
2071+ ("/sys/bus/cpu/devices/cpu0/cpuidle" , [], ["state1" , "state2" ]),
2072+ ]
2073+ self .validator .capture_cstates ()
2074+ # The prefix logic is based on order, so check for both lines
2075+ debug_call = self .mock_db .record_debug .call_args [0 ][0 ]
2076+ self .assertIn ("/sys/bus/cpu/devices/cpu0/cpuidle/state1: C1 info" , debug_call )
2077+ self .assertIn ("/sys/bus/cpu/devices/cpu0/cpuidle/state2: C2 info" , debug_call )
2078+ self .assertTrue (debug_call .startswith ("ACPI C-state information\n " ))
2079+
2080+ @patch ("amd_debug.prerequisites.os.walk" )
2081+ @patch ("builtins.open" , new_callable = mock_open , read_data = b"" )
2082+ def test_capture_cstates_empty_files (self , _mock_open , mock_walk ):
2083+ """Test capture_cstates with empty cpuidle files"""
2084+ mock_walk .return_value = [
2085+ ("/sys/bus/cpu/devices/cpu0/cpuidle" , [], ["state1" ]),
2086+ ]
2087+ self .validator .capture_cstates ()
2088+ self .mock_db .record_debug .assert_called_with (
2089+ "ACPI C-state information\n └─/sys/bus/cpu/devices/cpu0/cpuidle/state1: "
2090+ )
2091+
2092+ @patch ("amd_debug.prerequisites.os.walk" )
2093+ @patch ("builtins.open" , side_effect = PermissionError )
2094+ def test_capture_cstates_permission_error (self , _mock_open , mock_walk ):
2095+ """Test capture_cstates when reading cpuidle files raises PermissionError"""
2096+ mock_walk .return_value = [
2097+ ("/sys/bus/cpu/devices/cpu0/cpuidle" , [], ["state1" ]),
2098+ ]
2099+ with self .assertRaises (PermissionError ):
2100+ self .validator .capture_cstates ()
2101+ self .mock_db .record_debug .assert_not_called ()
2102+
2103+ @patch ("amd_debug.prerequisites.os.walk" )
2104+ def test_capture_cstates_no_files (self , mock_walk ):
2105+ """Test capture_cstates when no cpuidle files are present"""
2106+ mock_walk .return_value = [
2107+ ("/sys/bus/cpu/devices/cpu0/cpuidle" , [], []),
2108+ ]
2109+ self .validator .capture_cstates ()
2110+ self .mock_db .record_debug .assert_called_with ("ACPI C-state information\n " )
0 commit comments