mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-30 18:37:46 +08:00
During multi process test execution it may be difficult to propery read output from tests. Output lines maybe mixed so determining things like hardware or random seed becomes difficult. This change adds extra data to output: [ FAILED ][ BDW ][ 35357 ] <test name> [ FAILED ][ BDW ][ 35358 ] <test name> From this we can easily find that test failed on BDW with gtest_seed=35357 and 35358. Change-Id: I21e0767162d390f56dd270b1ba8650664c3898b5 Signed-off-by: Artur Harasimiuk <artur.harasimiuk@intel.com>
440 lines
14 KiB
C++
440 lines
14 KiB
C++
/*
|
|
* Copyright (c) 2017 - 2018, Intel Corporation
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "global_environment.h"
|
|
#include "hw_cmds.h"
|
|
#include "runtime/helpers/options.h"
|
|
#include "unit_tests/custom_event_listener.h"
|
|
#include "helpers/test_files.h"
|
|
#include "unit_tests/ult_config_listener.h"
|
|
#include "unit_tests/memory_leak_listener.h"
|
|
#include "unit_tests/mocks/mock_gmm.h"
|
|
#include "unit_tests/mocks/mock_program.h"
|
|
#include "unit_tests/mocks/mock_sip.h"
|
|
#include "runtime/gmm_helper/resource_info.h"
|
|
#include "runtime/os_interface/debug_settings_manager.h"
|
|
#include "External/Common/GmmLibDllName.h"
|
|
#include "mock_gmm_client_context.h"
|
|
#include "gmock/gmock.h"
|
|
#include <algorithm>
|
|
#include <mutex>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <thread>
|
|
|
|
#include <limits.h>
|
|
|
|
#ifdef WIN32
|
|
const char *fSeparator = "\\";
|
|
#else
|
|
const char *fSeparator = "/";
|
|
#endif
|
|
|
|
namespace OCLRT {
|
|
extern const char *hardwarePrefix[];
|
|
extern const HardwareInfo *hardwareInfoTable[IGFX_MAX_PRODUCT];
|
|
|
|
extern const unsigned int ultIterationMaxTime;
|
|
extern bool useMockGmm;
|
|
|
|
std::thread::id tempThreadID;
|
|
} // namespace OCLRT
|
|
namespace Os {
|
|
extern const char *gmmDllName;
|
|
extern const char *gmmEntryName;
|
|
} // namespace Os
|
|
|
|
using namespace OCLRT;
|
|
TestEnvironment *gEnvironment;
|
|
|
|
PRODUCT_FAMILY productFamily = IGFX_SKYLAKE;
|
|
GFXCORE_FAMILY renderCoreFamily = IGFX_GEN9_CORE;
|
|
PRODUCT_FAMILY defaultProductFamily = productFamily;
|
|
|
|
extern bool printMemoryOpCallStack;
|
|
extern std::string lastTest;
|
|
|
|
void applyWorkarounds() {
|
|
{
|
|
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;
|
|
}
|
|
{
|
|
class BaseClass {
|
|
public:
|
|
int method(int param) { return 1; }
|
|
};
|
|
class MockClass : public BaseClass {
|
|
public:
|
|
MOCK_METHOD1(method, int(int param));
|
|
};
|
|
::testing::NiceMock<MockClass> mockObj;
|
|
EXPECT_CALL(mockObj, method(::testing::_))
|
|
.Times(1);
|
|
mockObj.method(2);
|
|
}
|
|
|
|
//Create at least on thread to prevent false memory leaks in tests using threads
|
|
std::thread t([&]() {
|
|
});
|
|
tempThreadID = t.get_id();
|
|
t.join();
|
|
}
|
|
#ifdef __linux__
|
|
void handle_SIGALRM(int signal) {
|
|
std::cout << "Tests timeout on: " << lastTest << std::endl;
|
|
abort();
|
|
}
|
|
void handle_SIGSEGV(int signal) {
|
|
std::cout << "SIGSEGV on: " << lastTest << std::endl;
|
|
abort();
|
|
}
|
|
struct sigaction oldSigAbrt;
|
|
void handle_SIGABRT(int signal) {
|
|
std::cout << "SIGABRT on: " << lastTest << std::endl;
|
|
// restore signal handler to abort
|
|
if (sigaction(SIGABRT, &oldSigAbrt, nullptr) == -1) {
|
|
std::cout << "FATAL: cannot fatal SIGABRT handler" << std::endl;
|
|
std::cout << "FATAL: try SEGV" << std::endl;
|
|
uint8_t *ptr = nullptr;
|
|
*ptr = 0;
|
|
std::cout << "FATAL: still alive, call exit()" << std::endl;
|
|
exit(-1);
|
|
}
|
|
raise(signal);
|
|
}
|
|
#else
|
|
LONG WINAPI UltExceptionFilter(
|
|
_In_ struct _EXCEPTION_POINTERS *exceptionInfo) {
|
|
std::cout << "UnhandledException: 0x" << std::hex << exceptionInfo->ExceptionRecord->ExceptionCode << std::dec
|
|
<< " on test: " << lastTest
|
|
<< std::endl;
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
#endif
|
|
|
|
void initializeTestHelpers() {
|
|
GlobalMockSipProgram::initSipProgram();
|
|
}
|
|
|
|
void cleanTestHelpers() {
|
|
GlobalMockSipProgram::shutDownSipProgram();
|
|
}
|
|
|
|
std::string getHardwarePrefix() {
|
|
std::string s = hardwarePrefix[platformDevices[0]->pPlatform->eProductFamily];
|
|
return s;
|
|
}
|
|
|
|
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) {
|
|
#if defined(__linux__)
|
|
res = getcwd(nullptr, 0);
|
|
#else
|
|
res = _getcwd(nullptr, 0);
|
|
#endif
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
int retVal = 0;
|
|
bool useDefaultListener = false;
|
|
bool enable_alarm = true;
|
|
bool enable_segv = true;
|
|
bool enable_abrt = true;
|
|
|
|
applyWorkarounds();
|
|
|
|
#if defined(__linux__)
|
|
if (getenv("IGDRCL_TEST_SELF_EXEC") == nullptr) {
|
|
std::string wd = getRunPath(argv[0]);
|
|
setenv("LD_LIBRARY_PATH", wd.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;
|
|
} else {
|
|
}
|
|
#endif
|
|
|
|
::testing::InitGoogleMock(&argc, argv);
|
|
|
|
auto numDevices = numPlatformDevices;
|
|
HardwareInfo device = DEFAULT_TEST_PLATFORM::hwInfo;
|
|
GT_SYSTEM_INFO gtSystemInfo = *device.pSysInfo;
|
|
hardwareInfoSetupGt[device.pPlatform->eProductFamily](>SystemInfo);
|
|
size_t revisionId = device.pPlatform->usRevId;
|
|
uint32_t euPerSubSlice = 0;
|
|
uint32_t sliceCount = 0;
|
|
uint32_t subSliceCount = 0;
|
|
int dieRecovery = 1;
|
|
::productFamily = device.pPlatform->eProductFamily;
|
|
|
|
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])) {
|
|
enable_alarm = false;
|
|
} else if (!strcmp("--print_memory_op_cs", argv[i])) {
|
|
printMemoryOpCallStack = true;
|
|
} else if (!strcmp("--devices", argv[i])) {
|
|
++i;
|
|
if (i < argc) {
|
|
numDevices = atoi(argv[i]);
|
|
}
|
|
} else if (!strcmp("--rev_id", argv[i])) {
|
|
++i;
|
|
if (i < argc) {
|
|
revisionId = atoi(argv[i]);
|
|
}
|
|
} 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 {
|
|
::productFamily = IGFX_UNKNOWN;
|
|
for (int j = 0; j < IGFX_MAX_PRODUCT; j++) {
|
|
if (hardwarePrefix[j] == nullptr)
|
|
continue;
|
|
if (strcmp(hardwarePrefix[j], argv[i]) == 0) {
|
|
::productFamily = static_cast<PRODUCT_FAMILY>(j);
|
|
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;
|
|
}
|
|
}
|
|
} else if (!strcmp("--slices", argv[i])) {
|
|
++i;
|
|
if (i < argc) {
|
|
sliceCount = atoi(argv[i]);
|
|
}
|
|
} else if (!strcmp("--subslices", argv[i])) {
|
|
++i;
|
|
if (i < argc) {
|
|
subSliceCount = 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (numDevices < 1) {
|
|
return -1;
|
|
}
|
|
|
|
uint32_t threadsPerEu = 7;
|
|
PLATFORM platform;
|
|
auto hardwareInfo = hardwareInfoTable[productFamily];
|
|
if (!hardwareInfo) {
|
|
return -1;
|
|
}
|
|
platform = *hardwareInfo->pPlatform;
|
|
|
|
platform.usRevId = (uint16_t)revisionId;
|
|
|
|
// set Gt to initial state
|
|
hardwareInfoSetupGt[productFamily](>SystemInfo);
|
|
// and adjust dynamic values if not secified
|
|
sliceCount = sliceCount > 0 ? sliceCount : gtSystemInfo.SliceCount;
|
|
subSliceCount = subSliceCount > 0 ? subSliceCount : gtSystemInfo.SubSliceCount;
|
|
euPerSubSlice = euPerSubSlice > 0 ? euPerSubSlice : gtSystemInfo.MaxEuPerSubSlice;
|
|
// clang-format off
|
|
gtSystemInfo.SliceCount = sliceCount;
|
|
gtSystemInfo.SubSliceCount = subSliceCount;
|
|
gtSystemInfo.EUCount = gtSystemInfo.SubSliceCount * euPerSubSlice - dieRecovery;
|
|
gtSystemInfo.ThreadCount = gtSystemInfo.EUCount * threadsPerEu;
|
|
gtSystemInfo.MaxEuPerSubSlice = std::max(gtSystemInfo.MaxEuPerSubSlice, euPerSubSlice);
|
|
gtSystemInfo.MaxSlicesSupported = std::max(gtSystemInfo.MaxSlicesSupported, gtSystemInfo.SliceCount);
|
|
gtSystemInfo.MaxSubSlicesSupported = std::max(gtSystemInfo.MaxSubSlicesSupported, gtSystemInfo.SubSliceCount);
|
|
gtSystemInfo.IsDynamicallyPopulated = false;
|
|
// clang-format on
|
|
|
|
::productFamily = platform.eProductFamily;
|
|
::renderCoreFamily = platform.eRenderCoreFamily;
|
|
|
|
device.pPlatform = &platform;
|
|
device.pSysInfo = >SystemInfo;
|
|
device.capabilityTable = hardwareInfo->capabilityTable;
|
|
|
|
binaryNameSuffix.append(familyName[device.pPlatform->eRenderCoreFamily]);
|
|
binaryNameSuffix.append(getPlatformType(device));
|
|
|
|
std::string nBinaryKernelFiles = getRunPath(argv[0]);
|
|
nBinaryKernelFiles.append("/");
|
|
nBinaryKernelFiles.append(binaryNameSuffix);
|
|
nBinaryKernelFiles.append("/");
|
|
nBinaryKernelFiles.append(testFiles);
|
|
testFiles = nBinaryKernelFiles;
|
|
|
|
std::string nClFiles = getRunPath(argv[0]);
|
|
nClFiles.append("/");
|
|
nClFiles.append(hardwarePrefix[productFamily]);
|
|
nClFiles.append("/");
|
|
nClFiles.append(clFiles);
|
|
clFiles = nClFiles;
|
|
|
|
#ifdef WIN32
|
|
#include <direct.h>
|
|
if (_chdir(hardwarePrefix[productFamily])) {
|
|
std::cout << "chdir into " << hardwarePrefix[productFamily] << " directory failed.\nThis might cause test failures." << std::endl;
|
|
}
|
|
#elif defined(__linux__)
|
|
#include <unistd.h>
|
|
if (chdir(hardwarePrefix[productFamily]) != 0) {
|
|
std::cout << "chdir into " << hardwarePrefix[productFamily] << " directory failed.\nThis might cause test failures." << std::endl;
|
|
}
|
|
#endif
|
|
|
|
auto pDevices = new const HardwareInfo *[numDevices];
|
|
for (decltype(numDevices) i = 0; i < numDevices; ++i) {
|
|
pDevices[i] = &device;
|
|
}
|
|
|
|
numPlatformDevices = numDevices;
|
|
platformDevices = pDevices;
|
|
|
|
auto &listeners = ::testing::UnitTest::GetInstance()->listeners();
|
|
if (useDefaultListener == false) {
|
|
auto defaultListener = listeners.default_result_printer();
|
|
|
|
auto customEventListener = new CCustomEventListener(defaultListener, hardwarePrefix[productFamily]);
|
|
|
|
listeners.Release(defaultListener);
|
|
listeners.Append(customEventListener);
|
|
}
|
|
|
|
listeners.Append(new MemoryLeakListener);
|
|
listeners.Append(new UltConfigListener);
|
|
|
|
gEnvironment = reinterpret_cast<TestEnvironment *>(::testing::AddGlobalTestEnvironment(new TestEnvironment));
|
|
|
|
MockCompilerDebugVars fclDebugVars;
|
|
MockCompilerDebugVars igcDebugVars;
|
|
|
|
retrieveBinaryKernelFilename(fclDebugVars.fileName, "17246368129176860573_", ".bc");
|
|
retrieveBinaryKernelFilename(igcDebugVars.fileName, "17246368129176860573_", ".gen");
|
|
|
|
gEnvironment->setMockFileNames(fclDebugVars.fileName, igcDebugVars.fileName);
|
|
gEnvironment->setDefaultDebugVars(fclDebugVars, igcDebugVars, device);
|
|
|
|
#if defined(__linux__)
|
|
//ULTs timeout
|
|
if (enable_alarm) {
|
|
unsigned int alarmTime = OCLRT::ultIterationMaxTime * ::testing::GTEST_FLAG(repeat);
|
|
|
|
struct sigaction sa;
|
|
sa.sa_handler = &handle_SIGALRM;
|
|
sa.sa_flags = SA_RESTART;
|
|
sigfillset(&sa.sa_mask);
|
|
if (sigaction(SIGALRM, &sa, NULL) == -1) {
|
|
printf("FATAL ERROR: cannot intercept SIGALRM\n");
|
|
return -2;
|
|
}
|
|
alarm(alarmTime);
|
|
std::cout << "set timeout to: " << alarmTime << std::endl;
|
|
}
|
|
|
|
if (enable_segv) {
|
|
struct sigaction sa;
|
|
sa.sa_handler = &handle_SIGSEGV;
|
|
sa.sa_flags = SA_RESTART;
|
|
sigfillset(&sa.sa_mask);
|
|
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
|
|
printf("FATAL ERROR: cannot intercept SIGSEGV\n");
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
if (enable_abrt) {
|
|
struct sigaction sa;
|
|
sa.sa_handler = &handle_SIGABRT;
|
|
sa.sa_flags = SA_RESTART;
|
|
sigfillset(&sa.sa_mask);
|
|
if (sigaction(SIGABRT, &sa, &oldSigAbrt) == -1) {
|
|
printf("FATAL ERROR: cannot intercept SIGABRT\n");
|
|
return -2;
|
|
}
|
|
}
|
|
#else
|
|
SetUnhandledExceptionFilter(&UltExceptionFilter);
|
|
#endif
|
|
#ifdef GMM_LIB_DLL
|
|
if (!useMockGmm) {
|
|
Os::gmmDllName = GMM_UMD_DLL;
|
|
Os::gmmEntryName = GMM_ENTRY_NAME;
|
|
} else {
|
|
GmmHelper::createGmmContextWrapperFunc = GmmClientContextBase::create<MockGmmClientContext>;
|
|
}
|
|
std::unique_ptr<OsLibrary> gmmLib(OsLibrary::load(Os::gmmDllName));
|
|
#endif
|
|
initializeTestHelpers();
|
|
|
|
retVal = RUN_ALL_TESTS();
|
|
|
|
cleanTestHelpers();
|
|
|
|
delete[] pDevices;
|
|
|
|
return retVal;
|
|
}
|