/* * Copyright (c) Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef TESTS_AMD_SMI_TEST_TEST_COMMON_H_ #define TESTS_AMD_SMI_TEST_TEST_COMMON_H_ #include #include #include #include #include #include #include #include "amd_smi/amdsmi.h" #include "amd_smi/impl/amd_smi_utils.h" #include "test_base.h" struct AMDSMITstGlobals { uint32_t verbosity; uint32_t monitor_verbosity; uint32_t num_iterations; uint64_t init_options; bool dont_fail; }; uint32_t ProcessCmdline(AMDSMITstGlobals* test, int arg_cnt, char** arg_list); // Returns the global verbosity level set from the command line. // Can be used in plain TEST() cases that don't inherit from TestBase. uint32_t GetTestVerbosity(); void SetTestVerbosity(uint32_t verbosity); void PrintTestHeader(uint32_t dv_ind); const char* GetPerfLevelStr(amdsmi_dev_perf_level_t lvl); const char* GetBlockNameStr(amdsmi_gpu_block_t id); const char* GetErrStateNameStr(amdsmi_ras_err_state_t st); const char* FreqEnumToStr(amdsmi_clk_type_t amdsmi_clk); const std::string GetVoltSensorNameStr(amdsmi_voltage_type_t st); #if ENABLE_SMI void DumpMonitorInfo(const TestBase* test); #endif inline constexpr amdsmi_status_t NotSupportedErrorCodes[] = { AMDSMI_STATUS_NOT_SUPPORTED, AMDSMI_STATUS_NOT_YET_IMPLEMENTED, AMDSMI_STATUS_NO_HSMP_MSG_SUP}; inline void DISPLAY_AMDSMI_API(std::string_view func_name, std::string_view desc, bool isVerbose) { if (isVerbose) std::cout << "\t### " << (func_name) << "(" << (desc) << ")" << std::endl; return; } template inline void DISPLAY_AMDSMI_STATUS(bool isVerbose, std::string_view fileName, uint32_t lineNum, amdsmi_status_t returnCode, Args... args) { // Input: // isVerbose : Toggle for outputting to std_out // True : Allow printing // False: No printing // fileName : Name of file calling this routine // lineNum : Line number of function in file // returnCode : API return code // args : API Expected return code(s) // Must have at least 1, can be multiple // // Output: // isVerbose(true) : Print results // isVerbose(false) : No output // // Notes: // 1. The API returnCode is checked against all args, expected return codes. // If API returnCode matches any expected return codes, test passes with // TEST SUCCESS, AMDSMI API Returned 0, AMDSMI_STATUS_SUCCESS // 2. If the API returnCode is one of the Not Supported return codes // the test will pass with // TEST SUCCESS, AMDSMI API Returned 2, AMDSMI_STATUS_NOT_SUPPORTED // 3. If the API returnCode is not what was expected or not supported, // the test will fail with // TEST FAILURE, AMDSMI API Returned X1, AMDSMI_STATUS_XX1 // Expected X2, AMDSMI_STATUS_XX2 // where: // X1 API error code // XX1 API error code string // X2 API expected error code // XX2 API expected error code string // // TODO(amdsmi_team): // 1. Use this function to verify expected return codes and report failures // to testing framework // 2. Upon failures, alter test flow // 3. For not supported API's, allow function to mark as failures where applicable // // NOTE: This function currently only prints to stdout and does NOT call any // GTest assertion (ADD_FAILURE, EXPECT_*, etc.). Unexpected return codes // that are not in NotSupportedErrorCodes[] will silently pass CI unless // verbose output is reviewed for "TEST FAILURE" lines. See TODOs above // for planned GTest integration. amdsmi_status_t retExpected[] = {args...}; int numRetExpected = sizeof(retExpected) / sizeof(retExpected[0]); std::string status = smi_amdgpu_get_status_string(returnCode, false); amdsmi_status_t firstExpectedRet = retExpected[0]; // Check for successful (expected) return code for (int i = 0; i < numRetExpected; ++i) { if (returnCode == retExpected[i]) { if (isVerbose) std::cout << "\t===> TEST SUCCESS, AMDSMI API Returned " << returnCode << ", " << status << std::endl; return; } } // // Return code is not what was expected // Find and report error code // // Check if return code is in the not supported list int numNotSupportedErrorCodes = sizeof(NotSupportedErrorCodes) / sizeof(NotSupportedErrorCodes[0]); for (int i = 0; i < numNotSupportedErrorCodes; ++i) { if (returnCode == NotSupportedErrorCodes[i]) { if (isVerbose) std::cout << "\t===> TEST SUCCESS, AMDSMI API Returned " << returnCode << ", " << status << std::endl; return; } } // // Return code is not successful, print failure results // if (isVerbose) { std::string expectedStatus; std::cout << "\t===> TEST FAILURE, AMDSMI API Returned " << std::setfill(' ') << std::setw(2) << returnCode << ", " << status << std::endl; std::cout << "\t===> Expected "; if (numRetExpected == 1) { expectedStatus = smi_amdgpu_get_status_string(firstExpectedRet, false); std::cout << std::setfill(' ') << std::setw(2) << std::right << firstExpectedRet << ", " << expectedStatus << std::endl; } else { for (int i = 0; i < numRetExpected; ++i) { expectedStatus = smi_amdgpu_get_status_string(retExpected[i], false); if (i != 0) std::cout << "\t===> or "; std::cout << std::setfill(' ') << std::setw(2) << std::right << retExpected[i] << ", " << expectedStatus << std::endl; } std::cout << std::endl; } } // Display file path starting from root directory if (isVerbose) { std::string start_dir = std::string(fileName); size_t pos = start_dir.find("tests/amd_smi_test"); if (pos != std::string::npos) start_dir = start_dir.substr(pos); std::cout << "\t===> " << start_dir << ":" << std::dec << lineNum << std::endl; } return; } #endif // TESTS_AMD_SMI_TEST_TEST_COMMON_H_