LYN-2705: Remove 'AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS' trait for Linux (#1235)
* Fix Delete_Real_Readonly_Fails to mark parent directory as read-only as well Read-only files in Windows cannot be deleted. The previous version of this code relied on that fact, and would attempt to delete a file even when `skipReadOnly = true`, relying on the OS to refuse to delete the file if it is read only. On Linux, it is the writable state of the *directory* that determines if a file can be deleted or not. This fixes the test to set up the correct situation where a file deletion would fail. * Remove excluded items from a vector before iterating over it Removing items from the `pathMatches` `QStringList` while iterating over it was causing a segfault on Linux. This change separates out the item removal from the item iteration, which allows the item iteration loop to use a range-for loop instead of directly manipulating iterators. * Remove invalid test that asserts a file's metadata file can have differing file casing This test is asserting that a given source file and its accompanying metadata file can have the the same name but differing case. This is really testing whether or not the underlying filesystem that those files live on is case sensitive or not. The 99% chance is that users are using the default filesystem that their host OS gives them, NTFS on Windows, EXT* on Linux, and APFS on Mac. Even though NTFS is case-insensitive by default, it [can be configured per-directory](https://devblogs.microsoft.com/commandline/improved-per-directory-case-sensitivity-support-in-wsl/). APFS as well can be configured to be case-sensitive. For users with case sensitive filesystems, this test makes no sense. We could extend this test to inspect the case-sensitivity of the underlying filesystem, but then it is just testing the filesystem's behavior, which seems out of scope of this test. * Use a non-priviliged port for the Asset Processor tests From https://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html: > The TCP/IP port numbers below 1024 are special in that normal users are not > allowed to run servers on them. This is a security feaure, in that if you > connect to a service on one of these ports you can be fairly sure that you > have the real thing, and not a fake which some hacker has put up for you. > > When you run a server as a test from a non-priviliged account, you will > normally test it on other ports, such as 2784, 5000, 8001 or 8080. * Fix for `QDir::rmdir(".")` not working in Linux Qt uses `::rmdir` to remove directories on Linux. This comes from [unistd.h](https://pubs.opengroup.org/onlinepubs/007904875/functions/rmdir.html) The documentation for that function states: > If the path argument refers to a path whose final component is either dot > or dot-dot, rmdir() shall fail. So calling `dir.rmdir(".")` will never work on Linux. Instead, get the parent directory, and remove the child directory by name. * Avoid lowercasing source asset paths when resolving dependencies Source asset paths may be case sensitive, so their case must be preserved when doing operations that hit the underlying filesystem. This method was always lowercasing them, which would cause dependencies to not be found. * Correct test to expect product filenames to be lowercase The modtime tests were failing in Linux due to something unrelated to file modtime checking. The Asset Processor Manager does this during AnalyzeJob: ``` if (foundInDatabase && jobs[0].m_fingerprint == jobDetails.m_jobEntry.m_computedFingerprint) { // If the fingerprint hasn't changed, we won't process it.. unless...is it missing a product. ``` In this case, the test was setting up a product whose file case was the same as the source asset, and would write it to the cache dir using mixed case, but use the normal asset processor API to write the product file path to the database, which recorded the path in lowercase. When the manager then went to check if the source asset's products all exist, it checked the lowercase path, which didn't exist. This fixes that test failure, by updating the test to write the product file to the cache using the proper lowercased path. * Update test to define a "not current platform" for Linux This test was failing because it was setting some "not current platform" variable to be set to "pc" on Linux, when `AssetSystem::GetHostAssetPlatform()` is defined to: ```cpp inline const char* GetHostAssetPlatform() { return "mac"; return "pc"; // set this to pc because that's what bootstrap.cfg currently defines the platform to "pc", even on Linux return "pc"; #error Unimplemented Host Asset Platform } ``` The test would go on to assert that "pc" was simultaneously in a list and not in the same list. This fixes the test by updating the code to set the "not the current platform" variable appropriately on Linux. The expectations were also updated to improve the output on test failure. Instead of this: ``` Value of: recogs["rend"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform) Actual: true Expected: false ``` You now get this: ``` Value of: recogs["rend"].m_platformSpecs.keys() Expected: (has 3 elements and there exists some permutation of elements such that: - element #0 is equal to pc, and - element #1 is equal to es3, and - element #2 is equal to server) and (doesn't contain any element that is equal to pc) Actual: { pc, server, es3 } (of type QList<QString>), whose element #0 matches ``` * Prevent windows supported path separators to be included in the test paths for UpdateToCorrectCase_ExistingFile_ReturnsTrue_CorrectsCase * Fix failing linux unit test "PlatformConfigurationUnitTests.TestFailReadConfigFile_RegularScanfolder" caused by static variable not being reset from a different test run when using AssetUtilities::ComputeProjectPath * Fix AZ_RTTI declaration for RequestEscalateAsset Message * Implement FileWatcher for Linux to fix AssetProcessorMessages.All test (RequestAssetStatus) * Split AssetProcessorMessages into 2 tests, one with RequestAssetStatus/ResponseAssetStatus and one without Add The RequestAssetStatus/ResponseAssetStatus as a sandbox test because it relies on FileWatcher thread and seems to be timing related * Remove FileWatcher_win.cpp from the Linux specific folder for FileWatcher * - Fix build error related to non-unity builds - Fixed failed linux test 'Test/LegacyTestAdapter.AllTests/UtilitiesUnitTest' caused by misplaced windows only EXPECT - Remove test trait AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS for linux to expose remaining failed tests * Fixed failed linux test 'Test/LegacyTestAdapter.AllTests/RCcontrollerUnitTests' caused by misplaced windows only EXPECT * - Fix FileWatcher unit test, disable incompatible subtests for Linux - Fix errors in FileWatcher_linux from results of the FileWatcher Unit Test * Remove AZ::AssetProcessor.Tests.Sandbox tests from definition and restore the original AssetProcessorMessages.All tests now that Filewatcher_linux was fixed * Fixes for failed unit tests: AssetProcessorManagerUnitTests and AssetProcessorManagerUnitTests_JobDependencies_Fingerprint - Caused by differences between between case-sensitive files (Linux) and non-case-sensitive Filesystems (Windows) * Update consts in FileWatcher_linux.cpp to constexpr * Fixes related to PR comment suggestions * - Removed std::bind and replaced with lambda in FileWatcher_linux - Replaced String replace functions for path separators to use AZ::IO::Path::LexicallyNormal() instead * Restoring string replace function in PathDependencyManager::ResolveDependencies due to unit test failure Co-authored-by: Chris Burel <burelc@amazon.com>
This commit is contained in:
@@ -166,7 +166,7 @@ namespace AzFramework
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RequestEscalateAsset, AZ::OSAllocator, 0);
|
||||
AZ_RTTI(RequestAssetStatus, "{E95C5422-5F00-478B-A984-C041DE70484F}", BaseAssetProcessorMessage);
|
||||
AZ_RTTI(RequestEscalateAsset, "{E95C5422-5F00-478B-A984-C041DE70484F}", BaseAssetProcessorMessage);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static constexpr unsigned int MessageType = AZ_CRC("AssetSystem::RequestEscalateAsset", 0x1894d94e);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_AP_CONNECTION_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS true
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ATOM_RPI_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ZERO_COLOR_CONVERSION_TEST true
|
||||
|
||||
@@ -259,8 +259,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::AssetProcessor.Tests
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::AssetProcessor.Tests> --unittest
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::AssetProcessor.Tests> --unittest --gtest_filter=-*.SUITE_sandbox*
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
@@ -11,9 +11,127 @@
|
||||
*/
|
||||
#include <native/FileWatcher/FileWatcher.h>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
|
||||
static constexpr int s_handleToFolderMapLockTimeout = 1000; // 1 sec timeout for obtaining the handle to folder map lock
|
||||
static constexpr size_t s_iNotifyMaxEntries = 1024 * 16; // Control the maximum number of entries (from inotify) that can be read at one time
|
||||
static constexpr size_t s_iNotifyEventSize = sizeof(struct inotify_event);
|
||||
static constexpr size_t s_iNotifyReadBufferSize = s_iNotifyMaxEntries * s_iNotifyEventSize;
|
||||
|
||||
struct FolderRootWatch::PlatformImplementation
|
||||
{
|
||||
PlatformImplementation() { }
|
||||
PlatformImplementation() = default;
|
||||
|
||||
int m_iNotifyHandle = -1;
|
||||
QMutex m_handleToFolderMapLock;
|
||||
QHash<int, QString> m_handleToFolderMap;
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
if (m_iNotifyHandle < 0)
|
||||
{
|
||||
m_iNotifyHandle = inotify_init();
|
||||
}
|
||||
return (m_iNotifyHandle >= 0);
|
||||
}
|
||||
|
||||
void Finalize()
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
|
||||
QHashIterator<int, QString> iter(m_handleToFolderMap);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
iter.next();
|
||||
int watchHandle = iter.key();
|
||||
inotify_rm_watch(m_iNotifyHandle, watchHandle);
|
||||
}
|
||||
m_handleToFolderMap.clear();
|
||||
m_handleToFolderMapLock.unlock();
|
||||
|
||||
::close(m_iNotifyHandle);
|
||||
m_iNotifyHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void AddWatchFolder(QString folder)
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
// Clean up the path before accepting it as a watch folder
|
||||
QString cleanPath = QDir::cleanPath(folder);
|
||||
|
||||
// Add the folder to watch and track it
|
||||
int watchHandle = inotify_add_watch(m_iNotifyHandle,
|
||||
cleanPath.toUtf8().constData(),
|
||||
IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY);
|
||||
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
m_handleToFolderMap[watchHandle] = cleanPath;
|
||||
m_handleToFolderMapLock.unlock();
|
||||
|
||||
// Add all the subfolders to watch and track them
|
||||
QDirIterator dirIter(folder, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
|
||||
while (dirIter.hasNext())
|
||||
{
|
||||
QString dirName = dirIter.next();
|
||||
if (dirName.endsWith("/.") || dirName.endsWith("/.."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int watchHandle = inotify_add_watch(m_iNotifyHandle,
|
||||
dirName.toUtf8().constData(),
|
||||
IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY);
|
||||
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
m_handleToFolderMap[watchHandle] = dirName;
|
||||
m_handleToFolderMapLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveWatchFolder(int watchHandle)
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
|
||||
QHash<int, QString>::iterator handleToRemove = m_handleToFolderMap.find(watchHandle);
|
||||
if (handleToRemove != m_handleToFolderMap.end())
|
||||
{
|
||||
inotify_rm_watch(m_iNotifyHandle, watchHandle);
|
||||
m_handleToFolderMap.erase(handleToRemove);
|
||||
}
|
||||
|
||||
m_handleToFolderMapLock.unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -36,17 +154,86 @@ FolderRootWatch::~FolderRootWatch()
|
||||
|
||||
bool FolderRootWatch::Start()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
return false;
|
||||
// inotify will be used by linux to monitor file changes within directories under the root folder
|
||||
if (!m_platformImpl->Initialize())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_platformImpl->AddWatchFolder(m_root);
|
||||
|
||||
m_shutdownThreadSignal = false;
|
||||
m_thread = std::thread([this]() { WatchFolderLoop(); });
|
||||
return true;
|
||||
}
|
||||
|
||||
void FolderRootWatch::Stop()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
m_shutdownThreadSignal = true;
|
||||
|
||||
m_platformImpl->Finalize();
|
||||
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_thread.join(); // wait for the thread to finish
|
||||
m_thread = std::thread(); //destroy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FolderRootWatch::WatchFolderLoop()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
char eventBuffer[s_iNotifyReadBufferSize];
|
||||
while (!m_shutdownThreadSignal)
|
||||
{
|
||||
ssize_t bytesRead = ::read(m_platformImpl->m_iNotifyHandle, eventBuffer, s_iNotifyReadBufferSize);
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
// Break out of the loop when the notify handle was closed (outside of this thread)
|
||||
break;
|
||||
}
|
||||
else if (bytesRead > 0)
|
||||
{
|
||||
for (size_t index=0; index<bytesRead;)
|
||||
{
|
||||
struct inotify_event *event = ( struct inotify_event * ) &eventBuffer[ index ];
|
||||
const char* eventName = event->name;
|
||||
|
||||
if (event->mask & (IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE ))
|
||||
{
|
||||
QString pathStr = QString("%1%2%3").arg(m_platformImpl->m_handleToFolderMap[event->wd], QDir::separator(), event->name);
|
||||
|
||||
if (event->mask & (IN_CREATE | IN_MOVED_TO))
|
||||
{
|
||||
if ( event->mask & IN_ISDIR )
|
||||
{
|
||||
// New Directory, add it to the watch
|
||||
m_platformImpl->AddWatchFolder(pathStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessNewFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
else if (event->mask & (IN_DELETE | IN_MOVED_FROM))
|
||||
{
|
||||
if (event->mask & IN_ISDIR)
|
||||
{
|
||||
// Directory Deleted, remove it from the watch
|
||||
m_platformImpl->RemoveWatchFolder(event->wd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessDeleteFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
else if ((event->mask & IN_MODIFY) && ((event->mask & IN_ISDIR) != IN_ISDIR))
|
||||
{
|
||||
ProcessModifyFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
index += s_iNotifyEventSize + event->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <native/FileWatcher/FileWatcher.h>
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
struct FolderRootWatch::PlatformImplementation
|
||||
{
|
||||
PlatformImplementation() : m_directoryHandle(nullptr), m_ioHandle(nullptr) { }
|
||||
HANDLE m_directoryHandle;
|
||||
HANDLE m_ioHandle;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// FolderWatchRoot
|
||||
FolderRootWatch::FolderRootWatch(const QString rootFolder)
|
||||
: m_root(rootFolder)
|
||||
, m_shutdownThreadSignal(false)
|
||||
, m_fileWatcher(nullptr)
|
||||
, m_platformImpl(new PlatformImplementation())
|
||||
{
|
||||
}
|
||||
|
||||
FolderRootWatch::~FolderRootWatch()
|
||||
{
|
||||
// Destructor is required in here since this file contains the definition of struct PlatformImplementation
|
||||
Stop();
|
||||
|
||||
delete m_platformImpl;
|
||||
}
|
||||
|
||||
bool FolderRootWatch::Start()
|
||||
{
|
||||
m_platformImpl->m_directoryHandle = ::CreateFileW(m_root.toStdWString().data(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr);
|
||||
|
||||
if (m_platformImpl->m_directoryHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_platformImpl->m_ioHandle = ::CreateIoCompletionPort(m_platformImpl->m_directoryHandle, nullptr, 1, 0);
|
||||
if (m_platformImpl->m_ioHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_shutdownThreadSignal = false;
|
||||
m_thread = std::thread(std::bind(&FolderRootWatch::WatchFolderLoop, this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FolderRootWatch::Stop()
|
||||
{
|
||||
m_shutdownThreadSignal = true;
|
||||
CloseHandle(m_platformImpl->m_ioHandle);
|
||||
m_platformImpl->m_ioHandle = nullptr;
|
||||
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_thread.join(); // wait for the thread to finish
|
||||
m_thread = std::thread(); //destroy
|
||||
}
|
||||
CloseHandle(m_platformImpl->m_directoryHandle);
|
||||
m_platformImpl->m_directoryHandle = nullptr;
|
||||
}
|
||||
|
||||
void FolderRootWatch::WatchFolderLoop()
|
||||
{
|
||||
FILE_NOTIFY_INFORMATION aFileNotifyInformationList[50000];
|
||||
QString path;
|
||||
OVERLAPPED aOverlapped;
|
||||
LPOVERLAPPED pOverlapped;
|
||||
DWORD dwByteCount;
|
||||
ULONG_PTR ulKey;
|
||||
|
||||
while (!m_shutdownThreadSignal)
|
||||
{
|
||||
::memset(aFileNotifyInformationList, 0, sizeof(aFileNotifyInformationList));
|
||||
::memset(&aOverlapped, 0, sizeof(aOverlapped));
|
||||
|
||||
if (::ReadDirectoryChangesW(m_platformImpl->m_directoryHandle, aFileNotifyInformationList, sizeof(aFileNotifyInformationList), true, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_FILE_NAME, nullptr, &aOverlapped, nullptr))
|
||||
{
|
||||
//wait for up to a second for I/O to signal
|
||||
dwByteCount = 0;
|
||||
if (::GetQueuedCompletionStatus(m_platformImpl->m_ioHandle, &dwByteCount, &ulKey, &pOverlapped, INFINITE))
|
||||
{
|
||||
//if we are signaled to shutdown bypass
|
||||
if (!m_shutdownThreadSignal && ulKey)
|
||||
{
|
||||
if (dwByteCount)
|
||||
{
|
||||
int offset = 0;
|
||||
FILE_NOTIFY_INFORMATION* pFileNotifyInformation = aFileNotifyInformationList;
|
||||
do
|
||||
{
|
||||
pFileNotifyInformation = (FILE_NOTIFY_INFORMATION*)((char*)pFileNotifyInformation + offset);
|
||||
|
||||
path.clear();
|
||||
path.append(m_root);
|
||||
path.append(QString::fromWCharArray(pFileNotifyInformation->FileName, pFileNotifyInformation->FileNameLength / 2));
|
||||
|
||||
QString file = QDir::toNativeSeparators(QDir::cleanPath(path));
|
||||
|
||||
switch (pFileNotifyInformation->Action)
|
||||
{
|
||||
case FILE_ACTION_ADDED:
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
ProcessNewFileEvent(file);
|
||||
break;
|
||||
case FILE_ACTION_REMOVED:
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
ProcessDeleteFileEvent(file);
|
||||
break;
|
||||
case FILE_ACTION_MODIFIED:
|
||||
ProcessModifyFileEvent(file);
|
||||
break;
|
||||
}
|
||||
|
||||
offset = pFileNotifyInformation->NextEntryOffset;
|
||||
} while (offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,10 +445,10 @@ namespace AssetProcessor
|
||||
bool isExcludedDependency = dependencyPathSearch.starts_with(ExcludedDependenciesSymbol);
|
||||
dependencyPathSearch = isExcludedDependency ? dependencyPathSearch.substr(1) : dependencyPathSearch;
|
||||
bool isExactDependency = !AzFramework::StringFunc::Replace(dependencyPathSearch, '*', '%');
|
||||
SanitizeForDatabase(dependencyPathSearch);
|
||||
|
||||
if (cleanedupDependency.m_dependencyType == AssetBuilderSDK::ProductPathDependencyType::ProductFile)
|
||||
{
|
||||
SanitizeForDatabase(dependencyPathSearch);
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer productInfoContainer;
|
||||
QString productNameWithPlatform = QString("%1%2%3").arg(platform.c_str(), AZ_CORRECT_DATABASE_SEPARATOR_STRING, dependencyPathSearch.c_str());
|
||||
|
||||
@@ -508,6 +508,10 @@ namespace AssetProcessor
|
||||
}
|
||||
else
|
||||
{
|
||||
// For source assets, the casing of the input path must be maintained. Just fix up the path separators.
|
||||
AZStd::replace(dependencyPathSearch.begin(), dependencyPathSearch.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
AzFramework::StringFunc::Replace(dependencyPathSearch, AZ_DOUBLE_CORRECT_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR_STRING);
|
||||
|
||||
// See if path matches any source files
|
||||
AzToolsFramework::AssetDatabase::SourceDatabaseEntryContainer sourceInfoContainer;
|
||||
|
||||
|
||||
@@ -190,44 +190,55 @@ Please note that only those seed files will get updated that are active for your
|
||||
void SourceFileRelocator::HandleMetaDataFiles(QStringList pathMatches, QHash<QString, int>& sourceIndexMap, const ScanFolderInfo* scanFolderInfo, SourceFileRelocationContainer& metadataFiles, bool excludeMetaDataFiles) const
|
||||
{
|
||||
QSet<QString> metaDataFileEntries;
|
||||
for (QString file : pathMatches)
|
||||
|
||||
// Remove all the metadata files
|
||||
if (excludeMetaDataFiles)
|
||||
{
|
||||
pathMatches.erase(AZStd::remove_if(pathMatches.begin(), pathMatches.end(), [this](const QString& file)
|
||||
{
|
||||
for (int idx = 0; idx < m_platformConfig->MetaDataFileTypesCount(); idx++)
|
||||
{
|
||||
const auto& [metadataType, extension] = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metadataType, Qt::CaseInsensitive))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Metadata file %s will be ignored because --excludeMetadataFiles was specified in the command line.\n",
|
||||
file.toUtf8().constData());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
pathMatches.end());
|
||||
}
|
||||
|
||||
for (const QString& file : pathMatches)
|
||||
{
|
||||
for (int idx = 0; idx < m_platformConfig->MetaDataFileTypesCount(); idx++)
|
||||
{
|
||||
QPair<QString, QString> metaInfo = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metaInfo.first, Qt::CaseInsensitive))
|
||||
const auto& [metadataType, extension] = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metadataType, Qt::CaseInsensitive))
|
||||
{
|
||||
//it is a metadata file
|
||||
if (excludeMetaDataFiles)
|
||||
const QString normalizedFilePath = AssetUtilities::NormalizeFilePath(file);
|
||||
if (!metaDataFileEntries.contains(normalizedFilePath))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Metadata file %s will be ignored because --excludeMetadataFiles was specified in the command line.\n",
|
||||
file.toUtf8().constData());
|
||||
break; // don't check it against other metafile entries, we've already ascertained its a metafile.
|
||||
}
|
||||
else
|
||||
{
|
||||
QString normalizedFilePath = AssetUtilities::NormalizeFilePath(file);
|
||||
if (metaDataFileEntries.find(normalizedFilePath) == metaDataFileEntries.end())
|
||||
{
|
||||
SourceFileRelocationInfo metaDataFile(file.toUtf8().data(), scanFolderInfo);
|
||||
metaDataFile.m_isMetaDataFile = true;
|
||||
metadataFiles.emplace_back(metaDataFile);
|
||||
metaDataFileEntries.insert(normalizedFilePath);
|
||||
}
|
||||
SourceFileRelocationInfo metaDataFile(file.toUtf8().data(), scanFolderInfo);
|
||||
metaDataFile.m_isMetaDataFile = true;
|
||||
metadataFiles.emplace_back(metaDataFile);
|
||||
metaDataFileEntries.insert(normalizedFilePath);
|
||||
}
|
||||
}
|
||||
else if (!excludeMetaDataFiles && (file.endsWith("." + metaInfo.second, Qt::CaseInsensitive) || metaInfo.second.isEmpty()))
|
||||
else if (!excludeMetaDataFiles && (file.endsWith("." + extension, Qt::CaseInsensitive) || extension.isEmpty()))
|
||||
{
|
||||
// if we are here it implies that a metadata file might exists for this source file,
|
||||
// add metadata file only if it exists and is not added already
|
||||
AZStd::string metadataFilePath(file.toUtf8().data());
|
||||
if (metaInfo.second.isEmpty())
|
||||
if (extension.isEmpty())
|
||||
{
|
||||
metadataFilePath.append(AZStd::string::format(".%s", metaInfo.first.toUtf8().data()));
|
||||
metadataFilePath.append(AZStd::string::format(".%s", metadataType.toUtf8().data()));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::StringFunc::Path::ReplaceExtension(metadataFilePath, metaInfo.first.toUtf8().data());
|
||||
AZ::StringFunc::Path::ReplaceExtension(metadataFilePath, metadataType.toUtf8().data());
|
||||
};
|
||||
|
||||
// The metadata file can have a different case than the source file,
|
||||
|
||||
@@ -1697,7 +1697,10 @@ namespace AssetProcessor
|
||||
|
||||
if(productFileInfo.absoluteDir().entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).empty())
|
||||
{
|
||||
productFileInfo.absoluteDir().rmdir(".");
|
||||
const QDir productDir = productFileInfo.absoluteDir();
|
||||
QDir parentDir = productDir;
|
||||
parentDir.cdUp();
|
||||
successfullyRemoved &= parentDir.rmdir(productDir.dirName());
|
||||
}
|
||||
|
||||
if (successfullyRemoved)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AssetProcessorMessagesTests
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
|
||||
static constexpr unsigned short AssetProcessorPort = static_cast<unsigned short>(888u);
|
||||
static constexpr unsigned short AssetProcessorPort{65535u};
|
||||
|
||||
class AssetProcessorMessages;
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace AssetProcessorMessagesTests
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
AssetUtilities::ResetGameName();
|
||||
|
||||
m_temporarySourceDir = QDir(m_temporaryDir.path());
|
||||
@@ -166,12 +165,10 @@ namespace AssetProcessorMessagesTests
|
||||
});
|
||||
|
||||
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
QEventLoop eventLoop;
|
||||
|
||||
QObject::connect(m_batchApplicationManager->m_connectionManager, &ConnectionManager::ReadyToQuit, &eventLoop, &QEventLoop::quit);
|
||||
@@ -182,7 +179,6 @@ namespace AssetProcessorMessagesTests
|
||||
|
||||
m_assetSystemComponent->Deactivate();
|
||||
m_batchApplicationManager->Destroy();
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
}
|
||||
|
||||
void RunNetworkRequest(AZStd::function<void()> func) const
|
||||
@@ -207,6 +203,7 @@ namespace AssetProcessorMessagesTests
|
||||
|
||||
thread.join();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
MockAssetRequestHandler* m_assetRequestHandler{}; // Not owned, AP will delete this pointer
|
||||
@@ -226,11 +223,7 @@ namespace AssetProcessorMessagesTests
|
||||
AZStd::unique_ptr<AzFramework::AssetSystem::BaseAssetProcessorMessage> m_response;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorMessages, DISABLED_All)
|
||||
#else
|
||||
TEST_F(AssetProcessorMessages, All)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
// Test that we can successfully send network messages and have them arrive for processing
|
||||
// For messages that have a response, it also verifies the response comes back
|
||||
@@ -311,11 +304,7 @@ namespace AssetProcessorMessagesTests
|
||||
});
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorMessages, DISABLED_GetUnresolvedProductReferences_Succeeds)
|
||||
#else
|
||||
TEST_F(AssetProcessorMessages, GetUnresolvedProductReferences_Succeeds)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetDatabase;
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ namespace UnitTests
|
||||
SourceDatabaseEntry sourceFile8 = { m_data->m_scanFolder1.m_scanFolderID, "test.txt", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile9 = { m_data->m_scanFolder1.m_scanFolderID, "duplicate/folder/file1.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile10 = { m_data->m_scanFolder1.m_scanFolderID, "folder/file.foo", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile11 = { m_data->m_scanFolder1.m_scanFolderID, "testfolder/file.foo", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile1));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile2));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile3));
|
||||
@@ -123,7 +122,6 @@ namespace UnitTests
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile8));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile9));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile10));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile11));
|
||||
|
||||
SourceFileDependencyEntry dependency1 = { AZ::Uuid::CreateRandom(), "subfolder1/somefile.tif", "subfolder1/otherfile.tif", SourceFileDependencyEntry::TypeOfDependency::DEP_SourceToSource, false };
|
||||
SourceFileDependencyEntry dependency2 = { AZ::Uuid::CreateRandom(), "subfolder1/otherfile.tif", "otherfile.tif", SourceFileDependencyEntry::TypeOfDependency::DEP_JobToJob, false };
|
||||
@@ -176,8 +174,6 @@ namespace UnitTests
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/dummy/foo.metadataextension")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/folder/file.foo")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/folder/file.bar")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/file.foo")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/File.bar")));
|
||||
|
||||
if (AZ::IO::FileIOBase::GetInstance() == nullptr)
|
||||
{
|
||||
@@ -487,20 +483,12 @@ namespace UnitTests
|
||||
TestGetSourcesByPath("dev/", { }, false);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_MultipleScanFolders_Fails)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_MultipleScanFolders_Fails)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
TestGetSourcesByPath("*", { }, false);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_PartialPath_FailsWithNoResults)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_PartialPath_FailsWithNoResults)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
TestGetSourcesByPath("older/*", { }, false);
|
||||
}
|
||||
@@ -547,18 +535,6 @@ namespace UnitTests
|
||||
TestGetSourcesByPath(filePath.toUtf8().constData(), { "folder/file.foo" }, true, true);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_HaveMetadataDifferentFileCase_AbsolutePath_Succeeds)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_HaveMetadataDifferentFileCase_AbsolutePath_Succeeds)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto filePath = QDir(tempPath.absoluteFilePath(m_data->m_scanFolder1.m_scanFolder.c_str())).absoluteFilePath("testfolder/file.foo");
|
||||
TestGetSourcesByPath(filePath.toUtf8().constData(), { "testfolder/file.foo", "testfolder/File.bar" }, true, false);
|
||||
}
|
||||
|
||||
TEST_F(SourceFileRelocatorTest, GetMetaDataFile_SingleFileWildcard_Succeeds)
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
@@ -921,32 +897,46 @@ namespace UnitTests
|
||||
ASSERT_FALSE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_Delete_Real_Readonly_Fails)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, Delete_Real_Readonly_Fails)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
struct AutoResetDirectoryReadOnlyState
|
||||
{
|
||||
AutoResetDirectoryReadOnlyState(QString dirName)
|
||||
: m_dirName(AZStd::move(dirName))
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(m_dirName.toUtf8().constData(), false);
|
||||
}
|
||||
~AutoResetDirectoryReadOnlyState()
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(m_dirName.toUtf8().constData(), true);
|
||||
}
|
||||
AZ_DISABLE_COPY_MOVE(AutoResetDirectoryReadOnlyState)
|
||||
private:
|
||||
QString m_dirName;
|
||||
};
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto filePath = QDir(tempPath.absoluteFilePath(m_data->m_scanFolder1.m_scanFolder.c_str())).absoluteFilePath("duplicate/file1.tif");
|
||||
|
||||
ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
|
||||
AutoResetDirectoryReadOnlyState readOnlyResetter(QFileInfo(filePath).absoluteDir().absolutePath());
|
||||
|
||||
AZ::IO::SystemFile::SetWritable(filePath.toUtf8().constData(), false);
|
||||
|
||||
auto result = m_data->m_reporter->Delete(filePath.toUtf8().constData(), false);
|
||||
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
|
||||
RelocationSuccess successResult = result.TakeValue();
|
||||
|
||||
ASSERT_EQ(successResult.m_moveSuccessCount, 0);
|
||||
ASSERT_EQ(successResult.m_moveFailureCount, 1);
|
||||
ASSERT_EQ(successResult.m_moveTotalCount, 1);
|
||||
ASSERT_EQ(successResult.m_updateTotalCount, 0);
|
||||
EXPECT_EQ(successResult.m_moveSuccessCount, 0);
|
||||
EXPECT_EQ(successResult.m_moveFailureCount, 1);
|
||||
EXPECT_EQ(successResult.m_moveTotalCount, 1);
|
||||
EXPECT_EQ(successResult.m_updateTotalCount, 0);
|
||||
|
||||
ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
EXPECT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
}
|
||||
|
||||
TEST_F(SourceFileRelocatorTest, Delete_Real_WithDependencies_Fails)
|
||||
|
||||
@@ -30,11 +30,7 @@ public:
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies);
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_DeferredResolution);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, DISABLED_AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, DeleteFolder_SignalsDeleteOfContainedFiles);
|
||||
|
||||
@@ -70,19 +66,11 @@ public:
|
||||
friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_ValidatePathDependenciesMap);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedSourceFileTypeProductPathDependency_DependencyHasNoProductOutput_ValidatePathDependenciesMap);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, DISABLED_ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, DISABLED_ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile);
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAgain);
|
||||
@@ -2362,11 +2350,7 @@ TEST_F(PathDependencyTest, ChangeDependencies_Existing_ResolveCorrectly)
|
||||
);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(PathDependencyTest, DISABLED_MixedPathDependencies_Existing_ResolveCorrectly)
|
||||
#else
|
||||
TEST_F(PathDependencyTest, MixedPathDependencies_Existing_ResolveCorrectly)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
@@ -2661,11 +2645,7 @@ TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDepende
|
||||
ASSERT_NE(SearchDependencies(dependencyContainer, asset1.m_products[0]), SearchDependencies(dependencyContainer, asset1.m_products[1]));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(MultiplatformPathDependencyTest, DISABLED_AssetProcessed_Impl_MultiplatformDependencies_SourcePath)
|
||||
#else
|
||||
TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
// One product will be pc, one will be console (order is non-deterministic)
|
||||
TestAsset asset1("testAsset1");
|
||||
@@ -3894,7 +3874,7 @@ void ModtimeScanningTest::ProcessAssetJobs()
|
||||
|
||||
for (const auto& processResult : m_data->m_processResults)
|
||||
{
|
||||
auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName + ".arc1");
|
||||
auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName.toLower() + ".arc1");
|
||||
m_data->m_productPaths.emplace(
|
||||
QDir(processResult.m_jobEntry.m_watchFolderPath)
|
||||
.absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName)
|
||||
@@ -3943,11 +3923,11 @@ void ModtimeScanningTest::ExpectWork(int createJobs, int processJobs)
|
||||
{
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
|
||||
ASSERT_EQ(m_data->m_processResults.size(), processJobs);
|
||||
ASSERT_FALSE(m_data->m_processResults[0].m_autoFail);
|
||||
ASSERT_FALSE(m_data->m_processResults[1].m_autoFail);
|
||||
ASSERT_EQ(m_data->m_deletedSources.size(), 0);
|
||||
EXPECT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
|
||||
EXPECT_EQ(m_data->m_processResults.size(), processJobs);
|
||||
EXPECT_FALSE(m_data->m_processResults[0].m_autoFail);
|
||||
EXPECT_FALSE(m_data->m_processResults[1].m_autoFail);
|
||||
EXPECT_EQ(m_data->m_deletedSources.size(), 0);
|
||||
|
||||
m_isIdling = false;
|
||||
}
|
||||
@@ -3975,11 +3955,7 @@ void ModtimeScanningTest::SetFileContents(QString filePath, QString contents)
|
||||
file.close();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(ModtimeScanningTest, DISABLED_ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
|
||||
#else
|
||||
TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
|
||||
@@ -4008,11 +3984,7 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged)
|
||||
ExpectNoWork();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(ModtimeScanningTest, DISABLED_ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
|
||||
#else
|
||||
TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
|
||||
@@ -4633,11 +4605,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_WildcardM
|
||||
dependList.clear();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorManagerTest, DISABLED_RemoveSource_RemoveCacheFolderIfEmpty_Ok)
|
||||
#else
|
||||
TEST_F(AssetProcessorManagerTest, RemoveSource_RemoveCacheFolderIfEmpty_Ok)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
|
||||
+40
-54
@@ -14,6 +14,7 @@
|
||||
#include "native/tests/platformconfiguration/platformconfigurationtests.h"
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
const char TestAppRoot[] = "@exefolder@/testdata";
|
||||
const char EmptyDummyProjectName[] = "EmptyDummyProject";
|
||||
@@ -238,33 +239,6 @@ TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetScanFolderForFile_Sub
|
||||
EXPECT_STREQ(info->GetDisplayName().toUtf8().constData(), "Editor ScanFolder");
|
||||
}
|
||||
|
||||
// note that in the case of GetOverridingFile, this SHOULD return the correct case if an override is found
|
||||
// because its possible to override a file with another file with different case in a different scan folder
|
||||
// such a situation is supposed to be very rare, so the cost of correcting the case is mitigated.
|
||||
TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_Exists_ReturnsCorrectCase)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
// create two scan folders, since its order dependent, the ScanFolder1 is the "winner" in tie breakers (when they both contain same file relpath)
|
||||
QString scanfolder1Path = m_tempPath.filePath("scanfolder1");
|
||||
QString scanfolder2Path = m_tempPath.filePath("scanfolder2");
|
||||
QString caseSensitiveDummyFileName = m_tempPath.absoluteFilePath("scanfolder1/TestCase.tXt");
|
||||
QString differentCaseDummyFileName = m_tempPath.absoluteFilePath("scanfolder2/testcase.txt");
|
||||
UnitTestUtils::CreateDummyFile(caseSensitiveDummyFileName, QString("testcase1\n"));
|
||||
UnitTestUtils::CreateDummyFile(differentCaseDummyFileName, QString("testcase2\n"));
|
||||
m_config->AddScanFolder(ScanFolderInfo(scanfolder1Path, "ScanFolder1", "sf1", false, true, m_platforms), true);
|
||||
m_config->AddScanFolder(ScanFolderInfo(scanfolder2Path, "ScanFolder2", "sf2", false, true, m_platforms), true);
|
||||
|
||||
// Perform the test by asking it whether anyone overrides "testcase" (lowercase) in scanfolder 2.
|
||||
QString overrider = m_config->GetOverridingFile("testcase.txt", scanfolder2Path);
|
||||
|
||||
ASSERT_FALSE(overrider.isEmpty());
|
||||
// the result should be the real actual case of the file in scanfolder 1:
|
||||
EXPECT_STREQ(overrider.toUtf8().constData(), caseSensitiveDummyFileName.toUtf8().constData());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_ExistsButNotOverridden_ReturnsEmpty)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
@@ -360,7 +334,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderCount(), 3); // the two, and then the one that has the same data as prior but different identifier.
|
||||
QString scanName = AssetUtilities::ComputeProjectPath() + " Scan Folder";
|
||||
QString scanName = AssetUtilities::ComputeProjectPath(true) + " Scan Folder";
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetDisplayName(), scanName);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).RecurseSubFolders(), true);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetOrder(), 0);
|
||||
@@ -445,15 +419,11 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
|
||||
ASSERT_FALSE(config.IsFileExcluded("blahblah/Levels/blahblahhold/whatever.test"));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(PlatformConfigurationUnitTests, DISABLED_TestFailReadConfigFile_Recognizers)
|
||||
#else
|
||||
TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_LINUX)
|
||||
const char* platformWhichIsNotCurrentPlatform = "mac";
|
||||
#else
|
||||
const char* platformWhichIsNotCurrentPlatform = "pc";
|
||||
@@ -502,31 +472,47 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
|
||||
// the "rend" test makes sure that even if you dont specify 'params' its still there by default for all enabled platforms.
|
||||
// (but platforms can override it)
|
||||
ASSERT_TRUE(recogs.contains("rend"));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("server"));
|
||||
ASSERT_FALSE(recogs["rend"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there.
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs["android"].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs["server"].m_extraRCParams, ""); // default if not specified is empty string
|
||||
EXPECT_THAT(
|
||||
recogs["rend"].m_platformSpecs.keys(),
|
||||
testing::AllOf(
|
||||
testing::UnorderedElementsAre(
|
||||
QString(AzToolsFramework::AssetSystem::GetHostAssetPlatform()),
|
||||
QString("android"),
|
||||
QString("server")
|
||||
),
|
||||
testing::Not(testing::Contains(platformWhichIsNotCurrentPlatform)) // this is not an enabled platform and should not be there.
|
||||
)
|
||||
);
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs["android"].m_extraRCParams, "rendererparams");
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs["server"].m_extraRCParams, ""); // default if not specified is empty string
|
||||
|
||||
ASSERT_TRUE(recogs.contains("alldefault"));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("server"));
|
||||
ASSERT_FALSE(recogs["alldefault"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there.
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "");
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs["android"].m_extraRCParams, "");
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs["server"].m_extraRCParams, "");
|
||||
EXPECT_THAT(
|
||||
recogs["alldefault"].m_platformSpecs.keys(),
|
||||
testing::AllOf(
|
||||
testing::UnorderedElementsAre(
|
||||
QString(AzToolsFramework::AssetSystem::GetHostAssetPlatform()),
|
||||
QString("android"),
|
||||
QString("server")
|
||||
),
|
||||
testing::Not(testing::Contains(platformWhichIsNotCurrentPlatform)) // this is not an enabled platform and should not be there.
|
||||
)
|
||||
);
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "");
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs["android"].m_extraRCParams, "");
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs["server"].m_extraRCParams, "");
|
||||
|
||||
ASSERT_TRUE(recogs.contains("skipallbutone"));
|
||||
ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["skipallbutone"].m_platformSpecs.contains("server")); // server is only one enabled (set to copy)
|
||||
ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs.size(), 1);
|
||||
ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
EXPECT_THAT(
|
||||
recogs["skipallbutone"].m_platformSpecs.keys(),
|
||||
testing::UnorderedElementsAre(
|
||||
QString("server") // server is only one enabled (set to copy)
|
||||
)
|
||||
);
|
||||
EXPECT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
EXPECT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("android"));
|
||||
EXPECT_EQ(recogs["skipallbutone"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -137,10 +137,13 @@ TEST_F(AssetUtilitiesTest, UpdateToCorrectCase_ExistingFile_ReturnsTrue_Corrects
|
||||
thingsToTry << "SomeFile.TxT";
|
||||
thingsToTry << "otherfile.txt";
|
||||
thingsToTry << "subfolder1/otherfile.txt";
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
thingsToTry << "subfolder2\\otherfile.txt";
|
||||
thingsToTry << "subFolder3\\somefile.txt";
|
||||
thingsToTry << "subFolder4\\subfolder6\\somefile.txt";
|
||||
thingsToTry << "subFolder5\\subfolder7/someFile.txt";
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
thingsToTry << "specialFileName[.txt";
|
||||
thingsToTry << "specialFileName].txt";
|
||||
thingsToTry << "specialFileName!.txt";
|
||||
|
||||
@@ -175,6 +175,16 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_FALSE(gameName.isEmpty());
|
||||
// should create cache folder in the root, and read everything from there.
|
||||
|
||||
// There is a sub-case of handling mixed cases, but is only supported on case-insensitive filesystems.
|
||||
#if defined(AZ_PLATFORM_LINUX)
|
||||
// Linux is case-sensitive, so 'basefile.txt' will stay the same case as the other subfolder versions
|
||||
constexpr const char* subfolder3BaseFilePath = "subfolder3/basefile.txt";
|
||||
constexpr int expectedLegacyAssetIdCount = 1;
|
||||
#else
|
||||
constexpr const char* subfolder3BaseFilePath = "subfolder3/BaseFile.txt";
|
||||
constexpr int expectedLegacyAssetIdCount = 2;
|
||||
#endif
|
||||
|
||||
QSet<QString> expectedFiles;
|
||||
// set up some interesting files:
|
||||
expectedFiles << tempPath.absoluteFilePath("rootfile2.txt");
|
||||
@@ -185,7 +195,9 @@ namespace AssetProcessor
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/ccc/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/ccc/ddd/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/BaseFile.txt"); // note the case upper here
|
||||
|
||||
expectedFiles << tempPath.absoluteFilePath(subfolder3BaseFilePath);
|
||||
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder8/a/b/c/test.txt");
|
||||
|
||||
// subfolder3 is not recursive so none of these should show up in any scan or override check
|
||||
@@ -1521,7 +1533,8 @@ namespace AssetProcessor
|
||||
|
||||
// -------------- override test -----------------
|
||||
// set up by letting it compile basefile.txt from 3:
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder3/BaseFile.txt"));
|
||||
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath(subfolder3BaseFilePath));
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
|
||||
@@ -1583,8 +1596,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 4);
|
||||
for (auto element : assetMessages)
|
||||
{
|
||||
// because the source asset had UPPER CASE in it, we should have multiple legacy IDs
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_legacyAssetIds.size() == 2);
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_legacyAssetIds.size() == expectedLegacyAssetIdCount);
|
||||
}
|
||||
|
||||
// ------------- setup complete, now do the test...
|
||||
@@ -1607,7 +1619,7 @@ namespace AssetProcessor
|
||||
|
||||
// delete the highest priority override file and ensure that it generates tasks
|
||||
// for the next highest priority! Basically, deleting this file should "reveal" the file underneath it in the other subfolder
|
||||
QString deletedFile = tempPath.absoluteFilePath("subfolder3/BaseFile.txt");
|
||||
QString deletedFile = tempPath.absoluteFilePath(subfolder3BaseFilePath);
|
||||
QString expectedReplacementInputFile = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder2/basefile.txt"));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::remove(deletedFile));
|
||||
@@ -1621,6 +1633,11 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
#if defined(AZ_PLATFORM_LINUX)
|
||||
// On Linux, because of we cannot change the case of the source file, the job fingerprint is not updated due the case-switch so
|
||||
// there will be actually nothing to process
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 0);
|
||||
#else
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
@@ -1641,7 +1658,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1.startsWith(platformFolder));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_computedFingerprint != 0);
|
||||
}
|
||||
|
||||
#endif // defined(AZ_PLATFORM_LINUX)
|
||||
relativePathFromWatchFolder = "somefile.xxx";
|
||||
watchFolderPath = tempPath.absoluteFilePath("subfolder3");
|
||||
absolutePath = watchFolderPath + "/" + relativePathFromWatchFolder;
|
||||
@@ -2721,7 +2738,12 @@ namespace AssetProcessor
|
||||
{
|
||||
AssetBuilderSDK::JobDescriptor secondDescriptor = descriptor;
|
||||
secondDescriptor.m_jobKey = "yyy";
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
sourceFileDependency.m_sourceFileDependencyPath = "some\\random/Folders/FILEa.TxT";
|
||||
#else
|
||||
sourceFileDependency.m_sourceFileDependencyPath = "some/random/folders/FileA.txt";
|
||||
#endif // defined(AZ_PLATFORM_WINDOWS)
|
||||
|
||||
// ... declare a job dependency on job A ('FileA.txt', 'xxx', platform)
|
||||
AssetBuilderSDK::JobDependency jobDependency("xxx", platformInfo.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Fingerprint, sourceFileDependency);
|
||||
secondDescriptor.m_jobDependencyList.push_back(jobDependency);
|
||||
@@ -2805,11 +2827,11 @@ namespace AssetProcessor
|
||||
QDir cacheRoot;
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::ComputeProjectCacheRoot(cacheRoot));
|
||||
|
||||
QString productFileAPath = cacheRoot.filePath(QString("pc/FileAProduct.txt"));
|
||||
QString productFileBPath = cacheRoot.filePath(QString("pc/FileBProduct1.txt"));
|
||||
QString product2FileBPath = cacheRoot.filePath(QString("pc/FileBProduct2.txt"));
|
||||
QString productFileCPath = cacheRoot.filePath(QString("pc/FileCProduct.txt"));
|
||||
QString product2FileCPath = cacheRoot.filePath(QString("pc/FileCProduct2.txt"));
|
||||
QString productFileAPath = cacheRoot.filePath(QString("pc/fileaproduct.txt"));
|
||||
QString productFileBPath = cacheRoot.filePath(QString("pc/filebproduct1.txt"));
|
||||
QString product2FileBPath = cacheRoot.filePath(QString("pc/filebproduct2.txt"));
|
||||
QString productFileCPath = cacheRoot.filePath(QString("pc/filecproduct.txt"));
|
||||
QString product2FileCPath = cacheRoot.filePath(QString("pc/filecproduct2.txt"));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(sourceFileAPath, ""));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(sourceFileBPath, ""));
|
||||
|
||||
@@ -106,7 +106,7 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Waiting for remaining notifications: %d \n", outstandingFiles.count());
|
||||
}
|
||||
|
||||
if (outstandingFiles.count() > 0)
|
||||
if (outstandingFiles.count() > 0)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Timed out waiting for file changes: %d / %d missed\n", outstandingFiles.count(), maxFiles);
|
||||
@@ -226,7 +226,9 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(originalName).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName1).toLower());
|
||||
@@ -249,7 +251,10 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
// the new1 was "removed" and the new2 was "added"
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(newName1).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName2).toLower());
|
||||
|
||||
@@ -270,11 +275,15 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
// the new1 was "removed" and the new2 was "added"
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(newName2).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName3).toLower());
|
||||
|
||||
// final test... make sure that renaming a DIRECTORY works too
|
||||
#if !defined(AZ_PLATFORM_LINUX)
|
||||
// final test... make sure that renaming a DIRECTORY works too.
|
||||
// Note that linux does not get any callbacks if just the directory is renamed (from inotify)
|
||||
QDir renamer;
|
||||
fileAddCalled = false;
|
||||
fileRemoveCalled = false;
|
||||
@@ -297,7 +306,7 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(tempDirPath.absoluteFilePath("dir3")).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(tempDirPath.absoluteFilePath("dir4")).toLower());
|
||||
|
||||
#endif // AZ_PLATFORM_LINUX
|
||||
|
||||
QObject::disconnect(connectionRemove);
|
||||
QObject::disconnect(connectionAdd);
|
||||
|
||||
@@ -545,10 +545,13 @@ void RCcontrollerUnitTests::RunRCControllerTests()
|
||||
rcJob.SetCheckExclusiveLock(true);
|
||||
rcJob.Start();
|
||||
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// on windows, opening a file for reading locks it
|
||||
// but on other platforms, this is not the case.
|
||||
// we only expect work to begin when we can gain an exclusive lock on this file.
|
||||
UNIT_TEST_EXPECT_FALSE(UnitTestUtils::BlockUntil(beginWork, 5000));
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Once we release the file, it should process normally
|
||||
lockFileTest.close();
|
||||
#else
|
||||
|
||||
@@ -227,8 +227,9 @@ void UtilitiesUnitTests::StartTest()
|
||||
#else
|
||||
int handle = open(lockTestFileName.toUtf8().constData(), O_RDONLY | O_EXLOCK | O_NONBLOCK);
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
UNIT_TEST_EXPECT_FALSE(AssetUtilities::CheckCanLock(lockTestFileName));
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_FALSE(AssetUtilities::CheckCanLock(lockTestFileName));
|
||||
lockTestFile.close();
|
||||
#else
|
||||
if (handle != -1)
|
||||
|
||||
@@ -507,8 +507,13 @@ namespace AssetUtilities
|
||||
return QString::fromUtf8(s_projectName.c_str(), aznumeric_cast<int>(s_projectName.size()));
|
||||
}
|
||||
|
||||
QString ComputeProjectPath()
|
||||
QString ComputeProjectPath(bool resetCachedProjectPath/*=false*/)
|
||||
{
|
||||
if (resetCachedProjectPath)
|
||||
{
|
||||
// Clear any cached value if reset was requested
|
||||
s_projectPath.clear();
|
||||
}
|
||||
if (s_projectPath.empty())
|
||||
{
|
||||
// Check command-line args first
|
||||
|
||||
@@ -104,7 +104,8 @@ namespace AssetUtilities
|
||||
QString ComputeProjectName(QString projectNameOverride = QString(), bool force = false);
|
||||
|
||||
//! Determine the absolute path of the current project
|
||||
QString ComputeProjectPath();
|
||||
//! The path computed path will be cached on subsequent calls unless resetCachedProjectPath=true
|
||||
QString ComputeProjectPath(bool resetCachedProjectPath = false);
|
||||
|
||||
//! Reads the allowed list directly from the bootstrap file
|
||||
QString ReadAllowedlistFromSettingsRegistry(QString initialFolder = QString());
|
||||
|
||||
Reference in New Issue
Block a user