[SPEC-7644] ParallelDeepAssetReferences is failing intermittently (#5721)

* Fixed race condition caused by trying to handle asset ready event before asset container has finished filling out all the data structures.

Added check to only handle asset ready once init is complete
Added unit test to verify fix

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Re-enable test

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Add missing space to error message

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Add comment on sleep

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Collapse nested namespace

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Collapse nested namespace

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>
This commit is contained in:
amzn-mike
2021-11-18 16:56:26 -06:00
committed by GitHub
parent ae50187fba
commit 56900484fc
4 changed files with 109 additions and 49 deletions
@@ -2282,6 +2282,45 @@ namespace UnitTest
AssetManager::Destroy();
}
struct MockAssetContainer : AssetContainer
{
MockAssetContainer(Asset<AssetData> assetData, const AssetLoadParameters& loadParams)
{
// Copying the code in the original constructor, we can't call that constructor because it will not invoke our virtual method
m_rootAsset = AssetInternal::WeakAsset<AssetData>(assetData);
m_containerAssetId = m_rootAsset.GetId();
AddDependentAssets(assetData, loadParams);
}
protected:
AZStd::vector<AZStd::pair<AssetInfo, Asset<AssetData>>> CreateAndQueueDependentAssets(
const AZStd::vector<AssetInfo>& dependencyInfoList, const AssetLoadParameters& loadParamsCopyWithNoLoadingFilter) override
{
auto result = AssetContainer::CreateAndQueueDependentAssets(dependencyInfoList, loadParamsCopyWithNoLoadingFilter);
// Sleep for a long enough time to allow asset loads to complete and start triggering AssetReady events
// This forces the race condition to occur
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(500));
return result;
}
};
struct MockAssetManager : AssetManager
{
explicit MockAssetManager(const Descriptor& desc)
: AssetManager(desc)
{
}
protected:
AZStd::shared_ptr<AssetContainer> CreateAssetContainer(Asset<AssetData> asset, const AssetLoadParameters& loadParams) const override
{
return AZStd::shared_ptr<AssetContainer>(aznew MockAssetContainer(asset, loadParams));
}
};
void ParallelDeepAssetReferences()
{
SerializeContext context;
@@ -2289,7 +2328,7 @@ namespace UnitTest
AssetWithAssetReference::Reflect(context);
AssetManager::Descriptor desc;
AssetManager::Create(desc);
AssetManager::SetInstance(aznew MockAssetManager(desc));
auto& db = AssetManager::Instance();
@@ -2312,17 +2351,17 @@ namespace UnitTest
// AssetC is MYASSETC
AssetWithAssetReference c;
c.m_asset = AssetManager::Instance().CreateAsset<AssetWithSerializedData>(AssetId(MyAssetDId)); // point at D
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));
// AssetB is MYASSETB
AssetWithAssetReference b;
b.m_asset = AssetManager::Instance().CreateAsset<AssetWithAssetReference>(AssetId(MyAssetCId)); // point at C
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));
// AssetA will be written to disk as MYASSETA
AssetWithAssetReference a;
a.m_asset = AssetManager::Instance().CreateAsset<AssetWithAssetReference>(AssetId(MyAssetBId)); // point at B
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));
}
@@ -2531,7 +2570,7 @@ namespace UnitTest
TEST_F(AssetJobsMultithreadedTest, DISABLED_ParallelDeepAssetReferences)
#else
// temporarily disabled until sporadic failures can be root caused
TEST_F(AssetJobsMultithreadedTest, DISABLED_ParallelDeepAssetReferences)
TEST_F(AssetJobsMultithreadedTest, ParallelDeepAssetReferences)
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
{
ParallelDeepAssetReferences();