compute-runtime/shared/test/common/common_main.cpp

467 lines
16 KiB
C++

/*
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/device/device.h"
#include "shared/source/gmm_helper/gmm_helper.h"
#include "shared/source/gmm_helper/gmm_interface.h"
#include "shared/source/helpers/api_specific_config.h"
#include "shared/source/utilities/cpu_info.h"
#include "shared/source/utilities/debug_settings_reader.h"
#include "shared/source/utilities/logger.h"
#include "shared/test/common/helpers/custom_event_listener.h"
#include "shared/test/common/helpers/default_hw_info.inl"
#include "shared/test/common/helpers/kernel_binary_helper.h"
#include "shared/test/common/helpers/memory_leak_listener.h"
#include "shared/test/common/helpers/test_files.h"
#include "shared/test/common/helpers/ult_hw_config.inl"
#include "shared/test/common/helpers/virtual_file_system_listener.h"
#include "shared/test/common/libult/global_environment.h"
#include "shared/test/common/libult/signal_utils.h"
#include "shared/test/common/mocks/mock_gmm_client_context.h"
#include "shared/test/common/mocks/mock_sip.h"
#include "shared/test/common/test_macros/test_checks_shared.h"
#include "shared/test/common/test_stats.h"
#include "shared/test/common/tests_configuration.h"
#include "gtest/gtest.h"
#include "hw_cmds_default.h"
#include <fstream>
#include <iostream>
#include <mutex>
#include <thread>
namespace NEO {
namespace PagaFaultManagerTestConfig {
bool disabled = false;
}
extern const char *executionDirectorySuffix;
extern bool useMockGmm;
#ifdef WIN32
const char *fSeparator = "\\";
#else
const char *fSeparator = "/";
#endif
bool checkAubTestsExecutionPathValidity() {
bool valid = true;
if ((testMode == TestMode::aubTests || testMode == TestMode::aubTestsWithTbx)) {
std::ofstream testFile;
std::string aubPath = folderAUB;
aubPath += fSeparator;
aubPath += "testAubFolder";
testFile.open(aubPath, std::ofstream::app);
if (testFile.is_open()) {
testFile.close();
} else {
valid = false;
std::cout << "ERROR: Aub tests must be run in directory containing \" " << folderAUB << "\" folder!\n";
}
}
return valid;
}
} // namespace NEO
using namespace NEO;
extern PRODUCT_FAMILY productFamily;
extern GFXCORE_FAMILY renderCoreFamily;
void applyWorkarounds();
bool isPlatformSupported(const HardwareInfo &hwInfoForTests);
void setupTestFiles(std::string testBinaryFiles, int32_t revId);
std::string getBaseExecutionDir();
void addUltListener(::testing::TestEventListeners &listener);
void cleanTestHelpers();
bool generateRandomInput = false;
std::string getRunPath(char *argv0) {
std::string res(argv0);
auto pos = res.rfind(fSeparator);
if (pos != std::string::npos)
res = res.substr(0, pos);
if (res == "." || pos == std::string::npos) {
char *cwd;
#if defined(__linux__)
cwd = getcwd(nullptr, 0);
#else
cwd = _getcwd(nullptr, 0);
#endif
res = cwd;
free(cwd);
}
return res;
}
std::thread::id tempThreadID;
void applyCommonWorkarounds() {
{
std::ofstream f;
const std::string fileName("_tmp_");
f.open(fileName, std::ofstream::binary);
f.close();
}
{
std::mutex mtx;
std::unique_lock<std::mutex> stateLock(mtx);
}
{
std::stringstream ss("1");
int val;
ss >> val;
}
// intialize rand
srand(static_cast<unsigned int>(time(nullptr)));
// Create at least on thread to prevent false memory leaks in tests using threads
std::thread t([&]() {
});
tempThreadID = t.get_id();
t.join();
// Create FileLogger to prevent false memory leaks
{
NEO::fileLoggerInstance();
}
}
bool enableAlarm = true;
int main(int argc, char **argv) {
int retVal = 0;
bool useDefaultListener = false;
bool enableAbrt = true;
bool enableSegv = true;
bool showTestStats = false;
bool dumpTestStats = false;
std::string dumpTestStatsFileName = "";
applyWorkarounds();
applyCommonWorkarounds();
CpuInfo::cpuidexFunc = [](int *, int, int) -> void {};
CpuInfo::cpuidFunc = [](int[4], int) -> void {};
#if defined(__linux__)
if (getenv("IGDRCL_TEST_SELF_EXEC") == nullptr) {
std::string wd = getRunPath(argv[0]);
char *ldLibraryPath = getenv("LD_LIBRARY_PATH");
if (ldLibraryPath == nullptr) {
setenv("LD_LIBRARY_PATH", wd.c_str(), 1);
} else {
std::string ldLibraryPathConcat = wd + ":" + std::string(ldLibraryPath);
setenv("LD_LIBRARY_PATH", ldLibraryPathConcat.c_str(), 1);
}
setenv("IGDRCL_TEST_SELF_EXEC", wd.c_str(), 1);
execv(argv[0], argv);
printf("FATAL ERROR: cannot self-exec test: %s!, errno: %d\n", argv[0], errno);
return -1;
}
#endif
::testing::InitGoogleTest(&argc, argv);
HardwareInfo hwInfoForTests = DEFAULT_TEST_PLATFORM::hwInfo;
uint32_t euPerSubSlice = 0;
uint32_t sliceCount = 0;
uint32_t subSlicePerSliceCount = 0;
int32_t revId = -1;
int32_t devId = -1;
int dieRecovery = 0;
bool productOptionSelected = false;
std::vector<PRODUCT_FAMILY> selectedTestProducts;
auto baseTestFiles = testFiles;
auto baseTestFilesApiSpecific = testFilesApiSpecific;
for (int i = 1; i < argc; ++i) {
if (!strcmp("--disable_default_listener", argv[i])) {
useDefaultListener = false;
} else if (!strcmp("--enable_default_listener", argv[i])) {
useDefaultListener = true;
} else if (!strcmp("--disable_alarm", argv[i])) {
enableAlarm = false;
} else if (!strcmp("--show_test_stats", argv[i])) {
showTestStats = true;
} else if (!strcmp("--dump_test_stats", argv[i])) {
dumpTestStats = true;
++i;
dumpTestStatsFileName = std::string(argv[i]);
} else if (!strcmp("--disable_pagefaulting_tests", argv[i])) { // disable tests which raise page fault signal during execution
NEO::PagaFaultManagerTestConfig::disabled = true;
} else if (!strcmp("--tbx", argv[i])) {
if (isAubTestMode(testMode)) {
testMode = TestMode::aubTestsWithTbx;
}
initialHardwareTag = 0;
} else if (!strcmp("--rev_id", argv[i])) {
++i;
if (i < argc) {
revId = atoi(argv[i]);
}
} else if (!strcmp("--dev_id", argv[i])) {
++i;
if (i < argc) {
devId = static_cast<int32_t>(strtol(argv[i], nullptr, 16));
}
} else if (!strcmp("--product", argv[i])) {
++i;
if (i < argc) {
if (::isdigit(argv[i][0])) {
int productValue = atoi(argv[i]);
if (productValue > 0 && productValue < IGFX_MAX_PRODUCT && hardwarePrefix[productValue] != nullptr) {
productFamily = static_cast<PRODUCT_FAMILY>(productValue);
} else {
productFamily = IGFX_UNKNOWN;
}
} else {
bool selectAllProducts = (strcmp("*", argv[i]) == 0);
productFamily = IGFX_UNKNOWN;
for (int j = 0; j < IGFX_MAX_PRODUCT; j++) {
if (hardwarePrefix[j] == nullptr)
continue;
if ((strcmp(hardwarePrefix[j], argv[i]) == 0) || selectAllProducts) {
productFamily = static_cast<PRODUCT_FAMILY>(j);
selectedTestProducts.push_back(productFamily);
if (!selectAllProducts) {
break;
}
}
}
}
if (productFamily == IGFX_UNKNOWN) {
std::cout << "unknown or unsupported product family has been set: " << argv[i] << std::endl;
return -1;
} else {
std::cout << "product family: " << hardwarePrefix[productFamily] << " (" << productFamily << ")" << std::endl;
}
hwInfoForTests = *hardwareInfoTable[productFamily];
productOptionSelected = true;
}
} else if (!strcmp("--slices", argv[i])) {
++i;
if (i < argc) {
sliceCount = atoi(argv[i]);
}
} else if (!strcmp("--subslices", argv[i])) {
++i;
if (i < argc) {
subSlicePerSliceCount = atoi(argv[i]);
}
} else if (!strcmp("--eu_per_ss", argv[i])) {
++i;
if (i < argc) {
euPerSubSlice = atoi(argv[i]);
}
} else if (!strcmp("--die_recovery", argv[i])) {
++i;
if (i < argc) {
dieRecovery = atoi(argv[i]) ? 1 : 0;
}
} else if (!strcmp("--generate_random_inputs", argv[i])) {
generateRandomInput = true;
} else if (!strcmp("--read-config", argv[i]) && isAubTestMode(testMode)) {
if (debugManager.registryReadAvailable()) {
debugManager.setReaderImpl(SettingsReader::create(ApiSpecificConfig::getRegistryPath()));
debugManager.injectSettingsFromReader();
}
} else if (!strcmp("--dump_buffer_format", argv[i]) && isAubTestMode(testMode)) {
++i;
std::string dumpBufferFormat(argv[i]);
std::transform(dumpBufferFormat.begin(), dumpBufferFormat.end(), dumpBufferFormat.begin(), ::toupper);
debugManager.flags.AUBDumpBufferFormat.set(dumpBufferFormat);
} else if (!strcmp("--dump_image_format", argv[i]) && isAubTestMode(testMode)) {
++i;
std::string dumpImageFormat(argv[i]);
std::transform(dumpImageFormat.begin(), dumpImageFormat.end(), dumpImageFormat.begin(), ::toupper);
debugManager.flags.AUBDumpImageFormat.set(dumpImageFormat);
} else if (!strcmp("--null_aubstream", argv[i])) {
if (isAubTestMode(testMode)) {
testMode = TestMode::aubTestsWithoutOutputFiles;
}
initialHardwareTag = 0;
}
}
if (!productOptionSelected) {
selectedTestProducts.push_back(hwInfoForTests.platform.eProductFamily);
}
auto &listeners = ::testing::UnitTest::GetInstance()->listeners();
auto defaultListener = listeners.default_result_printer();
defaultHwInfo = std::make_unique<HardwareInfo>();
CCustomEventListener *customEventListener = nullptr;
bool ultListenersInitialized = false;
bool gmmInitialized = false;
bool sipInitialized = false;
adjustCsrType(testMode);
for (auto &selectedProduct : selectedTestProducts) {
hwInfoForTests = *hardwareInfoTable[selectedProduct];
productFamily = hwInfoForTests.platform.eProductFamily;
renderCoreFamily = hwInfoForTests.platform.eRenderCoreFamily;
PLATFORM &platform = hwInfoForTests.platform;
auto testRevId = revId;
auto testDevId = devId;
if (testRevId != -1) {
platform.usRevId = testRevId;
} else {
testRevId = platform.usRevId;
}
if (testDevId != -1) {
platform.usDeviceID = testDevId;
}
adjustHwInfoForTests(hwInfoForTests, euPerSubSlice, sliceCount, subSlicePerSliceCount, dieRecovery);
// Platforms with uninitialized factory are not supported
if (!isPlatformSupported(hwInfoForTests)) {
std::cout << "unsupported product family has been set: " << NEO::hardwarePrefix[::productFamily] << std::endl;
std::cout << "skipping tests" << std::endl;
return 0;
}
binaryNameSuffix = hardwarePrefix[hwInfoForTests.platform.eProductFamily];
testFiles = baseTestFiles;
testFilesApiSpecific = baseTestFilesApiSpecific;
setupTestFiles(getRunPath(argv[0]), testRevId);
auto executionDirectory = getBaseExecutionDir();
executionDirectory += hardwarePrefix[productFamily];
executionDirectory += NEO::executionDirectorySuffix; // _aub for aub_tests, empty otherwise
executionDirectory += "/";
executionDirectory += std::to_string(testRevId);
#ifdef WIN32
#include <direct.h>
if (_chdir(executionDirectory.c_str())) {
std::cout << "chdir into " << executionDirectory << " directory failed.\nThis might cause test failures." << std::endl;
}
#elif defined(__linux__)
#include <unistd.h>
if (chdir(executionDirectory.c_str()) != 0) {
std::cout << "chdir into " << executionDirectory << " directory failed.\nThis might cause test failures." << std::endl;
}
#endif
if (!checkAubTestsExecutionPathValidity()) {
return -1;
}
*defaultHwInfo = hwInfoForTests;
if (!useDefaultListener) {
if (!customEventListener) {
customEventListener = new CCustomEventListener(defaultListener);
}
customEventListener->setHwPrefix(hardwarePrefix[productFamily]);
}
if (!ultListenersInitialized) {
if (!useDefaultListener) {
listeners.Release(defaultListener);
listeners.Append(customEventListener);
}
listeners.Append(new MemoryLeakListener);
listeners.Append(new NEO::VirtualFileSystemListener);
addUltListener(listeners);
ultListenersInitialized = true;
}
if (!gEnvironment) {
gEnvironment = reinterpret_cast<TestEnvironment *>(::testing::AddGlobalTestEnvironment(new TestEnvironment));
}
MockCompilerDebugVars fclDebugVars;
MockCompilerDebugVars igcDebugVars;
std::string builtInsFileName;
if (TestChecks::supportsImages(defaultHwInfo)) {
builtInsFileName = KernelBinaryHelper::BUILT_INS_WITH_IMAGES;
} else {
builtInsFileName = KernelBinaryHelper::BUILT_INS;
}
retrieveBinaryKernelFilename(fclDebugVars.fileName, builtInsFileName + "_", ".spv");
retrieveBinaryKernelFilename(igcDebugVars.fileName, builtInsFileName + "_", ".bin");
gEnvironment->setMockFileNames(fclDebugVars.fileName, igcDebugVars.fileName);
gEnvironment->setDefaultDebugVars(fclDebugVars, igcDebugVars, hwInfoForTests);
int sigOut = setSegv(enableSegv);
if (sigOut != 0) {
return sigOut;
}
sigOut = setAbrt(enableAbrt);
if (sigOut != 0) {
return sigOut;
}
if (!gmmInitialized) {
if (useMockGmm) {
GmmHelper::createGmmContextWrapperFunc = GmmClientContext::create<MockGmmClientContext>;
} else {
GmmInterface::initialize(nullptr, nullptr);
}
gmmInitialized = true;
}
if (!sipInitialized) {
MockSipData::mockSipKernel.reset(new MockSipKernel());
if (testMode == TestMode::aubTests || testMode == TestMode::aubTestsWithTbx) {
MockSipData::useMockSip = false;
}
sipInitialized = true;
}
Device::createPerformanceCountersFunc = [](Device *) -> std::unique_ptr<NEO::PerformanceCounters> { return {}; };
sigOut = setAlarm(enableAlarm);
if (sigOut != 0) {
return sigOut;
}
retVal = RUN_ALL_TESTS();
cleanupSignals();
if (showTestStats) {
std::cout << getTestStats() << std::endl;
}
if (dumpTestStats) {
std::ofstream dumpTestStatsFile;
dumpTestStatsFile.open(dumpTestStatsFileName);
dumpTestStatsFile << getTestStatsJson();
dumpTestStatsFile.close();
}
cleanTestHelpers();
if (retVal != 0) {
break;
}
}
return retVal;
}