diff --git a/projects/amdsmi/tests/python_unittest/integration_test.py b/projects/amdsmi/tests/python_unittest/integration_test.py index 85d3c063a7..865a1718ec 100755 --- a/projects/amdsmi/tests/python_unittest/integration_test.py +++ b/projects/amdsmi/tests/python_unittest/integration_test.py @@ -30,6 +30,7 @@ except ImportError: import unittest import threading import multiprocessing +import time from datetime import datetime # Note: amdsmi_status_code_to_string is not tested due to the nature and functionality of the AMDSMI Python wrapper. @@ -80,6 +81,313 @@ class TestAmdSmiPythonInterface(unittest.TestCase): def tearDown(self): amdsmi.amdsmi_shut_down() + #Results of test can return 1 of 3 values per functional group: + # Pass: Test ran to completion with no errors + # Fail: Test ran to completion with 1 or more errors + # PassNA: Test cannot be run on this platform + # Hardware is not present. Ex. Trying to test fan speed when no fans are present + # ASIC not supported for this test + # FailEx: Test did not finish + # An uncaught exception occurred + # Test was interrupted. Ex. power failure or User input + + Pass = 0 + Not_Supported = 1 + Fail = 2 + Exception = 3 + + def Print(self, string='', myend='\n'): + tab_len = 4 + if myend == '\n': + print(string.expandtabs(tab_len)) + else: + print(string.expandtabs(tab_len), end=myend) + return + + # Return a value between min and max that is not current or default + def GetUniqueValue(self, current_value, min_value, max_value, default_value): + avg_value = int((min_value + max_value) / 2.0) + value = avg_value + if value != current_value and value != default_value: + return value + value = int(avg_value * 1.10) + if value >= max_value: + value = max_value -1 + if value == current_value or value == default_value: + value = int(avg_value * 0.90) + if value <= min_value: + value = min_value +1 + if value == current_value or value == default_value: + value = avg_value + return value + + def GetUniqueIndex(self, current_index, min_index, max_index, default_index): + avg_index = int(round((min_value + max_value) / 2.0)) + index = avg_index + while(index < max_index): + if index != current_index and index != default_index: + return index + index += 1 + index = avg_index + while(index > min_index): + if index != current_index and index != default_index: + return index + index -= 1 + index = avg_index + return index + + def VerifySetByEnum(self, funcGetValue, funcSetValue, gpu, values, value_default=None): + if not value_default: + value_default = funcGetValue(gpu) + self.Print(f'\t\t{"default"}: {values[value_default][0]}\n') + + num_pass = 0 + num_passNA = 0 + num_fail = 0 + num_failEx = 0 + for value in values: + try: + value_before = funcGetValue(gpu) + rc = funcSetValue(gpu, values[value][1]) + if rc: + if values[value][2] == self.Exception: + num_pass += 1 + self.Print(f'\t\t Set: {values[value][0]} Expected exception thrown') + self.Print(f'\t\tPass') + elif values[value][2] == self.Not_Supported: + num_passNA += 1 + self.Print(f'\t\t Set: {values[value][0]} Not Supported') + self.Print(f'\t\tPassNA') + else: + self.Print(f'\t\t Set: {values[value][0]} Exception thrown') + num_failEx += 1 + self.Print(f'\t\tFailEx') + self.Print(f'') + continue + value_after = funcGetValue(gpu) + except: + self.Print(f'Unexpected Exception occurred') + num_failEx += 1 + + self.Print(f'\t\tBefore: {values[value_before][0]}') + self.Print(f'\t\t Set: {values[value][0]}') + self.Print(f'\t\t After: {values[value_after][0]}') + if value == value_after: + num_pass += 1 + self.Print(f'\t\tPass') + else: + num_fail += 1 + self.Print(f'\t\tFail') + self.Print(f'') + + funcSetValue(gpu, values[value_default][1]) + return (num_pass, num_passNA, num_fail, num_failEx) + + #Get, Set, Get + # Get initial value + # Pass expected: (Change set values) + # Set to valid value, check + # Set to max value, check + # Set to min value, check + # Fail expected: (Change set values) + # Set to max+1 value, check + # Set to max*100 value, check + # Set to min-1 or 0 whichever value is valid, check + # Set to min-min*100 or 0 whichever value is valid, check + # Do a zero check, min may not accept negative values + # Set to initial value, check + # + #Get, Reset, Get + # Get initial value + # Reset, check + # Set to initial value, check + # + #Get, Set, Get, Reset, Get + # Get initial value + # Set Max/Min, check + # Reset, check + # Set initial value, check + # + def GetSetGet_ByValue(self, funcInfo, funcGetValue, funcSetValue, gpu, arg1=None): + def _GetSetGet(gpu, value_new, arg1): + msg = None + value_before = funcGetValue(gpu, arg1) + try: + funcSetValue(gpu, value_new, arg1) + except: + msg = '\t\tException occured' + value_after = funcGetValue(gpu, arg1) + self.Print(f'\t\tBefore: {value_before}') + self.Print(f'\t\t Set: {value_new}') + self.Print(f'\t\t After: {value_after}') + if msg: + self.Print(msg) + return (value_before, value_new, value_after) + + num_pass = 0 + num_fail = 0 + + value_current, value_min, value_max, value_default = funcInfo(gpu, arg1) + if value_min == value_max: + self.Print(f'Error: Min == Max, {value_min}, cannot be the same') + return (num_pass, num_fail) + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Set to valid value') + value_new = self.GetUniqueValue(value_current, value_min, value_max, value_default) + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected current({value_new}) == after({value_after})') + if value_new == value_after: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Set to max value') + value_new = value_max + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected current({value_new}) == after({value_after})') + if value_new == value_after: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Set to min value') + value_new = value_min + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected current({value_new}) == after({value_after})') + if value_new == value_after: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Set to max+1 value') + value_new = value_max +1 + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected after({value_after}) == before({value_before})') + if value_after == value_before: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Set to max*100 value') + value_new = value_max * 100 + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected after({value_after}) == before({value_before})') + if value_after == value_before: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Fail: Set to max(0, min-1)') + value_new = max(0, value_min -1) + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected after({value_after}) == before({value_before})') + if value_after == value_before: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get, Fail: Set to max(0, min-min*100)') + value_new = max(0, value_min - value_min*100) + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected after({value_after}) == before({value_before})') + if value_after == value_before: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Reset Get, Pass') + value_new = value_default + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected default({value_new}) == after({value_after})') + if value_default == value_after: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + + self.Print('#'*50) + self.Print(f'\tTest Get Set Get Reset Get, Pass') + value_new = self.GetUniqueValue(value_current, value_min, value_max, value_default) + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected current({value_new}) == after({value_after})') + if value_new == value_after: + value_new = value_default + value_before, value_new, value_after = _GetSetGet(gpu, value_new, arg1) + self.Print(f'\tExpected default({value_new}) == after({value_after})') + if value_default == value_after: + num_pass += 1 + self.Print(f'\tPass') + else: + num_fail += 1 + self.Print(f'\tFail') + else: + num_fail += 1 + self.Print(f'\tFail') + + # Return machine to default value + funcSetValue(gpu, value_default, arg1) + + return (num_pass, num_fail) + + + def GetSetGet_ByIndex(self, funcInfo, funcGetValue, funcSetValue, gpu, arg1=None): + pass + + + def GetSetGet_ByBitmask(self, funcInfo, funcGetValue, funcSetValue, gpu, arg1=None): + pass + +#jcnii + @handle_exceptions + def test_XXX(self): + def Get_XXX_Info(gpu, arg1=0): + try: + value_current = amdsmi.amdsmi_get_XXX(gpu, arg1) + value_min = 0 + value_max = 0 + value_default = 0 + # value_rpms = amdsmi.amdsmi_get_gpu_fan_rpms(gpu, arg1) + except: + value_current = 0 + value_min = 0 + value_max = 0 + value_default = 0 + return (value_current, value_min, value_max, value_default) + def Get_XXX_Value(gpu, arg1=0): + value_current = amdsmi.amdsmi_XXX(gpu, arg1) + return value_current + def Set_XXX_Value(gpu, value, arg1=0): + amdsmi.amdsmi_set_XXX(gpu, arg1, value) + return + + funcInfo = Get_XXX_Info + funcGetValue = Get_XXX_Value + funcSetValue = Set_XXX_Value + return + def test_asic_kfd_info(self): self.setUp() processors = amdsmi.amdsmi_get_processor_handles() @@ -347,6 +655,210 @@ class TestAmdSmiPythonInterface(unittest.TestCase): print() self.tearDown() + #frequencies_read_write + # amdsmi_get_clk_freq() + # amdsmi_set_clk_freq() + # amdsmi_set_gpu_clk_range() # deprecated + # amdsmi_set_gpu_clk_limit() + # TODO: Needs work + @handle_exceptions + def test_clock_freq_NEW(self): + def Get_Clock_Info(gpu, clock_type): + try: + # Gets values + info = amdsmi.amdsmi_get_clock_info(gpu, clock_type) + value_current = info['clk'] + value_min = info['min_clk'] + value_max = info['max_clk'] + value_default = 0 + #clk_locked = info['clk_locked'] + #clk_deep_sleep = info['clk_deep_sleep'] + except: + value_current = 0 + value_min = 0 + value_max = 0 + value_default = 0 + return (value_current, value_min, value_max, value_default) + def Set_Clock_Info(gpu, value_min, value_max, clock_type): + try: + # amdsmi.amdsmi_set_gpu_clk_range(gpu, value_min, value_max, clock_type) + amdsmi.amdsmi_set_gpu_clk_limit(gpu, clock_type, amdsmi.CLK_LIMIT_MIN, value_min) + amdsmi.amdsmi_set_gpu_clk_limit(gpu, clock_type, amdsmi.CLK_LIMIT_MAX, value_max) + except: + self.Print('\t\tException thrown') + return (value_current, value_min, value_max, value_default) + def Get_Clock_Value(gpu, clock_type): + try: + info = amdsmi.amdsmi_get_clk_freq(gpu, clock_type) + except: + return -1, 0, [], 0 + + num_supported = info['num_supported'] + current = info['current'] + frequency = info['frequency'] + if not num_supported or current < 0 or current >= num_supported: + return -1, 0, [], 0 + value_current = round(frequency[current] / 100000.0) + return num_supported, current, frequency, value_current + def Set_Clock_Value(gpu, value_bitmask, clock_type): + try: + amdsmi.amdsmi_set_clk_freq(gpu, clock_type, value_bitmask) + except: + self.Print('\t\tException thrown') + pass + return + + funcInfo = Get_Clock_Info + funcGetValue = Get_Clock_Value + funcSetValue = Set_Clock_Value + + clock_types = \ + [ + ['SYS', amdsmi.AmdSmiClkType.SYS], + ['GFX', amdsmi.AmdSmiClkType.GFX], + ['DF', amdsmi.AmdSmiClkType.DF], + ['DCEF', amdsmi.AmdSmiClkType.DCEF], + ['SOC', amdsmi.AmdSmiClkType.SOC], + ['MEM', amdsmi.AmdSmiClkType.MEM], + ['PCIE', amdsmi.AmdSmiClkType.PCIE], + ['VCLK0', amdsmi.AmdSmiClkType.VCLK0], + ['VCLK1', amdsmi.AmdSmiClkType.VCLK1], + ['DCLK0', amdsmi.AmdSmiClkType.DCLK0], + ['DCLK1', amdsmi.AmdSmiClkType.DCLK1] + ] + + self.setUp() + processors = amdsmi.amdsmi_get_processor_handles() + self.assertGreaterEqual(len(processors), 1) + self.assertLessEqual(len(processors), 32) + self.Print() + self.Print('#'*80) + self.Print('Test clock_freq') + for clock_name, clock_type in clock_types: + num_pass = 0 + num_passNA = 0 + num_fail = 0 + num_failEx = 0 + for i in range(0, len(processors)): + amdsmi.amdsmi_set_gpu_perf_level(processors[i], amdsmi.AmdSmiDevPerfLevel.MANUAL) + time.sleep(1) + self.Print('#'*50) + self.Print(f'\tClock Info(gpu={i}, clock_type={clock_name})') + value_current, value_min, value_max, value_default = funcInfo(processors[i], clock_type) + str_len = len('default') + self.Print(f'\t\t{"current":{str_len}s}: {value_current}') + self.Print(f'\t\t{"min":{str_len}s}: {value_min}') + self.Print(f'\t\t{"max":{str_len}s}: {value_max}') + self.Print(f'\t\t{"default":{str_len}s}: {value_default}') + + _num_pass = [] + _num_passNA = [] + _num_fail = [] + _num_failEx = [] + + num_supported, current, frequency, value_current = Get_Clock_Value(processors[i], clock_type) + self.Print(f'\t\tTest clock {clock_name}, {num_supported} frequencies') + if num_supported < 0: + self.Print('\t\t\tNot Supported') + _num_passNA.append(0) + for j in range(num_supported): + try: + Set_Clock_Value(processors[i], 1<= 0: + Set_Clock_Value(processors[i], 1<<0, clock_type) + + self.Print() + self.Print(f'\tPass : {num_pass:2d}') + self.Print(f'\tPassNA : {num_passNA:2d}') + self.Print(f'\tFail : {num_fail:2d}') + self.Print(f'\tFailEx : {num_failEx:2d}') + self.Print() + self.tearDown() + return + + #perf_level_read_write + # amdsmi_get_gpu_perf_level() + # amdsmi_set_gpu_perf_level() + @handle_exceptions + def test_gpu_perf_level_NEW(self): + def Get_Perf_Level_Value(gpu): + value_current = amdsmi.amdsmi_get_gpu_perf_level(gpu) + return value_current + def Set_Perf_Level_Value(gpu, perf_level): + #Return: + # pass = 0 + # fail = 1 + # fail = 2 exception + try: + amdsmi.amdsmi_set_gpu_perf_level(gpu, perf_level) + except: + return 2 + return 0 + + funcGetValue = Get_Perf_Level_Value + funcSetValue = Set_Perf_Level_Value + + perf_levels = \ + { + "AMDSMI_DEV_PERF_LEVEL_AUTO": ['AUTO', amdsmi.AmdSmiDevPerfLevel.AUTO, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_LOW": ['LOW', amdsmi.AmdSmiDevPerfLevel.LOW, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_HIGH": ['HIGH', amdsmi.AmdSmiDevPerfLevel.HIGH, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_MANUAL": ['MANUAL', amdsmi.AmdSmiDevPerfLevel.MANUAL, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_STABLE_STD": ['STABLE_STD', amdsmi.AmdSmiDevPerfLevel.STABLE_STD, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_STABLE_PEAK": ['STABLE_PEAK', amdsmi.AmdSmiDevPerfLevel.STABLE_PEAK, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_STABLE_MIN_MCLK": ['STABLE_MIN_MCLK', amdsmi.AmdSmiDevPerfLevel.STABLE_MIN_MCLK, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_STABLE_MIN_SCLK": ['STABLE_MIN_SCLK', amdsmi.AmdSmiDevPerfLevel.STABLE_MIN_SCLK, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_DETERMINISM": ['DETERMINISM', amdsmi.AmdSmiDevPerfLevel.DETERMINISM, self.Pass], + "AMDSMI_DEV_PERF_LEVEL_UNKNOWN": ['UNKNOWN', amdsmi.AmdSmiDevPerfLevel.UNKNOWN, self.Exception] + } + + self.setUp() + processors = amdsmi.amdsmi_get_processor_handles() + self.assertGreaterEqual(len(processors), 1) + self.assertLessEqual(len(processors), 32) + self.Print() + self.Print('#'*80) + self.Print('Test GPU Perf Levels') + for i in range(0, len(processors)): + self.Print('#'*50) + self.Print(f'\tPerf Level({i})') + num_pass, num_passNA, num_fail, num_failEx = self.VerifySetByEnum(funcGetValue, funcSetValue, processors[i], perf_levels, 'AMDSMI_DEV_PERF_LEVEL_MANUAL') + self.Print() + self.Print(f'\tPass : {num_pass:2d}') + self.Print(f'\tPassNA : {num_passNA:2d}') + self.Print(f'\tFail : {num_fail:2d}') + self.Print(f'\tFailEx : {num_failEx:2d}') + self.Print() + self.tearDown() + return + def test_driver_info(self): self.setUp() processors = amdsmi.amdsmi_get_processor_handles() @@ -541,32 +1053,136 @@ class TestAmdSmiPythonInterface(unittest.TestCase): self.assertLessEqual(len(processors), 32) for i in range(0, len(processors)): bdf = amdsmi.amdsmi_get_gpu_device_bdf(processors[i]) - print("\n\n###Test Processor {}, bdf: {}".format(i, bdf)) - print("\n###Test amdsmi_get_power_info \n") + self.Print(f'\n\n###Test Processor {i}, bdf: {bdf}') + self.Print('\n###Test amdsmi_get_power_info\n') power_info = amdsmi.amdsmi_get_power_info(processors[i]) - print(" power_info['current_socket_power'] is: {}".format( - power_info['current_socket_power'])) - print(" power_info['average_socket_power'] is: {}".format( - power_info['average_socket_power'])) - print(" power_info['gfx_voltage'] is: {}".format( - power_info['gfx_voltage'])) - print(" power_info['soc_voltage'] is: {}".format( - power_info['soc_voltage'])) - print(" power_info['mem_voltage'] is: {}".format( - power_info['mem_voltage'])) - print(" power_info['power_limit'] is: {}".format( - power_info['power_limit'])) - print("\n###Test amdsmi_get_power_cap_info \n") + self.Print(f'\tcurrent_socket_power is: {power_info["current_socket_power"]}') + self.Print(f'\taverage_socket_power is: {power_info["average_socket_power"]}') + self.Print(f'\tgfx_voltage is: {power_info["gfx_voltage"]}') + self.Print(f'\tsoc_voltage is: {power_info["soc_voltage"]}') + self.Print(f'\tmem_voltage is: {power_info["mem_voltage"]}') + self.Print(f'\tpower_limit is: {power_info["power_limit"]}') + self.Print('\n###Test amdsmi_get_power_cap_info\n') power_cap_info = amdsmi.amdsmi_get_power_cap_info(processors[i]) - print(" power_info['dpm_cap'] is: {}".format( - power_cap_info['dpm_cap'])) - print(" power_info['power_cap'] is: {}".format( - power_cap_info['power_cap'])) - print("\n###Test amdsmi_is_gpu_power_management_enabled \n") + self.Print(f'\tdpm_cap is: {power_cap_info["dpm_cap"]}') + self.Print(f'\tpower_cap is: {power_cap_info["power_cap"]}') + self.Print('\n###Test amdsmi_is_gpu_power_management_enabled \n') is_power_management_enabled = amdsmi.amdsmi_is_gpu_power_management_enabled(processors[i]) - print(" Power management enabled: {}".format( - is_power_management_enabled)) - print() + self.Print('\tPower management enabled: {is_power_management_enabled}') + self.Print() + self.tearDown() + return + + #power_cap_read_write + # amdsmi_get_power_cap_info() + # amdsmi_set_power_cap() + # amdsmi_set_power_cap() + @handle_exceptions + def test_power_cap_NEW(self): + def Get_Power_Info(gpu, arg1=None): + try: + info = amdsmi.amdsmi_get_power_cap_info(gpu) + value_current = info['power_cap'] + value_min = info['min_power_cap'] + value_max = info['max_power_cap'] + value_default = info['default_power_cap'] + except: + value_current = 0 + value_min = 0 + value_max = 0 + value_default = 0 + return (value_current, value_min, value_max, value_default) + def Get_Power_Value(gpu, arg1=None): + value_current, _, _, _ = Get_Power_Info(gpu, arg1) + return value_current + def Set_Power_Value(gpu, value, arg1=0): + amdsmi.amdsmi_set_power_cap(gpu, arg1, value) + return + + funcInfo = Get_Power_Info + funcGetValue = Get_Power_Value + funcSetValue = Set_Power_Value + + self.setUp() + processors = amdsmi.amdsmi_get_processor_handles() + self.assertGreaterEqual(len(processors), 1) + self.assertLessEqual(len(processors), 32) + self.Print() + self.Print('#'*80) + self.Print('Test power_cap') + for i in range(0, len(processors)): + self.Print('#'*50) + self.Print(f'\tPower Cap Info({i})') + value_current, value_min, value_max, value_default = funcInfo(processors[i]) + str_len = len('default') + self.Print(f'\t\t{"current":{str_len}s}: {value_current}') + self.Print(f'\t\t{"min":{str_len}s}: {value_min}') + self.Print(f'\t\t{"max":{str_len}s}: {value_max}') + self.Print(f'\t\t{"default":{str_len}s}: {value_default}') + num_pass, num_fail = self.GetSetGet_ByValue(funcInfo, funcGetValue, funcSetValue, processors[i], 0) + + self.Print() + self.Print(f'\tPass : {num_pass:2d}') + self.Print(f'\tFail : {num_fail:2d}') + self.Print() + self.tearDown() + return + + #fan_read_write + # amdsmi_get_gpu_fan_speed() + # amdsmi_get_gpu_fan_speed_max() + # amdsmi_get_gpu_fan_rpms() + # amdsmi_set_gpu_fan_speed() + # amdsmi_reset_gpu_fan() + # TODO: Needs work + @handle_exceptions + def test_fan_speed_NEW(self): + def Get_Fan_Info(gpu, arg1=0): + try: + value_current = amdsmi.amdsmi_get_gpu_fan_speed(gpu, arg1) + value_min = 0 + value_max = amdsmi.amdsmi_get_gpu_fan_speed_max(gpu, arg1) + value_default = 0 + # value_rpms = amdsmi.amdsmi_get_gpu_fan_rpms(gpu, arg1) + except: + value_current = 0 + value_min = 0 + value_max = 0 + value_default = 0 + return (value_current, value_min, value_max, value_default) + def Get_Fan_Value(gpu, arg1=0): + value_current = amdsmi.amdsmi_get_gpu_fan_speed(gpu, arg1) + return value_current + def Set_Fan_Value(gpu, value, arg1=0): + amdsmi.amdsmi_set_gpu_fan_speed(gpu, arg1, value) + return + + funcInfo = Get_Fan_Info + funcGetValue = Get_Fan_Value + funcSetValue = Set_Fan_Value + + self.setUp() + processors = amdsmi.amdsmi_get_processor_handles() + self.assertGreaterEqual(len(processors), 1) + self.assertLessEqual(len(processors), 32) + self.Print() + self.Print('#'*80) + self.Print('Test fan_speed') + for i in range(0, len(processors)): + self.Print('#'*50) + self.Print(f'\tFan Info({i})') + value_current, value_min, value_max, value_default = funcInfo(processors[i], 0) + str_len = len('default') + self.Print(f'\t\t{"current":{str_len}s}: {value_current}') + self.Print(f'\t\t{"min":{str_len}s}: {value_min}') + self.Print(f'\t\t{"max":{str_len}s}: {value_max}') + self.Print(f'\t\t{"default":{str_len}s}: {value_default}') + num_pass, num_fail = self.GetSetGet_ByValue(funcInfo, funcGetValue, funcSetValue, processors[i], 0) + + self.Print() + self.Print(f'\tPass : {num_pass:2d}') + self.Print(f'\tFail : {num_fail:2d}') + self.Print() self.tearDown() def test_process_list(self):