fix: refactor Windows cl_cache and add extra safety layers

What's changed:
- Add early return when open existing config
fails due to different error than `ERROR_FILE_NOT_FOUND`
- Swich `ReadFileEx` to `ReadFile`
- Add `SetFilePointer` to make sure we're reading
from the beginning of the file
- Pass `overlapped` to `WriteFile` to make sure
we're writing from the beginning of the file

Related-To: NEO-8092
Signed-off-by: Fabian Zwolinski <fabian.zwolinski@intel.com>
This commit is contained in:
Fabian Zwolinski 2023-10-02 09:35:55 +00:00 committed by Compute-Runtime-Automation
parent d27d81f206
commit 7c80f49176
5 changed files with 178 additions and 92 deletions

View File

@ -103,6 +103,10 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
NULL);
if (std::get<void *>(handle) == INVALID_HANDLE_VALUE) {
if (SysCalls::getLastError() != ERROR_FILE_NOT_FOUND) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache failure]: Open config file failed! error code: %lu\n", NEO::SysCalls::getProcessId(), SysCalls::getLastError());
return;
}
std::get<void *>(handle) = NEO::SysCalls::createFileA(configFilePath.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
@ -132,11 +136,6 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
MAXDWORD,
&overlapped);
if (result == FALSE && SysCalls::getLastError() == ERROR_IO_PENDING) { // if file is already locked by somebody else
DWORD numberOfBytesTransmitted = 0;
result = NEO::SysCalls::getOverlappedResult(std::get<void *>(handle), &overlapped, &numberOfBytesTransmitted, TRUE);
}
if (!result) {
std::get<void *>(handle) = INVALID_HANDLE_VALUE;
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache failure]: Lock config file failed! error code: %lu\n", NEO::SysCalls::getProcessId(), SysCalls::getLastError());
@ -150,8 +149,24 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
directorySize += static_cast<size_t>(file.fileSize);
}
} else {
memset(&overlapped, 0, sizeof(overlapped));
result = NEO::SysCalls::readFileEx(std::get<void *>(handle), &directorySize, sizeof(directorySize), &overlapped, NULL);
DWORD fPointer = NEO::SysCalls::setFilePointer(std::get<void *>(handle),
0,
NULL,
FILE_BEGIN);
if (fPointer != 0) {
directorySize = 0;
unlockFileAndClose(std::get<void *>(handle));
std::get<void *>(handle) = INVALID_HANDLE_VALUE;
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache failure]: File pointer move failed! error code: %lu\n", NEO::SysCalls::getProcessId(), SysCalls::getLastError());
return;
}
DWORD numOfBytesRead = 0;
result = NEO::SysCalls::readFile(std::get<void *>(handle),
&directorySize,
sizeof(directorySize),
&numOfBytesRead,
NULL);
if (!result) {
directorySize = 0;
@ -235,10 +250,6 @@ bool CompilerCache::cacheBinary(const std::string &kernelFileHash, const char *p
lockConfigFileAndReadSize(configFilePath, hConfigFile, directorySize);
if (std::get<void *>(hConfigFile) == INVALID_HANDLE_VALUE) {
if (SysCalls::getLastError() == ERROR_HANDLE_EOF) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache info]: deleting the corrupted config file\n", NEO::SysCalls::getProcessId());
SysCalls::deleteFileA(configFilePath.c_str());
}
return false;
}
@ -274,11 +285,12 @@ bool CompilerCache::cacheBinary(const std::string &kernelFileHash, const char *p
directorySize += binarySize;
DWORD sizeWritten = 0;
OVERLAPPED overlapped = {0};
auto result = NEO::SysCalls::writeFile(std::get<void *>(hConfigFile),
&directorySize,
(DWORD)sizeof(directorySize),
&sizeWritten,
NULL);
&overlapped);
if (!result) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache failure]: Writing to config file failed! error code: %lu\n", NEO::SysCalls::getProcessId(), SysCalls::getLastError());

View File

@ -104,8 +104,8 @@ HRESULT shGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken
return SHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPat);
}
BOOL readFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
return ReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
BOOL readFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
BOOL writeFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
@ -128,6 +128,10 @@ DWORD getFileAttributesA(LPCSTR lpFileName) {
return GetFileAttributesA(lpFileName);
}
DWORD setFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
return SetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
}
void coTaskMemFree(LPVOID pv) {
CoTaskMemFree(pv);
}

View File

@ -28,12 +28,13 @@ BOOL createDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttribu
HANDLE createFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
BOOL deleteFileA(LPCSTR lpFileName);
HRESULT shGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPat);
BOOL readFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
BOOL readFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
BOOL writeFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
HANDLE findFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData);
BOOL findNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData);
BOOL findClose(HANDLE hFindFile);
DWORD getFileAttributesA(LPCSTR lpFileName);
DWORD setFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
void coTaskMemFree(LPVOID pv);

View File

@ -68,10 +68,10 @@ HRESULT shGetKnownFolderPathResult = 0;
extern const size_t shGetKnownFolderSetPathSize = 50;
wchar_t shGetKnownFolderSetPath[shGetKnownFolderSetPathSize];
bool callBaseReadFileEx = true;
BOOL readFileExResult = TRUE;
size_t readFileExCalled = 0u;
size_t readFileExBufferData = 0u;
bool callBaseReadFile = true;
BOOL readFileResult = TRUE;
size_t readFileCalled = 0u;
size_t readFileBufferData = 0u;
size_t writeFileCalled = 0u;
BOOL writeFileResult = true;
@ -90,6 +90,9 @@ size_t findCloseCalled = 0u;
size_t getFileAttributesCalled = 0u;
DWORD getFileAttributesResult = TRUE;
size_t setFilePointerCalled = 0u;
DWORD setFilePointerResult = 0;
bool pathExists(const std::string &path) {
std::string tempP1 = path;
if (!path.empty() && path.back() == PATH_SEPARATOR) {
@ -214,15 +217,15 @@ HRESULT shGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken
return shGetKnownFolderPathResult;
}
BOOL readFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
readFileExCalled++;
if (callBaseReadFileEx) {
return ReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
BOOL readFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
readFileCalled++;
if (callBaseReadFile) {
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
if (lpBuffer) {
*static_cast<size_t *>(lpBuffer) = readFileExBufferData;
*static_cast<size_t *>(lpBuffer) = readFileBufferData;
}
return readFileExResult;
return readFileResult;
}
BOOL writeFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
@ -261,6 +264,11 @@ DWORD getFileAttributesA(LPCSTR lpFileName) {
return getFileAttributesResult;
}
DWORD setFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
setFilePointerCalled++;
return setFilePointerResult;
}
void coTaskMemFree(LPVOID pv) {
return;
}

View File

@ -109,10 +109,10 @@ extern HANDLE createFileAResults[];
extern size_t deleteFileACalled;
extern std::string deleteFiles[];
extern bool callBaseReadFileEx;
extern BOOL readFileExResult;
extern size_t readFileExCalled;
extern size_t readFileExBufferData;
extern bool callBaseReadFile;
extern BOOL readFileResult;
extern size_t readFileCalled;
extern size_t readFileBufferData;
extern size_t writeFileCalled;
extern BOOL writeFileResult;
@ -130,6 +130,9 @@ extern size_t findCloseCalled;
extern size_t getFileAttributesCalled;
extern DWORD getFileAttributesResult;
extern size_t setFilePointerCalled;
extern DWORD setFilePointerResult;
} // namespace SysCalls
struct CompilerCacheWindowsTest : public ::testing::Test {
@ -144,17 +147,19 @@ struct CompilerCacheWindowsTest : public ::testing::Test {
unlockFileExResultBackup(&SysCalls::unlockFileExResult),
createFileACalledBackup(&SysCalls::createFileACalled),
deleteFileACalledBackup(&SysCalls::deleteFileACalled),
callBaseReadFileExBackup(&SysCalls::callBaseReadFileEx),
readFileExResultBackup(&SysCalls::readFileExResult),
readFileExCalledBackup(&SysCalls::readFileExCalled),
readFileExBufferDataBackup(&SysCalls::readFileExBufferData),
callBaseReadFileBackup(&SysCalls::callBaseReadFile),
readFileResultBackup(&SysCalls::readFileResult),
readFileCalledBackup(&SysCalls::readFileCalled),
readFileBufferDataBackup(&SysCalls::readFileBufferData),
writeFileCalledBackup(&SysCalls::writeFileCalled),
writeFileResultBackup(&SysCalls::writeFileResult),
writeFileNumberOfBytesWrittenBackup(&SysCalls::writeFileNumberOfBytesWritten),
findFirstFileAResultBackup(&SysCalls::findFirstFileAResult),
findNextFileACalledBackup(&SysCalls::findNextFileACalled),
getFileAttributesCalledBackup(&SysCalls::getFileAttributesCalled),
getFileAttributesResultBackup(&SysCalls::getFileAttributesResult) {}
getFileAttributesResultBackup(&SysCalls::getFileAttributesResult),
setFilePointerCalledBackup(&SysCalls::setFilePointerCalled),
setFilePointerResultBackup(&SysCalls::setFilePointerResult) {}
void SetUp() override {
SysCalls::closeHandleCalled = 0u;
@ -163,10 +168,11 @@ struct CompilerCacheWindowsTest : public ::testing::Test {
SysCalls::unlockFileExCalled = 0u;
SysCalls::createFileACalled = 0u;
SysCalls::deleteFileACalled = 0u;
SysCalls::readFileExCalled = 0u;
SysCalls::readFileCalled = 0u;
SysCalls::writeFileCalled = 0u;
SysCalls::findNextFileACalled = 0u;
SysCalls::getFileAttributesCalled = 0u;
SysCalls::setFilePointerCalled = 0u;
}
void TearDown() override {
@ -193,10 +199,10 @@ struct CompilerCacheWindowsTest : public ::testing::Test {
VariableBackup<BOOL> unlockFileExResultBackup;
VariableBackup<size_t> createFileACalledBackup;
VariableBackup<size_t> deleteFileACalledBackup;
VariableBackup<bool> callBaseReadFileExBackup;
VariableBackup<BOOL> readFileExResultBackup;
VariableBackup<size_t> readFileExCalledBackup;
VariableBackup<size_t> readFileExBufferDataBackup;
VariableBackup<bool> callBaseReadFileBackup;
VariableBackup<BOOL> readFileResultBackup;
VariableBackup<size_t> readFileCalledBackup;
VariableBackup<size_t> readFileBufferDataBackup;
VariableBackup<size_t> writeFileCalledBackup;
VariableBackup<BOOL> writeFileResultBackup;
VariableBackup<DWORD> writeFileNumberOfBytesWrittenBackup;
@ -204,6 +210,8 @@ struct CompilerCacheWindowsTest : public ::testing::Test {
VariableBackup<size_t> findNextFileACalledBackup;
VariableBackup<size_t> getFileAttributesCalledBackup;
VariableBackup<DWORD> getFileAttributesResultBackup;
VariableBackup<size_t> setFilePointerCalledBackup;
VariableBackup<DWORD> setFilePointerResultBackup;
};
TEST_F(CompilerCacheWindowsTest, GivenCompilerCacheWithOneMegabyteWhenEvictCacheIsCalledThenDeleteTwoOldestFiles) {
@ -258,9 +266,9 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::callBaseReadFileEx = false;
SysCalls::readFileExResult = TRUE;
SysCalls::readFileExBufferData = readCacheDirSize;
SysCalls::callBaseReadFile = false;
SysCalls::readFileResult = TRUE;
SysCalls::readFileBufferData = readCacheDirSize;
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
@ -272,7 +280,7 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(1u, SysCalls::lockFileExCalled);
EXPECT_EQ(1u, SysCalls::readFileExCalled);
EXPECT_EQ(1u, SysCalls::readFileCalled);
EXPECT_EQ(readCacheDirSize, directorySize);
EXPECT_EQ(0u, SysCalls::unlockFileExCalled);
@ -286,8 +294,8 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = FALSE;
SysCalls::callBaseReadFileEx = false;
SysCalls::readFileExResult = TRUE;
SysCalls::callBaseReadFile = false;
SysCalls::readFileResult = TRUE;
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
@ -305,12 +313,47 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(1u, SysCalls::lockFileExCalled);
EXPECT_EQ(0u, SysCalls::readFileExCalled);
EXPECT_EQ(0u, SysCalls::readFileCalled);
EXPECT_EQ(0u, SysCalls::unlockFileExCalled);
EXPECT_EQ(0u, SysCalls::closeHandleCalled);
}
TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigWhenSetFilePointerFailsThenErrorIsPrintedAndFileIsUnlockedAndClosed) {
DebugManagerStateRestore restore;
NEO::DebugManager.flags.PrintDebugMessages.set(1);
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::setFilePointerResult = 8;
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
UnifiedHandle configFileHandle{nullptr};
size_t directorySize = 0u;
::testing::internal::CaptureStderr();
cache.lockConfigFileAndReadSize("somePath\\cl_cache\\config.file", configFileHandle, directorySize);
auto capturedStderr = ::testing::internal::GetCapturedStderr();
std::string expectedStderrSubstr("[Cache failure]: File pointer move failed! error code:");
EXPECT_TRUE(hasSubstr(capturedStderr, expectedStderrSubstr));
EXPECT_EQ(INVALID_HANDLE_VALUE, std::get<void *>(configFileHandle));
EXPECT_EQ(0u, directorySize);
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(1u, SysCalls::lockFileExCalled);
EXPECT_EQ(1u, SysCalls::setFilePointerCalled);
EXPECT_EQ(0u, SysCalls::readFileCalled);
EXPECT_EQ(1u, SysCalls::unlockFileExCalled);
EXPECT_EQ(1u, SysCalls::closeHandleCalled);
}
TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigWhenReadFileFailsThenErrorIsPrintedAndFileIsUnlockedAndClosed) {
DebugManagerStateRestore restore;
NEO::DebugManager.flags.PrintDebugMessages.set(1);
@ -318,8 +361,8 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::callBaseReadFileEx = false;
SysCalls::readFileExResult = FALSE;
SysCalls::callBaseReadFile = false;
SysCalls::readFileResult = FALSE;
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
@ -337,21 +380,23 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(1u, SysCalls::lockFileExCalled);
EXPECT_EQ(1u, SysCalls::readFileExCalled);
EXPECT_EQ(1u, SysCalls::readFileCalled);
EXPECT_EQ(1u, SysCalls::unlockFileExCalled);
EXPECT_EQ(1u, SysCalls::closeHandleCalled);
}
TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigFailsThenCreateNewConfigFileAndCountDirectorySize) {
TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigFailsDueToFileNotFoundThenCreateNewConfigFileAndCountDirectorySize) {
const size_t readCacheDirSize = 840 * MemoryConstants::kiloByte;
SysCalls::createFileAResults[0] = INVALID_HANDLE_VALUE;
SysCalls::createFileAResults[1] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::callBaseReadFileEx = false;
SysCalls::readFileExResult = TRUE;
SysCalls::readFileExBufferData = readCacheDirSize;
SysCalls::callBaseReadFile = false;
SysCalls::readFileResult = TRUE;
SysCalls::readFileBufferData = readCacheDirSize;
SysCalls::getLastErrorResult = ERROR_FILE_NOT_FOUND;
WIN32_FIND_DATAA filesData[4];
DWORD cacheFileSize = (MemoryConstants::megaByte / 6) + 10;
@ -383,11 +428,65 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC
EXPECT_EQ(expectedDirectorySize, directorySize);
EXPECT_EQ(0u, SysCalls::readFileExCalled);
EXPECT_EQ(0u, SysCalls::readFileCalled);
EXPECT_EQ(0u, SysCalls::unlockFileExCalled);
EXPECT_EQ(0u, SysCalls::closeHandleCalled);
}
TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigFailsThenPrintErrorMessageAndEarlyReturn) {
DebugManagerStateRestore restore;
NEO::DebugManager.flags.PrintDebugMessages.set(1);
const size_t readCacheDirSize = 840 * MemoryConstants::kiloByte;
SysCalls::createFileAResults[0] = INVALID_HANDLE_VALUE;
SysCalls::createFileAResults[1] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::callBaseReadFile = false;
SysCalls::readFileResult = TRUE;
SysCalls::readFileBufferData = readCacheDirSize;
SysCalls::getLastErrorResult = ERROR_FILE_NOT_FOUND + 1;
WIN32_FIND_DATAA filesData[4];
DWORD cacheFileSize = (MemoryConstants::megaByte / 6) + 10;
filesData[0].ftLastAccessTime.dwLowDateTime = 6u;
filesData[1].ftLastAccessTime.dwLowDateTime = 4u;
filesData[2].ftLastAccessTime.dwLowDateTime = 8u;
filesData[3].ftLastAccessTime.dwLowDateTime = 2u;
for (size_t i = 0; i < 4; i++) {
snprintf(filesData[i].cFileName, MAX_PATH, "file_%zu.cl_cache", i);
filesData[i].nFileSizeHigh = 0;
filesData[i].nFileSizeLow = cacheFileSize;
filesData[i].ftLastAccessTime.dwHighDateTime = 0;
SysCalls::findNextFileAFileData[i] = filesData[i];
}
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
UnifiedHandle configFileHandle{nullptr};
size_t directorySize = 0u;
::testing::internal::CaptureStderr();
cache.lockConfigFileAndReadSize("somePath\\cl_cache\\config.file", configFileHandle, directorySize);
auto capturedStderr = ::testing::internal::GetCapturedStderr();
std::string expectedStderrSubstr("[Cache failure]: Open config file failed! error code:");
EXPECT_TRUE(hasSubstr(capturedStderr, expectedStderrSubstr));
EXPECT_EQ(INVALID_HANDLE_VALUE, std::get<void *>(configFileHandle));
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(0u, SysCalls::lockFileExCalled);
EXPECT_EQ(0u, SysCalls::readFileCalled);
EXPECT_EQ(0u, SysCalls::unlockFileExCalled);
EXPECT_EQ(0u, SysCalls::closeHandleCalled);
EXPECT_EQ(0u, directorySize);
}
TEST_F(CompilerCacheWindowsTest, givenCreateUniqueTempFileAndWriteDataWhenCreateAndWriteTempFileSucceedsThenBinaryIsWritten) {
SysCalls::getTempFileNameAResult = 6u;
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
@ -578,44 +677,6 @@ TEST_F(CompilerCacheWindowsTest, givenCacheBinaryWhenCacheAlreadyExistsThenDoNot
EXPECT_EQ(0u, SysCalls::writeFileCalled);
}
TEST_F(CompilerCacheWindowsTest, givenEmptyConfigFileWhenCacheBinaryAndReadConfigFailsWithEOFErrorThenConfigIsDeletedAndErrorIsPrinted) {
DebugManagerStateRestore restore;
NEO::DebugManager.flags.PrintDebugMessages.set(1);
SysCalls::getLastErrorResult = ERROR_HANDLE_EOF;
SysCalls::createFileAResults[0] = reinterpret_cast<HANDLE>(0x1234);
SysCalls::lockFileExResult = TRUE;
SysCalls::callBaseReadFileEx = false;
SysCalls::readFileExResult = FALSE;
const size_t cacheSize = MemoryConstants::megaByte - 2u;
CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize});
const std::string kernelFileHash = "7e3291364d8df42";
const char *binary = "123456";
const size_t binarySize = strlen(binary);
::testing::internal::CaptureStderr();
auto result = cache.cacheBinary(kernelFileHash, binary, binarySize);
auto capturedStderr = ::testing::internal::GetCapturedStderr();
std::string expectedStderrSubstr1("[Cache failure]: Read config failed! error code:");
EXPECT_TRUE(hasSubstr(capturedStderr, expectedStderrSubstr1));
std::string expectedStderrSubstr2("[Cache info]: deleting the corrupted config file");
EXPECT_TRUE(hasSubstr(capturedStderr, expectedStderrSubstr2));
EXPECT_FALSE(result);
EXPECT_EQ(1u, SysCalls::createFileACalled);
EXPECT_EQ(1u, SysCalls::lockFileExCalled);
EXPECT_EQ(1u, SysCalls::readFileExCalled);
EXPECT_EQ(1u, SysCalls::unlockFileExCalled);
EXPECT_EQ(1u, SysCalls::closeHandleCalled);
EXPECT_EQ(1u, SysCalls::deleteFileACalled);
}
TEST_F(CompilerCacheWindowsTest, givenCacheBinaryWhenWriteToConfigFileFailsThenErrorIsPrinted) {
DebugManagerStateRestore restore;
NEO::DebugManager.flags.PrintDebugMessages.set(1);