Merge remote-tracking branch 'upstream/development' into nvsickle/GenericDomDocument
This commit is contained in:
@@ -1392,7 +1392,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(done);
|
||||
}
|
||||
|
||||
// Fixture for thread-driller-bus related calls
|
||||
// Fixture for thread-event-bus related calls
|
||||
// exists only to categorize the tests.
|
||||
class ThreadEventsBus :
|
||||
public AllocatorsFixture
|
||||
@@ -1438,44 +1438,33 @@ namespace UnitTest
|
||||
TEST_F(ThreadEventsBus, Broadcasts_BothBusses)
|
||||
{
|
||||
ThreadEventCounter<AZStd::ThreadEventBus::Handler> eventBusCounter;
|
||||
ThreadEventCounter<AZStd::ThreadDrillerEventBus::Handler> drillerBusCounter;
|
||||
auto thread_function = [&]()
|
||||
{
|
||||
; // intentionally left blank
|
||||
};
|
||||
|
||||
eventBusCounter.Connect();
|
||||
drillerBusCounter.Connect();
|
||||
|
||||
AZStd::thread starter = AZStd::thread(thread_function);
|
||||
starter.join();
|
||||
EXPECT_EQ(drillerBusCounter.m_enterCount, 1);
|
||||
EXPECT_EQ(drillerBusCounter.m_exitCount, 1);
|
||||
EXPECT_EQ(eventBusCounter.m_enterCount, 1);
|
||||
EXPECT_EQ(eventBusCounter.m_exitCount, 1);
|
||||
eventBusCounter.Disconnect();
|
||||
drillerBusCounter.Disconnect();
|
||||
}
|
||||
|
||||
// this class tests for deadlocks caused by interactions between the thread
|
||||
// driller bus and the other driller busses.
|
||||
// Client code (ie, not part of the driller system) can connec to the
|
||||
// ThreadEventBus and be told when threads are started and stopped
|
||||
// However, if they instead listen to the ThreadDrillerEventBus, a deadlock condition
|
||||
// could be caused if they lock a mutex that another thread needs in order to proceed.
|
||||
// This test makes sure that using the ThreadEventBus (ie, the one meant for client code)
|
||||
// instead of the ThreadDrillerEventBus (the one meant only for profilers) does NOT cause
|
||||
// a deadlock.
|
||||
// This class tests for deadlocks caused by multiple threads interacting with the ThreadEventBus.
|
||||
// Client code can connect to the ThreadEventBus and be told when threads are started and stopped.
|
||||
// A deadlock condition could be caused if they lock a mutex that another thread needs in order to proceed.
|
||||
// This test makes sure that using the ThreadEventBus does NOT cause a deadlock.
|
||||
|
||||
// We will simulate this series of events by doing the following
|
||||
// 1. Main thread listens on the ThreadEventBus
|
||||
// 2. OnThreadExit will lock a mutex, perform an allocation, unlock a mutex
|
||||
// 3. The thread itself will lock the mutex, perform an allocation, unlock the mutex.
|
||||
// As long as there is no cross talk between the client and the driller busses, the
|
||||
// above operation should not deadlock.
|
||||
// but if there is, then a deadlock can occur where one thread will be unable to perform
|
||||
// its allocation because the other is in OnThreadExit()
|
||||
// and the other will not be able to perform OnThreadExit() because it cannot lock the mutex.
|
||||
// As long as there is no cross talk between threads, the above operation should not deadlock.
|
||||
// If there is, then a deadlock can occur where one thread will be unable to perform
|
||||
// its allocation because the other is in OnThreadExit() and the other will not be able to perform
|
||||
// OnThreadExit() because it cannot lock the mutex.
|
||||
|
||||
class ThreadEventsDeathTest :
|
||||
public AllocatorsFixture
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "UserTypes.h"
|
||||
#include <AzCore/std/typetraits/internal/is_template_copy_constructible.h>
|
||||
#include <AzCore/std/containers/forward_list.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/parallel/condition_variable.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
|
||||
#include <AZTestShared/Utils/Utils.h>
|
||||
#include <Streamer/IStreamerMock.h>
|
||||
#include <Tests/Asset/BaseAssetManagerTest.h>
|
||||
@@ -131,8 +132,8 @@ namespace UnitTest
|
||||
* This will test the aspect of the system where ObjectStreams and asset jobs loading dependent
|
||||
* assets will do the work in their own thread.
|
||||
*/
|
||||
class AssetJobsFloodTest
|
||||
: public BaseAssetManagerTest
|
||||
|
||||
class AssetJobsFloodTest : public DisklessAssetManagerBase
|
||||
{
|
||||
public:
|
||||
TestAssetManager* m_testAssetManager{ nullptr };
|
||||
@@ -183,15 +184,14 @@ namespace UnitTest
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
BaseAssetManagerTest::SetUp();
|
||||
DisklessAssetManagerBase::SetUp();
|
||||
SetupTest();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TearDownTest();
|
||||
AssetManager::Destroy();
|
||||
BaseAssetManagerTest::TearDown();
|
||||
DisklessAssetManagerBase::TearDown();
|
||||
}
|
||||
|
||||
void SetupAssets()
|
||||
@@ -257,9 +257,9 @@ namespace UnitTest
|
||||
AssetWithSerializedData ap2;
|
||||
AssetWithSerializedData ap3;
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset4.txt", AZ::DataStream::ST_XML, &ap1, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset5.txt", AZ::DataStream::ST_XML, &ap2, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset6.txt", AZ::DataStream::ST_XML, &ap3, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset4.txt", &ap1, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset5.txt", &ap2, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset6.txt", &ap3, m_serializeContext));
|
||||
|
||||
AssetWithAssetReference assetWithPreload1;
|
||||
AssetWithAssetReference assetWithPreload2;
|
||||
@@ -273,11 +273,11 @@ namespace UnitTest
|
||||
noLoadAsset.m_asset = m_testAssetManager->CreateAsset<AssetWithSerializedData>(MyAsset2Id, AssetLoadBehavior::NoLoad);
|
||||
EXPECT_EQ(m_assetHandlerAndCatalog->m_numCreations, 4);
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset1.txt", AZ::DataStream::ST_XML, &assetWithPreload1, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset2.txt", AZ::DataStream::ST_XML, &assetWithPreload2, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset3.txt", AZ::DataStream::ST_XML, &assetWithPreload3, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "DelayLoadAsset.txt", AZ::DataStream::ST_XML, &delayedAsset, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "NoLoadAsset.txt", AZ::DataStream::ST_XML, &noLoadAsset, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset1.txt", &assetWithPreload1, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset2.txt", &assetWithPreload2, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset3.txt", &assetWithPreload3, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("DelayLoadAsset.txt", &delayedAsset, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("NoLoadAsset.txt", &noLoadAsset, m_serializeContext));
|
||||
|
||||
AssetWithQueueAndPreLoadReferences preLoadRoot;
|
||||
AssetWithQueueAndPreLoadReferences preLoadA;
|
||||
@@ -297,16 +297,16 @@ namespace UnitTest
|
||||
preLoadBrokenA.m_preLoad = m_testAssetManager->CreateAsset<AssetWithAssetReference>(PreloadBrokenDepBId, AssetLoadBehavior::PreLoad);
|
||||
preLoadBrokenB.m_preLoad = m_testAssetManager->CreateAsset<AssetWithAssetReference>(PreloadAssetNoDataId, AssetLoadBehavior::PreLoad);
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadRoot.txt", AZ::DataStream::ST_XML, &preLoadRoot, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadA.txt", AZ::DataStream::ST_XML, &preLoadA, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadB.txt", AZ::DataStream::ST_XML, &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadC.txt", AZ::DataStream::ST_XML, &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "QueueLoadA.txt", AZ::DataStream::ST_XML, &queueLoadA, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "QueueLoadB.txt", AZ::DataStream::ST_XML, &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "QueueLoadC.txt", AZ::DataStream::ST_XML, &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadBrokenA.txt", AZ::DataStream::ST_XML, &preLoadBrokenA, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadBrokenB.txt", AZ::DataStream::ST_XML, &preLoadBrokenB, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "PreLoadNoData.txt", AZ::DataStream::ST_XML, &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadRoot.txt", &preLoadRoot, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadA.txt", &preLoadA, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadB.txt", &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadC.txt", &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("QueueLoadA.txt", &queueLoadA, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("QueueLoadB.txt", &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("QueueLoadC.txt", &noRefs, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadBrokenA.txt", &preLoadBrokenA, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadBrokenB.txt", &preLoadBrokenB, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("PreLoadNoData.txt", &noRefs, m_serializeContext));
|
||||
|
||||
AssetWithQueueAndPreLoadReferences circularA;
|
||||
AssetWithQueueAndPreLoadReferences circularB;
|
||||
@@ -318,43 +318,15 @@ namespace UnitTest
|
||||
circularC.m_preLoad = m_testAssetManager->CreateAsset<AssetWithAssetReference>(CircularBId, AssetLoadBehavior::PreLoad);
|
||||
circularD.m_preLoad = circularC.m_preLoad;
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "CircularA.txt", AZ::DataStream::ST_XML, &circularA, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "CircularB.txt", AZ::DataStream::ST_XML, &circularB, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "CircularC.txt", AZ::DataStream::ST_XML, &circularC, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "CircularD.txt", AZ::DataStream::ST_XML, &circularD, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("CircularA.txt", &circularA, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("CircularB.txt", &circularB, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("CircularC.txt", &circularC, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("CircularD.txt", &circularD, m_serializeContext));
|
||||
|
||||
m_assetHandlerAndCatalog->m_numCreations = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TearDownTest()
|
||||
{
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset4.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset5.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset6.txt");
|
||||
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset1.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset2.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "TestAsset3.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "DelayLoadAsset.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "NoLoadAsset.txt");
|
||||
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadRoot.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadA.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadB.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadC.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "QueueLoadA.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "QueueLoadB.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "QueueLoadC.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadBrokenA.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadBrokenB.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "PreLoadNoData.txt");
|
||||
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "CircularA.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "CircularB.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "CircularC.txt");
|
||||
DeleteAssetFromDisk(GetTestFolderPath() + "CircularD.txt");
|
||||
}
|
||||
|
||||
void CheckFinishedCreationsAndDestructions()
|
||||
{
|
||||
// Make sure asset jobs have finished before validating the number of destroyed assets, because it's possible that the asset job
|
||||
@@ -367,7 +339,7 @@ namespace UnitTest
|
||||
};
|
||||
|
||||
static constexpr AZStd::chrono::seconds MaxDispatchTimeoutSeconds = BaseAssetManagerTest::DefaultTimeoutSeconds * 12;
|
||||
|
||||
|
||||
template <typename Pred>
|
||||
bool DispatchEventsUntilCondition(AZ::Data::AssetManager& assetManager, Pred&& conditionPredicate,
|
||||
AZStd::chrono::seconds logIntervalSeconds = BaseAssetManagerTest::DefaultTimeoutSeconds,
|
||||
@@ -608,7 +580,7 @@ namespace UnitTest
|
||||
AZ::Data::AssetData::AssetStatus expected_base_status = AZ::Data::AssetData::AssetStatus::Ready;
|
||||
EXPECT_EQ(baseStatus, expected_base_status);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AssetJobsFloodTest, RapidAcquireAndRelease)
|
||||
{
|
||||
auto assetUuids = {
|
||||
@@ -641,7 +613,7 @@ namespace UnitTest
|
||||
{
|
||||
Asset<AssetWithAssetReference> asset1 =
|
||||
m_testAssetManager->GetAsset(assetUuid, azrtti_typeid<AssetWithAssetReference>(), AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
|
||||
if (checkLoaded)
|
||||
{
|
||||
asset1.BlockUntilLoadComplete();
|
||||
@@ -714,8 +686,8 @@ namespace UnitTest
|
||||
|
||||
AssetWithSerializedData ap;
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "a.txt", AZ::DataStream::ST_XML, &ap, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "b.txt", AZ::DataStream::ST_XML, &ap, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("a.txt", &ap, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("b.txt", &ap, m_serializeContext));
|
||||
}
|
||||
|
||||
auto& assetManager = AssetManager::Instance();
|
||||
@@ -778,7 +750,7 @@ namespace UnitTest
|
||||
* Verify that loads without using the Asset Container still work correctly
|
||||
*/
|
||||
class AssetContainerDisableTest
|
||||
: public BaseAssetManagerTest
|
||||
: public DisklessAssetManagerBase
|
||||
{
|
||||
public:
|
||||
static inline const AZ::Uuid MyAsset1Id{ "{5B29FE2B-6B41-48C9-826A-C723951B0560}" };
|
||||
@@ -797,7 +769,7 @@ namespace UnitTest
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
BaseAssetManagerTest::SetUp();
|
||||
DisklessAssetManagerBase::SetUp();
|
||||
SetupTest();
|
||||
|
||||
}
|
||||
@@ -807,7 +779,7 @@ namespace UnitTest
|
||||
AssetManager::Instance().UnregisterHandler(m_assetHandlerAndCatalog);
|
||||
delete m_assetHandlerAndCatalog;
|
||||
AssetManager::Destroy();
|
||||
BaseAssetManagerTest::TearDown();
|
||||
DisklessAssetManagerBase::TearDown();
|
||||
}
|
||||
|
||||
void SetupAssets()
|
||||
@@ -849,9 +821,9 @@ namespace UnitTest
|
||||
AssetWithSerializedData ap2;
|
||||
AssetWithSerializedData ap3;
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset4.txt", AZ::DataStream::ST_XML, &ap1, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset5.txt", AZ::DataStream::ST_XML, &ap2, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset6.txt", AZ::DataStream::ST_XML, &ap3, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset4.txt", &ap1, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset5.txt", &ap2, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset6.txt", &ap3, m_serializeContext));
|
||||
|
||||
AssetWithAssetReference assetWithPreload1;
|
||||
AssetWithAssetReference assetWithPreload2;
|
||||
@@ -862,9 +834,9 @@ namespace UnitTest
|
||||
assetWithPreload3.m_asset = m_testAssetManager->CreateAsset<AssetWithSerializedData>(MyAsset6Id, AssetLoadBehavior::PreLoad);
|
||||
EXPECT_EQ(m_assetHandlerAndCatalog->m_numCreations, 3);
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset1.txt", AZ::DataStream::ST_XML, &assetWithPreload1, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset2.txt", AZ::DataStream::ST_XML, &assetWithPreload2, m_serializeContext));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset3.txt", AZ::DataStream::ST_XML, &assetWithPreload3, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset1.txt", &assetWithPreload1, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset2.txt", &assetWithPreload2, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset3.txt", &assetWithPreload3, m_serializeContext));
|
||||
|
||||
m_assetHandlerAndCatalog->m_numCreations = 0;
|
||||
}
|
||||
@@ -942,11 +914,11 @@ namespace UnitTest
|
||||
m_testAssetManager->SetParallelDependentLoadingEnabled(true);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
TEST_F(AssetJobsFloodTest, DISABLED_LoadTest_SameAsset_DifferentFilters)
|
||||
#else
|
||||
TEST_F(AssetJobsFloodTest, LoadTest_SameAsset_DifferentFilters)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
{
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
|
||||
|
||||
@@ -1291,11 +1263,11 @@ namespace UnitTest
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadDependencies_NoLoadNotLoaded)
|
||||
#else
|
||||
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadDependencies_NoLoadNotLoaded)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
{
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
|
||||
// Setup has already created/destroyed assets
|
||||
@@ -1332,11 +1304,11 @@ namespace UnitTest
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadContainerDependencies_LoadAllLoadsNoLoad)
|
||||
#else
|
||||
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadContainerDependencies_LoadAllLoadsNoLoad)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
{
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
|
||||
// Setup has already created/destroyed assets
|
||||
@@ -1371,11 +1343,11 @@ namespace UnitTest
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadDependencies_BehaviorObeyed)
|
||||
#else
|
||||
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadDependencies_BehaviorObeyed)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
{
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
|
||||
// Setup has already created/destroyed assets
|
||||
@@ -2014,11 +1986,12 @@ namespace UnitTest
|
||||
CheckFinishedCreationsAndDestructions();
|
||||
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run multiple threads that get and release assets simultaneously to test AssetManager's thread safety
|
||||
*/
|
||||
class AssetJobsMultithreadedTest
|
||||
: public BaseAssetManagerTest
|
||||
: public DisklessAssetManagerBase
|
||||
{
|
||||
public:
|
||||
static inline const AZ::Uuid MyAsset1Id{ "{5B29FE2B-6B41-48C9-826A-C723951B0560}" };
|
||||
@@ -2028,6 +2001,7 @@ namespace UnitTest
|
||||
static inline const AZ::Uuid MyAsset5Id{ "{D9CDAB04-D206-431E-BDC0-1DD615D56197}" };
|
||||
static inline const AZ::Uuid MyAsset6Id{ "{B2F139C3-5032-4B52-ADCA-D52A8F88E043}" };
|
||||
|
||||
|
||||
// Initialize the Job Manager with 2 threads for the Asset Manager to use.
|
||||
size_t GetNumJobManagerThreads() const override { return 2; }
|
||||
|
||||
@@ -2078,9 +2052,9 @@ namespace UnitTest
|
||||
AssetWithSerializedData ap2;
|
||||
AssetWithSerializedData ap3;
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset4.txt", AZ::DataStream::ST_XML, &ap1, &context));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset5.txt", AZ::DataStream::ST_XML, &ap2, &context));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset6.txt", AZ::DataStream::ST_XML, &ap3, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset4.txt", &ap1, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset5.txt", &ap2, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset6.txt", &ap3, &context));
|
||||
|
||||
AssetWithAssetReference assetWithPreload1;
|
||||
AssetWithAssetReference assetWithPreload2;
|
||||
@@ -2089,9 +2063,9 @@ namespace UnitTest
|
||||
assetWithPreload2.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset5Id, AssetLoadBehavior::PreLoad);
|
||||
assetWithPreload3.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset6Id, AssetLoadBehavior::PreLoad);
|
||||
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset1.txt", AZ::DataStream::ST_XML, &assetWithPreload1, &context));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset2.txt", AZ::DataStream::ST_XML, &assetWithPreload2, &context));
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset3.txt", AZ::DataStream::ST_XML, &assetWithPreload3, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset1.txt", &assetWithPreload1, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset2.txt", &assetWithPreload2, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset3.txt", &assetWithPreload3, &context));
|
||||
|
||||
EXPECT_TRUE(assetHandlerAndCatalog->m_numCreations == 3);
|
||||
assetHandlerAndCatalog->m_numCreations = 0;
|
||||
@@ -2191,22 +2165,22 @@ namespace UnitTest
|
||||
// A will be saved to disk with MyAsset1Id
|
||||
AssetWithAssetReference a;
|
||||
a.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset2Id);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset1.txt", AZ::DataStream::ST_XML, &a, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset1.txt", &a, &context));
|
||||
AssetWithAssetReference b;
|
||||
b.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset3Id);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset2.txt", AZ::DataStream::ST_XML, &b, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset2.txt", &b, &context));
|
||||
AssetWithAssetReference c;
|
||||
c.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset4Id);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset3.txt", AZ::DataStream::ST_XML, &c, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset3.txt", &c, &context));
|
||||
AssetWithAssetReference d;
|
||||
d.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset5Id);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset4.txt", AZ::DataStream::ST_XML, &d, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset4.txt", &d, &context));
|
||||
AssetWithAssetReference e;
|
||||
e.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset6Id);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset5.txt", AZ::DataStream::ST_XML, &e, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset5.txt", &e, &context));
|
||||
AssetWithAssetReference f;
|
||||
f.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(MyAsset1Id); // refer back to asset1
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset6.txt", AZ::DataStream::ST_XML, &f, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset6.txt", &f, &context));
|
||||
|
||||
EXPECT_TRUE(assetHandlerAndCatalog->m_numCreations == 6);
|
||||
assetHandlerAndCatalog->m_numCreations = 0;
|
||||
@@ -2347,26 +2321,26 @@ namespace UnitTest
|
||||
// AssetD is MYASSETD
|
||||
AssetWithSerializedData d;
|
||||
d.m_data = 42;
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset4.txt", AZ::DataStream::ST_XML, &d, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset4.txt", &d, &context));
|
||||
|
||||
// AssetC is MYASSETC
|
||||
AssetWithAssetReference c;
|
||||
c.m_asset = db.CreateAsset<AssetWithSerializedData>(AssetId(MyAssetDId)); // point at D
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset3.txt", AZ::DataStream::ST_XML, &c, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset3.txt", &c, &context));
|
||||
|
||||
// AssetB is MYASSETB
|
||||
AssetWithAssetReference b;
|
||||
b.m_asset = db.CreateAsset<AssetWithAssetReference>(AssetId(MyAssetCId)); // point at C
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset2.txt", AZ::DataStream::ST_XML, &b, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset2.txt", &b, &context));
|
||||
|
||||
// AssetA will be written to disk as MYASSETA
|
||||
AssetWithAssetReference a;
|
||||
a.m_asset = db.CreateAsset<AssetWithAssetReference>(AssetId(MyAssetBId)); // point at B
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "TestAsset1.txt", AZ::DataStream::ST_XML, &a, &context));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("TestAsset1.txt", &a, &context));
|
||||
}
|
||||
|
||||
const size_t numThreads = 4;
|
||||
AZStd::atomic_int threadCount(numThreads);
|
||||
constexpr size_t NumThreads = 4;
|
||||
AZStd::atomic_int threadCount(NumThreads);
|
||||
AZStd::condition_variable cv;
|
||||
AZStd::vector<AZStd::thread> threads;
|
||||
AZStd::atomic_bool keepDispatching(true);
|
||||
@@ -2381,7 +2355,7 @@ namespace UnitTest
|
||||
|
||||
AZStd::thread dispatchThread(dispatch);
|
||||
|
||||
for (size_t threadIdx = 0; threadIdx < numThreads; ++threadIdx)
|
||||
for (size_t threadIdx = 0; threadIdx < NumThreads; ++threadIdx)
|
||||
{
|
||||
threads.emplace_back([&threadCount, &db, &cv]()
|
||||
{
|
||||
@@ -2569,7 +2543,6 @@ namespace UnitTest
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
TEST_F(AssetJobsMultithreadedTest, DISABLED_ParallelDeepAssetReferences)
|
||||
#else
|
||||
// temporarily disabled until sporadic failures can be root caused
|
||||
TEST_F(AssetJobsMultithreadedTest, ParallelDeepAssetReferences)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
|
||||
{
|
||||
@@ -2577,7 +2550,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
class AssetManagerTests
|
||||
: public BaseAssetManagerTest
|
||||
: public DisklessAssetManagerBase
|
||||
{
|
||||
protected:
|
||||
static inline const AZ::Uuid MyAsset1Id{ "{5B29FE2B-6B41-48C9-826A-C723951B0560}" };
|
||||
@@ -2592,7 +2565,7 @@ namespace UnitTest
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
BaseAssetManagerTest::SetUp();
|
||||
DisklessAssetManagerBase::SetUp();
|
||||
|
||||
m_console = AZStd::make_unique<AZ::Console>();
|
||||
AZ::Interface<AZ::IConsole>::Register(m_console.get());
|
||||
@@ -2631,7 +2604,7 @@ namespace UnitTest
|
||||
AssetManager::Destroy();
|
||||
AZ::Interface<AZ::IConsole>::Unregister(m_console.get());
|
||||
m_console = nullptr;
|
||||
BaseAssetManagerTest::TearDown();
|
||||
DisklessAssetManagerBase::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2982,7 +2955,7 @@ namespace UnitTest
|
||||
* the middle of loading. The tests help ensure that assets can't get stuck in perpetual loading states.
|
||||
**/
|
||||
class AssetManagerClearAssetReferenceTests
|
||||
: public BaseAssetManagerTest
|
||||
: public DisklessAssetManagerBase
|
||||
{
|
||||
protected:
|
||||
static inline const AZ::Uuid RootAssetId{ "{AB13F568-C676-41FE-A7E9-341F71A78104}" };
|
||||
@@ -3001,7 +2974,7 @@ namespace UnitTest
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
BaseAssetManagerTest::SetUp();
|
||||
DisklessAssetManagerBase::SetUp();
|
||||
|
||||
// create the database
|
||||
AssetManager::Descriptor desc;
|
||||
@@ -3039,21 +3012,18 @@ namespace UnitTest
|
||||
|
||||
// Create and save the dependent asset first, so that we can get a reference to it.
|
||||
AssetWithSerializedData dependentBlockingAsset;
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "DependentPreloadBlockingAsset.txt",
|
||||
AZ::DataStream::ST_XML, &dependentBlockingAsset, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("DependentPreloadBlockingAsset.txt", &dependentBlockingAsset, m_serializeContext));
|
||||
|
||||
AssetWithAssetReference dependentAsset;
|
||||
dependentAsset.m_asset = AssetManager::Instance().CreateAsset<AssetWithAssetReference>(
|
||||
NestedDependentPreloadBlockingAssetId, AssetLoadBehavior::PreLoad);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "DependentPreloadAsset.txt",
|
||||
AZ::DataStream::ST_XML, &dependentAsset, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("DependentPreloadAsset.txt", &dependentAsset, m_serializeContext));
|
||||
|
||||
// Create and save the top-level asset.
|
||||
AssetWithAssetReference rootAsset;
|
||||
rootAsset.m_asset = AssetManager::Instance().CreateAsset<AssetWithAssetReference>(
|
||||
DependentPreloadAssetId, AssetLoadBehavior::PreLoad);
|
||||
EXPECT_TRUE(AZ::Utils::SaveObjectToFile(GetTestFolderPath() + "RootAsset.txt",
|
||||
AZ::DataStream::ST_XML, &rootAsset, m_serializeContext));
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile("RootAsset.txt", &rootAsset, m_serializeContext));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
@@ -3065,7 +3035,7 @@ namespace UnitTest
|
||||
delete m_assetHandlerAndCatalog;
|
||||
|
||||
AssetManager::Destroy();
|
||||
BaseAssetManagerTest::TearDown();
|
||||
DisklessAssetManagerBase::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -165,4 +165,254 @@ namespace UnitTest
|
||||
|
||||
EXPECT_FALSE(AssetManager::Instance().HasActiveJobsOrStreamerRequests());
|
||||
}
|
||||
|
||||
MemoryStreamerWrapper::MemoryStreamerWrapper()
|
||||
{
|
||||
using ::testing::_;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
|
||||
ON_CALL(m_mockStreamer, SuspendProcessing()).WillByDefault([this]()
|
||||
{
|
||||
m_suspended = true;
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, ResumeProcessing()).WillByDefault([this]()
|
||||
{
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
|
||||
m_suspended = false;
|
||||
|
||||
while (!m_processingQueue.empty())
|
||||
{
|
||||
FileRequestHandle requestHandle = m_processingQueue.front();
|
||||
m_processingQueue.pop();
|
||||
|
||||
const auto& onCompleteCallback = GetReadRequest(requestHandle)->m_callback;
|
||||
|
||||
if (onCompleteCallback)
|
||||
{
|
||||
onCompleteCallback(requestHandle);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, Read(_, ::testing::An<IStreamerTypes::RequestMemoryAllocator&>(), _, _, _, _))
|
||||
.WillByDefault(
|
||||
[this](
|
||||
[[maybe_unused]] AZStd::string_view relativePath, IStreamerTypes::RequestMemoryAllocator& allocator, size_t size,
|
||||
AZStd::chrono::microseconds deadline, IStreamerTypes::Priority priority, [[maybe_unused]] size_t offset)
|
||||
{
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
|
||||
ReadRequest request;
|
||||
|
||||
// Save off the requested deadline and priority
|
||||
request.m_deadline = deadline;
|
||||
request.m_priority = priority;
|
||||
request.m_data = allocator.Allocate(size, size, 8);
|
||||
|
||||
const auto* virtualFile = FindFile(relativePath);
|
||||
|
||||
AZ_Assert(
|
||||
virtualFile->size() == size, "Streamer read request size did not match size of saved file: %d vs %d (%.*s)",
|
||||
virtualFile->size(), size,
|
||||
relativePath.size(), relativePath.data());
|
||||
AZ_Assert(size > 0, "Size is zero %.*s", relativePath.size(), relativePath.data());
|
||||
|
||||
memcpy(request.m_data.m_address, virtualFile->data(), size);
|
||||
|
||||
// Create a real file request result and return it
|
||||
request.m_request = m_context.GetNewExternalRequest();
|
||||
|
||||
m_readRequests.push_back(request);
|
||||
|
||||
return request.m_request;
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, SetRequestCompleteCallback(_, _))
|
||||
.WillByDefault([this](FileRequestPtr& request, AZ::IO::IStreamer::OnCompleteCallback callback) -> FileRequestPtr&
|
||||
{
|
||||
// Save off the callback just so that we can call it when the request is "done"
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
ReadRequest* readRequest = GetReadRequest(request);
|
||||
readRequest->m_callback = callback;
|
||||
|
||||
return request;
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, QueueRequest(_))
|
||||
.WillByDefault([this](const auto& fileRequest)
|
||||
{
|
||||
if (!m_suspended)
|
||||
{
|
||||
decltype(ReadRequest::m_callback) onCompleteCallback;
|
||||
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
ReadRequest* readRequest = GetReadRequest(fileRequest);
|
||||
onCompleteCallback = readRequest->m_callback;
|
||||
|
||||
if (onCompleteCallback)
|
||||
{
|
||||
onCompleteCallback(fileRequest);
|
||||
|
||||
m_readRequests.erase(readRequest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
|
||||
m_processingQueue.push(fileRequest);
|
||||
}
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, GetRequestStatus(_))
|
||||
.WillByDefault([]([[maybe_unused]] FileRequestHandle request)
|
||||
{
|
||||
// Return whatever request status has been set in this class
|
||||
return IO::IStreamerTypes::RequestStatus::Completed;
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, GetReadRequestResult(_, _, _, _))
|
||||
.WillByDefault([this](
|
||||
[[maybe_unused]] FileRequestHandle request, void*& buffer, AZ::u64& numBytesRead,
|
||||
IStreamerTypes::ClaimMemory claimMemory)
|
||||
{
|
||||
// Make sure the requestor plans to free the data buffer we allocated.
|
||||
EXPECT_EQ(claimMemory, IStreamerTypes::ClaimMemory::Yes);
|
||||
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
|
||||
ReadRequest* readRequest = GetReadRequest(request);
|
||||
|
||||
// Provide valid data buffer results.
|
||||
numBytesRead = readRequest->m_data.m_size;
|
||||
buffer = readRequest->m_data.m_address;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
ON_CALL(m_mockStreamer, RescheduleRequest(_, _, _))
|
||||
.WillByDefault([this](IO::FileRequestPtr target, AZStd::chrono::microseconds newDeadline, IO::IStreamerTypes::Priority newPriority)
|
||||
{
|
||||
AZStd::unique_lock lock(m_mutex);
|
||||
ReadRequest* readRequest = GetReadRequest(target);
|
||||
|
||||
readRequest->m_deadline = newDeadline;
|
||||
readRequest->m_priority = newPriority;
|
||||
|
||||
return target;
|
||||
});
|
||||
}
|
||||
|
||||
ReadRequest* MemoryStreamerWrapper::GetReadRequest(FileRequestHandle request)
|
||||
{
|
||||
auto itr = AZStd::find_if(
|
||||
m_readRequests.begin(), m_readRequests.end(),
|
||||
[request](const ReadRequest& searchItem) -> bool
|
||||
{
|
||||
return (searchItem.m_request == request);
|
||||
});
|
||||
|
||||
return itr;
|
||||
}
|
||||
|
||||
AZStd::vector<char>* MemoryStreamerWrapper::FindFile(AZStd::string_view path)
|
||||
{
|
||||
auto itr = m_virtualFiles.find(path);
|
||||
|
||||
if (itr == m_virtualFiles.end())
|
||||
{
|
||||
// Path didn't work as-is, does it have the test folder prefixed? If so try removing it
|
||||
if (AZ::StringFunc::StartsWith(path, GetTestFolderPath()))
|
||||
{
|
||||
AZStd::string_view pathWithoutFolder = path;
|
||||
|
||||
pathWithoutFolder = AZ::StringFunc::LStrip(pathWithoutFolder, GetTestFolderPath().c_str());
|
||||
itr = m_virtualFiles.find(pathWithoutFolder);
|
||||
}
|
||||
else // Path isn't prefixed, so try adding it
|
||||
{
|
||||
itr = m_virtualFiles.find(GetTestFolderPath().append(path));
|
||||
}
|
||||
}
|
||||
|
||||
if (itr != m_virtualFiles.end())
|
||||
{
|
||||
return &itr->second;
|
||||
}
|
||||
|
||||
// Currently no test expects a file not to exist so we assert to make it easy to quickly find where something went wrong
|
||||
// If we ever need to test for a non-existent file this assert should just be conditionally disabled for that specific test
|
||||
AZ_Assert(false, "Failed to find virtual file %*.s", path.size(), path.data())
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DisklessAssetManagerBase::SetUp()
|
||||
{
|
||||
using ::testing::_;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
|
||||
BaseAssetManagerTest::SetUp();
|
||||
|
||||
ON_CALL(m_fileIO, Size(::testing::Matcher<const char*>(::testing::_), _))
|
||||
.WillByDefault(
|
||||
[this](const char* path, u64& size)
|
||||
{
|
||||
AZStd::scoped_lock lock(m_streamerWrapper->m_mutex);
|
||||
|
||||
const auto* file = m_streamerWrapper->FindFile(path);
|
||||
|
||||
if (file)
|
||||
{
|
||||
size = file->size();
|
||||
return ResultCode::Success;
|
||||
}
|
||||
|
||||
AZ_Error("DisklessAssetManagerBase", false, "Failed to find virtual file %.*s", path);
|
||||
|
||||
return ResultCode::Error;
|
||||
});
|
||||
|
||||
m_prevFileIO = IO::FileIOBase::GetInstance();
|
||||
IO::FileIOBase::SetInstance(nullptr);
|
||||
IO::FileIOBase::SetInstance(&m_fileIO);
|
||||
}
|
||||
|
||||
void DisklessAssetManagerBase::TearDown()
|
||||
{
|
||||
IO::FileIOBase::SetInstance(nullptr);
|
||||
IO::FileIOBase::SetInstance(m_prevFileIO);
|
||||
|
||||
BaseAssetManagerTest::TearDown();
|
||||
}
|
||||
|
||||
IO::IStreamer* DisklessAssetManagerBase::CreateStreamer()
|
||||
{
|
||||
m_streamerWrapper = AZStd::make_unique<MemoryStreamerWrapper>();
|
||||
|
||||
return &(m_streamerWrapper->m_mockStreamer);
|
||||
}
|
||||
|
||||
void DisklessAssetManagerBase::DestroyStreamer(IO::IStreamer*)
|
||||
{
|
||||
m_streamerWrapper = nullptr;
|
||||
}
|
||||
|
||||
void DisklessAssetManagerBase::WriteAssetToDisk(const AZStd::string& assetName, const AZStd::string&)
|
||||
{
|
||||
AZStd::string assetFileName = GetTestFolderPath() + assetName;
|
||||
|
||||
AssetWithCustomData asset;
|
||||
|
||||
EXPECT_TRUE(m_streamerWrapper->WriteMemoryFile(assetFileName, &asset, m_serializeContext));
|
||||
}
|
||||
|
||||
void DisklessAssetManagerBase::DeleteAssetFromDisk(const AZStd::string&)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#include <Tests/Asset/TestAssetTypes.h>
|
||||
#include <Tests/SerializeContextFixture.h>
|
||||
#include <Tests/TestCatalog.h>
|
||||
|
||||
#include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
|
||||
#include <Streamer/IStreamerMock.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
@@ -58,7 +59,11 @@ namespace UnitTest
|
||||
|
||||
// Subclasses can optionally override the streamer creation and destruction
|
||||
virtual IO::IStreamer* CreateStreamer() { return aznew IO::Streamer(AZStd::thread_desc{}, StreamerComponent::CreateStreamerStack()); }
|
||||
virtual void DestroyStreamer(IO::IStreamer* streamer) { delete streamer; }
|
||||
virtual void DestroyStreamer(IO::IStreamer* streamer)
|
||||
{
|
||||
delete streamer;
|
||||
streamer = nullptr;
|
||||
}
|
||||
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
@@ -66,8 +71,8 @@ namespace UnitTest
|
||||
static void SuppressTraceOutput(bool suppress);
|
||||
|
||||
// Helper methods to create and destroy actual assets on the disk for true end-to-end asset loading.
|
||||
void WriteAssetToDisk(const AZStd::string& assetName, const AZStd::string& assetIdGuid);
|
||||
void DeleteAssetFromDisk(const AZStd::string& assetName);
|
||||
virtual void WriteAssetToDisk(const AZStd::string& assetName, const AZStd::string& assetIdGuid);
|
||||
virtual void DeleteAssetFromDisk(const AZStd::string& assetName);
|
||||
|
||||
void BlockUntilAssetJobsAreComplete();
|
||||
|
||||
@@ -82,4 +87,57 @@ namespace UnitTest
|
||||
AZStd::vector<AZStd::string> m_assetsWritten;
|
||||
};
|
||||
|
||||
|
||||
struct ReadRequest
|
||||
{
|
||||
AZStd::chrono::milliseconds m_deadline{};
|
||||
AZ::IO::IStreamerTypes::Priority m_priority{};
|
||||
IO::IStreamerTypes::RequestMemoryAllocatorResult m_data{ nullptr, 0, IO::IStreamerTypes::MemoryType::ReadWrite };
|
||||
AZ::IO::IStreamer::OnCompleteCallback m_callback;
|
||||
IO::FileRequestPtr m_request;
|
||||
};
|
||||
|
||||
struct MemoryStreamerWrapper
|
||||
{
|
||||
MemoryStreamerWrapper();
|
||||
~MemoryStreamerWrapper() = default;
|
||||
|
||||
ReadRequest* GetReadRequest(IO::FileRequestHandle request);
|
||||
|
||||
template<typename TObject>
|
||||
bool WriteMemoryFile(const AZStd::string& filePath, TObject* object, AZ::SerializeContext* context)
|
||||
{
|
||||
auto& buffer = m_virtualFiles[filePath];
|
||||
ByteContainerStream stream(&buffer);
|
||||
|
||||
return AZ::Utils::SaveObjectToStream(stream, DataStream::StreamType::ST_XML, object, context);
|
||||
}
|
||||
|
||||
AZStd::vector<char>* FindFile(AZStd::string_view path);
|
||||
|
||||
::testing::NiceMock<StreamerMock> m_mockStreamer;
|
||||
IO::StreamerContext m_context;
|
||||
AZStd::atomic_bool m_suspended{ false };
|
||||
|
||||
AZStd::recursive_mutex m_mutex;
|
||||
AZStd::queue<FileRequestHandle> m_processingQueue; // Keeps tracks of requests that have been queued while processing is suspended
|
||||
AZStd::vector<ReadRequest> m_readRequests;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::vector<char>> m_virtualFiles;
|
||||
};
|
||||
|
||||
struct DisklessAssetManagerBase : BaseAssetManagerTest
|
||||
{
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
IO::IStreamer* CreateStreamer() override;
|
||||
void DestroyStreamer(IO::IStreamer*) override;
|
||||
|
||||
void WriteAssetToDisk(const AZStd::string& assetName, const AZStd::string& assetIdGuid) override;
|
||||
void DeleteAssetFromDisk(const AZStd::string& assetName) override;
|
||||
|
||||
AZStd::unique_ptr<MemoryStreamerWrapper> m_streamerWrapper;
|
||||
::testing::NiceMock<MockFileIOBase> m_fileIO;
|
||||
IO::FileIOBase* m_prevFileIO{};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -175,7 +175,6 @@ namespace UnitTest
|
||||
ComponentApplication componentApp;
|
||||
ComponentApplication::Descriptor desc;
|
||||
desc.m_useExistingAllocator = true;
|
||||
desc.m_enableDrilling = false; // we already created a memory driller for the test (AllocatorsFixture)
|
||||
ComponentApplication::StartupParameters startupParams;
|
||||
startupParams.m_allocator = &AZ::AllocatorInstance<AZ::SystemAllocator>::Get();
|
||||
Entity* systemEntity = componentApp.Create(desc, startupParams);
|
||||
@@ -631,7 +630,6 @@ namespace UnitTest
|
||||
|
||||
ComponentApplication::Descriptor desc;
|
||||
desc.m_useExistingAllocator = true;
|
||||
desc.m_enableDrilling = false; // we already created a memory driller for the test (AllocatorsFixture in Components)
|
||||
|
||||
ComponentApplication::StartupParameters startupParams;
|
||||
startupParams.m_allocator = &AZ::AllocatorInstance<AZ::SystemAllocator>::Get();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Debug/StackTracer.h>
|
||||
#include <AzCore/Debug/TraceMessagesDrillerBus.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
@@ -104,7 +104,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
class TraceTest
|
||||
: public AZ::Debug::TraceMessageDrillerBus::Handler
|
||||
: public AZ::Debug::TraceMessageBus::Handler
|
||||
, public ::testing::Test
|
||||
{
|
||||
int m_numTracePrintfs;
|
||||
@@ -113,12 +113,13 @@ namespace UnitTest
|
||||
: m_numTracePrintfs(0) {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TraceMessagesDrillerBus
|
||||
void OnPrintf(const char* windowName, const char* message) override
|
||||
// TraceMessageBus
|
||||
bool OnPrintf(const char* windowName, const char* message) override
|
||||
{
|
||||
(void)windowName;
|
||||
(void)message;
|
||||
++m_numTracePrintfs;
|
||||
return false;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Debug/AssetTrackingTypesImpl.h>
|
||||
#include <AzCore/Debug/AssetTracking.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct TestData
|
||||
{
|
||||
};
|
||||
|
||||
using AssetTree = AZ::Debug::AssetTree<TestData>;
|
||||
using AllocationTable = AZ::Debug::AllocationTable<TestData>;
|
||||
|
||||
struct AssetTrackingTestEnvironment
|
||||
{
|
||||
AssetTrackingTestEnvironment() : m_table(m_mutex)
|
||||
{
|
||||
}
|
||||
|
||||
AZStd::mutex m_mutex;
|
||||
AssetTree m_tree;
|
||||
AllocationTable m_table;
|
||||
AZStd::unique_ptr<AZ::Debug::AssetTracking> m_assetTracking;
|
||||
};
|
||||
}
|
||||
|
||||
class AssetTrackingTests
|
||||
: public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::Debug::AssetTrackingAllocator>::Create();
|
||||
m_env.reset(new AssetTrackingTestEnvironment);
|
||||
m_env->m_assetTracking.reset(aznew AZ::Debug::AssetTracking(&m_env->m_tree, &m_env->m_table));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_env.reset();
|
||||
AZ::AllocatorInstance<AZ::Debug::AssetTrackingAllocator>::Destroy();
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
TestAssetScopes();
|
||||
TestScopedAllocation();
|
||||
TestScopeAttach();
|
||||
}
|
||||
|
||||
private:
|
||||
void TestAssetScopes()
|
||||
{
|
||||
const char* debugScopeText;
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestAssetScopes.1");
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestAssetScopes.2");
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestAssetScopes.3");
|
||||
debugScopeText = AZ::Debug::AssetTracking::GetDebugScope();
|
||||
EXPECT_STREQ(debugScopeText, "TestAssetScopes.3\nTestAssetScopes.2\nTestAssetScopes.1\n");
|
||||
}
|
||||
|
||||
debugScopeText = AZ::Debug::AssetTracking::GetDebugScope();
|
||||
EXPECT_STREQ(debugScopeText, "TestAssetScopes.2\nTestAssetScopes.1\n");
|
||||
}
|
||||
|
||||
|
||||
debugScopeText = AZ::Debug::AssetTracking::GetDebugScope();
|
||||
EXPECT_STREQ(debugScopeText, "TestAssetScopes.1\n");
|
||||
}
|
||||
}
|
||||
|
||||
void TestScopedAllocation()
|
||||
{
|
||||
void* TEST_POINTER = (void*)0xDEADBEEFull;
|
||||
static const size_t TEST_SIZE = 32;
|
||||
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestScopedAllocation.1");
|
||||
AZ::Debug::AssetTreeNodeBase* activeAsset = m_env->m_assetTracking->GetCurrentThreadAsset();
|
||||
m_env->m_table.Get().emplace(TEST_POINTER, AllocationTable::RecordType{ activeAsset, (uint32_t)TEST_SIZE, TestData() });
|
||||
}
|
||||
|
||||
auto& rootAsset = m_env->m_tree.m_rootAssets;
|
||||
auto itr = rootAsset.m_children.find("TestScopedAllocation.1");
|
||||
|
||||
EXPECT_EQ(&rootAsset, &m_env->m_tree.GetRoot());
|
||||
ASSERT_NE(itr, rootAsset.m_children.end());
|
||||
EXPECT_EQ(itr->second.m_primaryinfo->m_id->m_id, "TestScopedAllocation.1");
|
||||
|
||||
EXPECT_EQ(&itr->second, m_env->m_table.FindAllocation(TEST_POINTER));
|
||||
|
||||
auto allocationRecord = m_env->m_table.Get().find(TEST_POINTER);
|
||||
ASSERT_NE(allocationRecord, m_env->m_table.Get().end());
|
||||
EXPECT_EQ(allocationRecord->second.m_asset, &itr->second);
|
||||
EXPECT_EQ(allocationRecord->second.m_size, TEST_SIZE);
|
||||
|
||||
// Test realocation
|
||||
void* TEST_REALLOC_POINTER = (void*)0xDEADC0DEull;
|
||||
static const size_t TEST_REALLOC_SIZE = 128;
|
||||
|
||||
m_env->m_table.ReallocateAllocation(TEST_POINTER, TEST_REALLOC_POINTER, TEST_REALLOC_SIZE);
|
||||
allocationRecord = m_env->m_table.Get().find(TEST_POINTER);
|
||||
EXPECT_EQ(allocationRecord, m_env->m_table.Get().end());
|
||||
allocationRecord = m_env->m_table.Get().find(TEST_REALLOC_POINTER);
|
||||
ASSERT_NE(allocationRecord, m_env->m_table.Get().end());
|
||||
EXPECT_EQ(allocationRecord->second.m_asset, &itr->second);
|
||||
EXPECT_EQ(allocationRecord->second.m_size, TEST_REALLOC_SIZE);
|
||||
|
||||
// Test resize
|
||||
static const size_t TEST_RESIZE_SIZE = 1024;
|
||||
m_env->m_table.ResizeAllocation(TEST_REALLOC_POINTER, TEST_RESIZE_SIZE);
|
||||
EXPECT_EQ(allocationRecord->second.m_size, TEST_RESIZE_SIZE);
|
||||
}
|
||||
|
||||
void TestScopeAttach()
|
||||
{
|
||||
void* TEST_POINTER = (void*)0xDEADBEEFull;
|
||||
static const size_t TEST_SIZE = 32;
|
||||
AZ::Debug::AssetTreeNodeBase* originatingAsset;
|
||||
|
||||
{
|
||||
AZ_ASSET_ATTACH_TO_SCOPE(TEST_POINTER);
|
||||
EXPECT_EQ(m_env->m_assetTracking->GetCurrentThreadAsset(), nullptr);
|
||||
}
|
||||
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestScopeAttach.1");
|
||||
{
|
||||
AZ_ASSET_NAMED_SCOPE("TestScopeAttach.2");
|
||||
{
|
||||
originatingAsset = m_env->m_assetTracking->GetCurrentThreadAsset();
|
||||
EXPECT_NE(originatingAsset, nullptr);
|
||||
m_env->m_table.Get().emplace(TEST_POINTER, AllocationTable::RecordType{ originatingAsset, (uint32_t)TEST_SIZE, TestData() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(m_env->m_assetTracking->GetCurrentThreadAsset(), nullptr);
|
||||
|
||||
{
|
||||
AZ_ASSET_ATTACH_TO_SCOPE(TEST_POINTER);
|
||||
EXPECT_EQ(m_env->m_assetTracking->GetCurrentThreadAsset(), originatingAsset);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AssetTrackingTestEnvironment> m_env;
|
||||
};
|
||||
|
||||
TEST_F(AssetTrackingTests, Test)
|
||||
{
|
||||
RunTests();
|
||||
}
|
||||
}
|
||||
@@ -2500,7 +2500,7 @@ namespace UnitTest
|
||||
|
||||
namespace RoutingTest
|
||||
{
|
||||
class DrillerInterceptor : public EBusVersion1::Router
|
||||
class EBusInterceptor : public EBusVersion1::Router
|
||||
{
|
||||
public:
|
||||
void OnEvent(int a) override
|
||||
@@ -2555,20 +2555,20 @@ namespace UnitTest
|
||||
TEST_F(EBus, Routing)
|
||||
{
|
||||
using namespace RoutingTest;
|
||||
DrillerInterceptor driller;
|
||||
EBusInterceptor interceptor;
|
||||
EBusVersion1Handler v1Handler;
|
||||
|
||||
v1Handler.BusConnect();
|
||||
driller.BusRouterConnect();
|
||||
interceptor.BusRouterConnect();
|
||||
|
||||
EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
|
||||
EXPECT_EQ(1, driller.m_numOnEvent);
|
||||
EXPECT_EQ(1, interceptor.m_numOnEvent);
|
||||
EXPECT_EQ(1, v1Handler.m_numOnEvent);
|
||||
|
||||
driller.BusRouterDisconnect();
|
||||
interceptor.BusRouterDisconnect();
|
||||
|
||||
EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
|
||||
EXPECT_EQ(1, driller.m_numOnEvent);
|
||||
EXPECT_EQ(1, interceptor.m_numOnEvent);
|
||||
EXPECT_EQ(2, v1Handler.m_numOnEvent);
|
||||
|
||||
// routing events
|
||||
|
||||
@@ -402,17 +402,18 @@ namespace UnitTest
|
||||
AllocatorsFixture::SetUp();
|
||||
AZ::ComponentApplication::Descriptor desc;
|
||||
desc.m_useExistingAllocator = true;
|
||||
desc.m_enableDrilling = false; // we already created a memory driller for the test (AllocatorsFixture)
|
||||
m_app.Create(desc);
|
||||
m_app.reset(aznew AZ::ComponentApplication);
|
||||
m_app->Create(desc);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_app.Destroy();
|
||||
m_app->Destroy();
|
||||
m_app.reset();
|
||||
AllocatorsFixture::TearDown();
|
||||
}
|
||||
|
||||
AZ::ComponentApplication m_app;
|
||||
AZStd::unique_ptr<AZ::ComponentApplication> m_app;
|
||||
};
|
||||
|
||||
TEST_F(MATH_TransformApplicationFixture, DeserializingOldFormat)
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <AzCore/Memory/HeapSchema.h>
|
||||
#include <AzCore/Memory/HphaSchema.h>
|
||||
|
||||
#include <AzCore/Driller/Driller.h>
|
||||
#include <AzCore/Memory/MemoryDriller.h>
|
||||
#include <AzCore/Memory/AllocationRecords.h>
|
||||
#include <AzCore/Debug/StackTracer.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
@@ -44,16 +42,13 @@ namespace UnitTest
|
||||
void SetUp() override
|
||||
{
|
||||
AZ::AllocatorManager::Instance().SetDefaultTrackingMode(AZ::Debug::AllocationRecords::RECORD_FULL);
|
||||
m_drillerManager = Debug::DrillerManager::Create();
|
||||
m_drillerManager->Register(aznew MemoryDriller);
|
||||
AZ::AllocatorManager::Instance().EnterProfilingMode();
|
||||
}
|
||||
void TearDown() override
|
||||
{
|
||||
Debug::DrillerManager::Destroy(m_drillerManager);
|
||||
AZ::AllocatorManager::Instance().ExitProfilingMode();
|
||||
AZ::AllocatorManager::Instance().SetDefaultTrackingMode(AZ::Debug::AllocationRecords::RECORD_NO_RECORDS);
|
||||
}
|
||||
protected:
|
||||
Debug::DrillerManager* m_drillerManager = nullptr;
|
||||
};
|
||||
|
||||
class SystemAllocatorTest
|
||||
|
||||
@@ -270,8 +270,7 @@ namespace UnitTest
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
m_drillerManager = AZ::Debug::DrillerManager::Create();
|
||||
m_drillerManager->Register(aznew AZ::Debug::MemoryDriller);
|
||||
AZ::AllocatorManager::Instance().EnterProfilingMode();
|
||||
AZ::AllocatorManager::Instance().SetDefaultTrackingMode(AZ::Debug::AllocationRecords::RECORD_FULL);
|
||||
|
||||
if (azrtti_typeid<AllocatorType>() != azrtti_typeid<AZ::SystemAllocator>()) // simplifies instead of template specialization
|
||||
@@ -292,7 +291,7 @@ namespace UnitTest
|
||||
// Other allocators need the SystemAllocator in order to work
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
}
|
||||
AZ::Debug::DrillerManager::Destroy(m_drillerManager);
|
||||
AZ::AllocatorManager::Instance().ExitProfilingMode();
|
||||
|
||||
m_busRedirector.BusDisconnect();
|
||||
EXPECT_EQ(m_leakExpected, m_leakDetected);
|
||||
@@ -352,7 +351,6 @@ namespace UnitTest
|
||||
};
|
||||
|
||||
BusRedirector m_busRedirector;
|
||||
AZ::Debug::DrillerManager* m_drillerManager = nullptr;
|
||||
bool m_leakDetected = false;
|
||||
bool m_leakExpected = false;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <AzCore/std/containers/fixed_unordered_map.h>
|
||||
#include <AzCore/std/containers/fixed_unordered_set.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
#include <AzCore/std/containers/forward_list.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/IO/ByteContainerStream.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/Path/PathReflect.h>
|
||||
#include <AzCore/IO/Streamer/StreamerComponent.h>
|
||||
|
||||
#include <AzCore/RTTI/AttributeReader.h>
|
||||
@@ -8151,5 +8152,98 @@ namespace UnitTest
|
||||
m_serializeContext->Class<TestClassWithEnumFieldThatSpecializesTypeInfo>();
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
}
|
||||
|
||||
template <typename ParamType>
|
||||
class PathSerializationParamFixture
|
||||
: public ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<ParamType>
|
||||
{
|
||||
public:
|
||||
PathSerializationParamFixture()
|
||||
: ScopedAllocatorSetupFixture(
|
||||
[]() { AZ::SystemAllocator::Descriptor desc; desc.m_stackRecordLevels = 30; return desc; }()
|
||||
)
|
||||
{}
|
||||
|
||||
// We must expose the class for serialization first.
|
||||
void SetUp() override
|
||||
{
|
||||
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
|
||||
AZ::IO::PathReflect(m_serializeContext.get());
|
||||
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_serializeContext->EnableRemoveReflection();
|
||||
AZ::IO::PathReflect(m_serializeContext.get());
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
|
||||
m_serializeContext.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
||||
};
|
||||
|
||||
struct PathSerializationParams
|
||||
{
|
||||
const char m_preferredSeparator{};
|
||||
const char* m_testPath{};
|
||||
};
|
||||
using PathSerializationFixture = PathSerializationParamFixture<PathSerializationParams>;
|
||||
|
||||
TEST_P(PathSerializationFixture, PathSerializer_SerializesStringBackedPath_Succeeds)
|
||||
{
|
||||
const auto& testParams = GetParam();
|
||||
{
|
||||
// Path serialization
|
||||
AZ::IO::Path testPath{ testParams.m_testPath, testParams.m_preferredSeparator };
|
||||
|
||||
AZStd::vector<char> byteBuffer;
|
||||
AZ::IO::ByteContainerStream byteStream(&byteBuffer);
|
||||
auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
|
||||
objStream->WriteClass(&testPath);
|
||||
objStream->Finalize();
|
||||
|
||||
byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
|
||||
|
||||
AZ::IO::Path loadPath{ testParams.m_preferredSeparator };
|
||||
EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadPath, m_serializeContext.get()));
|
||||
EXPECT_EQ(testPath.LexicallyNormal(), loadPath);
|
||||
}
|
||||
|
||||
{
|
||||
// FixedMaxPath serialization
|
||||
AZ::IO::FixedMaxPath testFixedMaxPath{ testParams.m_testPath, testParams.m_preferredSeparator };
|
||||
|
||||
AZStd::vector<char> byteBuffer;
|
||||
AZ::IO::ByteContainerStream byteStream(&byteBuffer);
|
||||
auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
|
||||
objStream->WriteClass(&testFixedMaxPath);
|
||||
objStream->Finalize();
|
||||
|
||||
byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
|
||||
|
||||
AZ::IO::FixedMaxPath loadPath{ testParams.m_preferredSeparator };
|
||||
EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadPath, m_serializeContext.get()));
|
||||
EXPECT_EQ(testFixedMaxPath.LexicallyNormal(), loadPath);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
PathSerialization,
|
||||
PathSerializationFixture,
|
||||
::testing::Values(
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "" },
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "test" },
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "D:test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "D:/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "test/foo/../bar" }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/std/containers/list.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/forward_list.h>
|
||||
#include <AzCore/std/iterator.h>
|
||||
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
|
||||
#include <Tests/Serialization/Json/TestCases_Classes.h>
|
||||
|
||||
@@ -539,6 +539,22 @@ tags=tools,renderer,metal)"
|
||||
EXPECT_STREQ("Bat", commandLine.GetMiscValue(2).c_str());
|
||||
}
|
||||
|
||||
TEST_F(SettingsRegistryMergeUtilsCommandLineFixture, RegsetFileArgument_DoesNotMergeNUL)
|
||||
{
|
||||
AZStd::string regsetFile = AZ::IO::SystemFile::GetNullFilename();
|
||||
AZ::CommandLine commandLine;
|
||||
commandLine.Parse({ "--regset-file", regsetFile });
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_registry, commandLine, false);
|
||||
|
||||
// Add a settings path to anchor loaded settings underneath
|
||||
regsetFile = AZStd::string::format("%s::/AnchorPath/Of/Settings", AZ::IO::SystemFile::GetNullFilename());
|
||||
commandLine.Parse({ "--regset-file", regsetFile });
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_registry, commandLine, false);
|
||||
EXPECT_EQ(AZ::SettingsRegistryInterface::Type::NoType, m_registry->GetType("/AnchorPath/Of/Settings"));
|
||||
}
|
||||
|
||||
using SettingsRegistryAncestorDescendantOrEqualPathFixture = SettingsRegistryMergeUtilsCommandLineFixture;
|
||||
|
||||
TEST_F(SettingsRegistryAncestorDescendantOrEqualPathFixture, ValidateThatAncestorOrDescendantOrPathWithTheSameValue_Succeeds)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/std/parallel/shared_spin_mutex.h>
|
||||
#include <AzCore/Debug/TraceMessagesDrillerBus.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
|
||||
@@ -468,28 +468,29 @@ namespace UnitTest
|
||||
/** Trace message handler to track messages during tests
|
||||
*/
|
||||
struct MyTraceMessageSink final
|
||||
: public AZ::Debug::TraceMessageDrillerBus::Handler
|
||||
: public AZ::Debug::TraceMessageBus::Handler
|
||||
{
|
||||
MyTraceMessageSink()
|
||||
{
|
||||
AZ::Debug::TraceMessageDrillerBus::Handler::BusConnect();
|
||||
AZ::Debug::TraceMessageBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~MyTraceMessageSink()
|
||||
{
|
||||
AZ::Debug::TraceMessageDrillerBus::Handler::BusDisconnect();
|
||||
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TraceMessageDrillerBus
|
||||
void OnPrintf(const char* window, const char* message) override
|
||||
// TraceMessageBus
|
||||
bool OnPrintf(const char* window, const char* message) override
|
||||
{
|
||||
OnOutput(window, message);
|
||||
return OnOutput(window, message);
|
||||
}
|
||||
|
||||
void OnOutput(const char* window, const char* message) override
|
||||
bool OnOutput(const char* window, const char* message) override
|
||||
{
|
||||
printf("%s: %s\n", window, message);
|
||||
return false;
|
||||
}
|
||||
}; //struct MyTraceMessageSink
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace AZ::IO
|
||||
m_context = nullptr;
|
||||
|
||||
AllocatorInstance<ThreadPoolAllocator>::Destroy();
|
||||
AllocatorInstance<PoolAllocator>::Destroy();
|
||||
AllocatorInstance<PoolAllocator>::Destroy();
|
||||
|
||||
UnitTest::AllocatorsFixture::TearDown();
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace AZ::IO
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*m_mock, QueueRequest(_));
|
||||
EXPECT_CALL(*m_mock, UpdateStatus(_)).Times(AnyNumber());
|
||||
|
||||
|
||||
switch (mockResult)
|
||||
{
|
||||
case ReadResult::Success:
|
||||
@@ -267,7 +267,7 @@ namespace AZ::IO
|
||||
{
|
||||
allCompleted = allCompleted && request.GetStatus() == IStreamerTypes::RequestStatus::Completed;
|
||||
};
|
||||
|
||||
|
||||
FileRequest* requests[count];
|
||||
AZStd::unique_ptr<u32[]> buffers[count];
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
@@ -300,7 +300,7 @@ namespace AZ::IO
|
||||
size = size >> 2;
|
||||
for (u64 i = 0; i < size; ++i)
|
||||
{
|
||||
// Using assert here because in case of a problem EXPECT would
|
||||
// Using assert here because in case of a problem EXPECT would
|
||||
// cause a large amount of log noise.
|
||||
ASSERT_EQ(buffer[i], offset + (i << 2));
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace AZ::IO
|
||||
.Times(2)
|
||||
.WillRepeatedly([this](FileRequest* request) { m_context.MarkRequestAsCompleted(request); });
|
||||
m_context.FinalizeCompletedRequests();
|
||||
|
||||
|
||||
azfree(memory);
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace AZ::IO
|
||||
m_context.FinalizeCompletedRequests();
|
||||
|
||||
EXPECT_EQ(2, completedRequests);
|
||||
|
||||
|
||||
azfree(memory1);
|
||||
azfree(memory0);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace AZ::IO
|
||||
{
|
||||
using ::testing::_;
|
||||
using ::testing::AnyNumber;
|
||||
|
||||
|
||||
UnitTest::AllocatorsFixture::SetUp();
|
||||
|
||||
m_mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
@@ -78,7 +78,7 @@ namespace AZ::IO
|
||||
{
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
|
||||
|
||||
EXPECT_CALL(*m_mock, UpdateStatus(_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, UpdateCompletionEstimates(_, _, _, _)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, PrepareRequest(_))
|
||||
@@ -115,7 +115,7 @@ namespace AZ::IO
|
||||
void MockAllocatorForUnclaimedMemory(IStreamerTypes::RequestMemoryAllocatorMock& mock, AZStd::binary_semaphore& sync)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
EXPECT_CALL(mock, LockAllocator()).Times(1);
|
||||
EXPECT_CALL(mock, UnlockAllocator())
|
||||
.Times(1)
|
||||
@@ -256,13 +256,13 @@ namespace AZ::IO
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Return;
|
||||
|
||||
|
||||
EXPECT_CALL(*m_mock, UpdateStatus(_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, UpdateCompletionEstimates(_, _, _, _)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, PrepareRequest(_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, ExecuteRequests()).Times(AtLeast(1));
|
||||
EXPECT_CALL(*m_mock, QueueRequest(_)).Times(1);
|
||||
|
||||
|
||||
AZStd::atomic_int counter = 2;
|
||||
AZStd::binary_semaphore sync;
|
||||
auto wait = [&sync, &counter](FileRequestHandle)
|
||||
@@ -350,7 +350,7 @@ namespace AZ::IO
|
||||
|
||||
EXPECT_CALL(*m_mock, UpdateStatus(_)).Times(AnyNumber());
|
||||
EXPECT_CALL(*m_mock, UpdateCompletionEstimates(_, _, _, _)).Times(AnyNumber());
|
||||
|
||||
|
||||
// Pretend to be busy [Iterations] times, then set the status to idle so the Scheduler thread can exit.
|
||||
EXPECT_CALL(*m_mock, ExecuteRequests())
|
||||
.Times(Iterations + 1)
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace AZ::IO
|
||||
TYPED_TEST_P(StreamStackEntryConformityTests, SetContext_ContextIsForwardedToNext_SetContextOnMockIsCalled)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
auto mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
auto entry = this->m_description.CreateInstance();
|
||||
entry.SetNext(mock);
|
||||
@@ -194,14 +194,14 @@ namespace AZ::IO
|
||||
TYPED_TEST_P(StreamStackEntryConformityTests, UpdateStatus_ForwardsCallToNext_NextRecievedCall)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
auto mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
auto entry = this->m_description.CreateInstance();
|
||||
entry.SetNext(mock);
|
||||
|
||||
EXPECT_CALL(*mock, UpdateStatus(_))
|
||||
.Times(1);
|
||||
|
||||
|
||||
StreamStackEntry::Status status;
|
||||
entry.UpdateStatus(status);
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace AZ::IO
|
||||
TYPED_TEST_P(StreamStackEntryConformityTests, UpdateStatus_NextHasSmallerNumSlots_ReturnsSmallestNumSlots)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
if (this->m_description.UsesSlots())
|
||||
{
|
||||
auto mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
@@ -264,7 +264,7 @@ namespace AZ::IO
|
||||
TYPED_TEST_P(StreamStackEntryConformityTests, UpdateStatus_NextHasLargerNumSlots_ReturnsSmallestNumSlots)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
if (this->m_description.UsesSlots())
|
||||
{
|
||||
auto mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
@@ -289,7 +289,7 @@ namespace AZ::IO
|
||||
TYPED_TEST_P(StreamStackEntryConformityTests, UpdateCompletionEstimates_ForwardsCallToNext_NextRecievedCall)
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
|
||||
auto mock = AZStd::make_shared<StreamStackEntryMock>();
|
||||
auto entry = this->m_description.CreateInstance();
|
||||
entry.SetNext(mock);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -167,7 +167,8 @@ namespace UnitTest
|
||||
if (!info.m_streamName.empty())
|
||||
{
|
||||
AZStd::string fullName = GetTestFolderPath() + info.m_streamName;
|
||||
info.m_dataLen = static_cast<size_t>(IO::SystemFile::Length(fullName.c_str()));
|
||||
IO::FileIOBase* io = IO::FileIOBase::GetInstance();
|
||||
io->Size(fullName.c_str(), info.m_dataLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -187,8 +188,11 @@ namespace UnitTest
|
||||
|
||||
if (!info.m_streamName.empty())
|
||||
{
|
||||
IO::FileIOBase* io = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
AZStd::string fullName = GetTestFolderPath() + info.m_streamName;
|
||||
info.m_dataLen = static_cast<size_t>(IO::SystemFile::Length(fullName.c_str()));
|
||||
|
||||
io->Size(fullName.c_str(), info.m_dataLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -69,7 +69,6 @@ set(FILES
|
||||
TickBusTest.cpp
|
||||
UUIDTests.cpp
|
||||
XML.cpp
|
||||
Debug/AssetTracking.cpp
|
||||
Debug/LocalFileEventLoggerTests.cpp
|
||||
Debug/Trace.cpp
|
||||
Debug/UnhandledExceptions.cpp
|
||||
|
||||
Reference in New Issue
Block a user