Integrating latest 47acbe8

This commit is contained in:
alexpete
2021-03-25 13:57:57 -07:00
parent 448c549698
commit 75dc720198
10312 changed files with 2711566 additions and 671451 deletions
@@ -1600,6 +1600,148 @@ namespace UnitTest
EXPECT_TRUE(test_adl.empty());
}
TEST_F(HashedContainers, UnorderedMapTryEmplace_DoesNotConstruct_OnExistingKey)
{
static int s_tryEmplaceConstructorCallCount;
s_tryEmplaceConstructorCallCount = 0;
struct TryEmplaceConstructorCalls
{
TryEmplaceConstructorCalls()
{
++s_tryEmplaceConstructorCallCount;
}
TryEmplaceConstructorCalls(int value)
: m_value{ value }
{
++s_tryEmplaceConstructorCallCount;
}
TryEmplaceConstructorCalls(const TryEmplaceConstructorCalls&)
{
++s_tryEmplaceConstructorCallCount;
}
int m_value{};
};
using TryEmplaceTestMap = AZStd::unordered_map<int, TryEmplaceConstructorCalls>;
TryEmplaceTestMap testContainer;
// try_emplace move key
AZStd::pair<TryEmplaceTestMap::iterator, bool> emplacePairIter = testContainer.try_emplace(1, 5);
EXPECT_EQ(1, s_tryEmplaceConstructorCallCount);
EXPECT_TRUE(emplacePairIter.second);
EXPECT_EQ(5, emplacePairIter.first->second.m_value);
// try_emplace copy key
int testKey = 3;
emplacePairIter = testContainer.try_emplace(testKey, 72);
EXPECT_EQ(2, s_tryEmplaceConstructorCallCount);
EXPECT_TRUE(emplacePairIter.second);
EXPECT_EQ(72, emplacePairIter.first->second.m_value);
// invoke try_emplace with hint and move key
TryEmplaceTestMap::iterator emplaceIter = testContainer.try_emplace(testContainer.end(), 5, 4092);
EXPECT_EQ(3, s_tryEmplaceConstructorCallCount);
EXPECT_EQ(4092, emplaceIter->second.m_value);
// invoke try_emplace with hint and copy key
testKey = 48;
emplaceIter = testContainer.try_emplace(testContainer.end(), testKey, 824);
EXPECT_EQ(4, s_tryEmplaceConstructorCallCount);
EXPECT_EQ(824, emplaceIter->second.m_value);
// Since the key of '1' exist, nothing should be constructed
emplacePairIter = testContainer.try_emplace(1, -6354);
EXPECT_EQ(4, s_tryEmplaceConstructorCallCount);
EXPECT_FALSE(emplacePairIter.second);
EXPECT_EQ(5, emplacePairIter.first->second.m_value);
}
TEST_F(HashedContainers, UnorderedMapTryEmplace_DoesNotMoveValue_OnExistingKey)
{
AZStd::unordered_map<int, AZStd::unique_ptr<int>> testMap;
auto testPtr = AZStd::make_unique<int>(5);
auto [emplaceIter, inserted] = testMap.try_emplace(1, AZStd::move(testPtr));
EXPECT_TRUE(inserted);
EXPECT_EQ(nullptr, testPtr);
testPtr = AZStd::make_unique<int>(7000);
auto [emplaceIter2, inserted2] = testMap.try_emplace(1, AZStd::move(testPtr));
EXPECT_FALSE(inserted2);
ASSERT_NE(nullptr, testPtr);
EXPECT_EQ(7000, *testPtr);
}
TEST_F(HashedContainers, UnorderedMapInsertOrAssign_PerformsAssignment_OnExistingKey)
{
static int s_tryInsertOrAssignConstructorCalls;
static int s_tryInsertOrAssignAssignmentCalls;
s_tryInsertOrAssignConstructorCalls = 0;
s_tryInsertOrAssignAssignmentCalls = 0;
struct InsertOrAssignInitCalls
{
InsertOrAssignInitCalls()
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls(int value)
: m_value{ value }
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls(const InsertOrAssignInitCalls& other)
: m_value{ other.m_value }
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls& operator=(int value)
{
m_value = value;
++s_tryInsertOrAssignAssignmentCalls;
return *this;
}
int m_value{};
};
using InsertOrAssignTestMap = AZStd::unordered_map<int, InsertOrAssignInitCalls>;
InsertOrAssignTestMap testContainer;
// insert_or_assign move key
AZStd::pair<InsertOrAssignTestMap::iterator, bool> insertOrAssignPairIter = testContainer.insert_or_assign(1, 5);
EXPECT_EQ(1, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_TRUE(insertOrAssignPairIter.second);
EXPECT_EQ(5, insertOrAssignPairIter.first->second.m_value);
// insert_or_assign copy key
int testKey = 3;
insertOrAssignPairIter = testContainer.insert_or_assign(testKey, 72);
EXPECT_EQ(2, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_TRUE(insertOrAssignPairIter.second);
EXPECT_EQ(72, insertOrAssignPairIter.first->second.m_value);
// invoke insert_or_assign with hint and move key
InsertOrAssignTestMap::iterator insertOrAssignIter = testContainer.insert_or_assign(testContainer.end(), 5, 4092);
EXPECT_EQ(3, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_EQ(4092, insertOrAssignIter->second.m_value);
// invoke insert_or_assign with hint and copy key
testKey = 48;
insertOrAssignIter = testContainer.insert_or_assign(testContainer.end(), testKey, 824);
EXPECT_EQ(4, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_EQ(824, insertOrAssignIter->second.m_value);
// Since the key of '1' exist, only an assignment should take place
insertOrAssignPairIter = testContainer.insert_or_assign(1, -6354);
EXPECT_EQ(4, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(1, s_tryInsertOrAssignAssignmentCalls);
EXPECT_FALSE(insertOrAssignPairIter.second);
EXPECT_EQ(-6354, insertOrAssignPairIter.first->second.m_value);
}
template <typename ContainerType>
class HashedMapDifferentAllocatorFixture
: public AllocatorsFixture
+61 -17
View File
@@ -10,14 +10,13 @@
*
*/
#include <AzCore/std/numeric.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/numeric.h>
namespace UnitTest
{
class AccumulateFixture
: public AllocatorsTestFixture
class AccumulateFixture : public AllocatorsTestFixture
{
};
@@ -25,31 +24,76 @@ namespace UnitTest
{
using ::testing::Eq;
AZStd::vector<int> numbers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
AZStd::vector<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const int total = AZStd::accumulate(AZStd::cbegin(numbers), AZStd::cend(numbers), 0);
EXPECT_THAT(total, Eq(55));
}
TEST_F(AccumulateFixture, AccumulateWithBinaryOperator)
{
using ::testing::Eq;
using ::testing::ElementsAre;
using ::testing::Eq;
const AZStd::vector<int> numbers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const AZStd::vector<int> evenNumbers =
AZStd::accumulate(
AZStd::cbegin(numbers), AZStd::cend(numbers), AZStd::vector<int>{},
[](AZStd::vector<int> acc, const int number)
const AZStd::vector<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const AZStd::vector<int> evenNumbers = AZStd::accumulate(
AZStd::cbegin(numbers), AZStd::cend(numbers), AZStd::vector<int>{}, [](AZStd::vector<int> acc, const int number) {
if (number % 2 == 0)
{
if (number % 2 == 0)
{
acc.push_back(number);
}
acc.push_back(number);
}
return acc;
});
return acc;
});
EXPECT_THAT(evenNumbers.size(), Eq(5));
EXPECT_THAT(evenNumbers, ElementsAre(2, 4, 6, 8, 10));
}
class InnerProductFixture : public AllocatorsTestFixture
{
};
TEST_F(InnerProductFixture, InnerProductWithoutBinaryOperator)
{
using ::testing::Eq;
AZStd::vector<int> numbers1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
AZStd::vector<int> numbers2{2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
const int total = AZStd::inner_product(AZStd::cbegin(numbers1), AZStd::cend(numbers1), AZStd::cbegin(numbers2), 0);
EXPECT_THAT(total, Eq(770));
}
TEST_F(InnerProductFixture, InnerProductWithBinaryOperator)
{
using ::testing::ElementsAre;
using ::testing::Eq;
const AZStd::vector<int> number_values{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const AZStd::vector<AZStd::string> number_names{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
struct NumberLabel
{
int m_value;
AZStd::string m_name;
};
const AZStd::vector<NumberLabel> numberLabels = AZStd::inner_product(
AZStd::cbegin(number_values), AZStd::cend(number_values), AZStd::cbegin(number_names), AZStd::vector<NumberLabel>{},
[](AZStd::vector<NumberLabel> acc, const NumberLabel& numberLabel) {
acc.push_back(numberLabel);
return acc;
},
[](const int value, const AZStd::string& label) {
return NumberLabel{value, label};
});
EXPECT_THAT(numberLabels.size(), Eq(10));
for (size_t i = 0; i < numberLabels.size(); ++i)
{
EXPECT_THAT(numberLabels[i].m_value, Eq(number_values[i]));
EXPECT_THAT(numberLabels[i].m_name, Eq(number_names[i]));
}
}
} // namespace UnitTest
@@ -1353,6 +1353,149 @@ namespace UnitTest
EXPECT_EQ(1, uniqueMap.count(4));
}
TEST_F(Tree_Map, MapTryEmplace_DoesNotConstruct_OnExistingKey)
{
static int s_tryEmplaceConstructorCallCount;
s_tryEmplaceConstructorCallCount = 0;
struct TryEmplaceConstructorCalls
{
TryEmplaceConstructorCalls()
{
++s_tryEmplaceConstructorCallCount;
}
TryEmplaceConstructorCalls(int value)
: m_value{ value }
{
++s_tryEmplaceConstructorCallCount;
}
TryEmplaceConstructorCalls(const TryEmplaceConstructorCalls& other)
: m_value{ other.m_value }
{
++s_tryEmplaceConstructorCallCount;
}
int m_value{};
};
using TryEmplaceTestMap = AZStd::map<int, TryEmplaceConstructorCalls>;
TryEmplaceTestMap testContainer;
// try_emplace move key
AZStd::pair<TryEmplaceTestMap::iterator, bool> emplacePairIter = testContainer.try_emplace(1, 5);
EXPECT_EQ(1, s_tryEmplaceConstructorCallCount);
EXPECT_TRUE(emplacePairIter.second);
EXPECT_EQ(5, emplacePairIter.first->second.m_value);
// try_emplace copy key
int testKey = 3;
emplacePairIter = testContainer.try_emplace(testKey, 72);
EXPECT_EQ(2, s_tryEmplaceConstructorCallCount);
EXPECT_TRUE(emplacePairIter.second);
EXPECT_EQ(72, emplacePairIter.first->second.m_value);
// invoke try_emplace with hint and move key
TryEmplaceTestMap::iterator emplaceIter = testContainer.try_emplace(testContainer.end(), 5, 4092);
EXPECT_EQ(3, s_tryEmplaceConstructorCallCount);
EXPECT_EQ(4092, emplaceIter->second.m_value);
// invoke try_emplace with hint and copy key
testKey = 48;
emplaceIter = testContainer.try_emplace(testContainer.end(), testKey, 824);
EXPECT_EQ(4, s_tryEmplaceConstructorCallCount);
EXPECT_EQ(824, emplaceIter->second.m_value);
// Since the key of '1' exist, nothing should be constructed
emplacePairIter = testContainer.try_emplace(1, -6354);
EXPECT_EQ(4, s_tryEmplaceConstructorCallCount);
EXPECT_FALSE(emplacePairIter.second);
EXPECT_EQ(5, emplacePairIter.first->second.m_value);
}
TEST_F(Tree_Map, MapTryEmplace_DoesNotMoveValue_OnExistingKey)
{
AZStd::unordered_map<int, AZStd::unique_ptr<int>> testMap;
auto testPtr = AZStd::make_unique<int>(5);
auto [emplaceIter, inserted] = testMap.try_emplace(1, AZStd::move(testPtr));
EXPECT_TRUE(inserted);
EXPECT_EQ(nullptr, testPtr);
testPtr = AZStd::make_unique<int>(7000);
auto [emplaceIter2, inserted2] = testMap.try_emplace(1, AZStd::move(testPtr));
EXPECT_FALSE(inserted2);
ASSERT_NE(nullptr, testPtr);
EXPECT_EQ(7000, *testPtr);
}
TEST_F(Tree_Map, MapInsertOrAssign_PerformsAssignment_OnExistingKey)
{
static int s_tryInsertOrAssignConstructorCalls;
static int s_tryInsertOrAssignAssignmentCalls;
s_tryInsertOrAssignConstructorCalls = 0;
s_tryInsertOrAssignAssignmentCalls = 0;
struct InsertOrAssignInitCalls
{
InsertOrAssignInitCalls()
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls(int value)
: m_value{ value }
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls(const InsertOrAssignInitCalls& other)
: m_value{ other.m_value }
{
++s_tryInsertOrAssignConstructorCalls;
}
InsertOrAssignInitCalls& operator=(int value)
{
m_value = value;
++s_tryInsertOrAssignAssignmentCalls;
return *this;
}
int m_value{};
};
using InsertOrAssignTestMap = AZStd::map<int, InsertOrAssignInitCalls>;
InsertOrAssignTestMap testContainer;
// insert_or_assign move key
AZStd::pair<InsertOrAssignTestMap::iterator, bool> insertOrAssignPairIter = testContainer.insert_or_assign(1, 5);
EXPECT_EQ(1, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_TRUE(insertOrAssignPairIter.second);
EXPECT_EQ(5, insertOrAssignPairIter.first->second.m_value);
// insert_or_assign copy key
int testKey = 3;
insertOrAssignPairIter = testContainer.insert_or_assign(testKey, 72);
EXPECT_EQ(2, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_TRUE(insertOrAssignPairIter.second);
EXPECT_EQ(72, insertOrAssignPairIter.first->second.m_value);
// invoke insert_or_assign with hint and move key
InsertOrAssignTestMap::iterator insertOrAssignIter = testContainer.insert_or_assign(testContainer.end(), 5, 4092);
EXPECT_EQ(3, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_EQ(4092, insertOrAssignIter->second.m_value);
// invoke insert_or_assign with hint and copy key
testKey = 48;
insertOrAssignIter = testContainer.insert_or_assign(testContainer.end(), testKey, 824);
EXPECT_EQ(4, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(0, s_tryInsertOrAssignAssignmentCalls);
EXPECT_EQ(824, insertOrAssignIter->second.m_value);
// Since the key of '1' exist, only an assignment should take place
insertOrAssignPairIter = testContainer.insert_or_assign(1, -6354);
EXPECT_EQ(4, s_tryInsertOrAssignConstructorCalls);
EXPECT_EQ(1, s_tryInsertOrAssignAssignmentCalls);
EXPECT_FALSE(insertOrAssignPairIter.second);
EXPECT_EQ(-6354, insertOrAssignPairIter.first->second.m_value);
}
template <typename ContainerType>
class TreeMapDifferentAllocatorFixture
: public AllocatorsFixture
@@ -646,7 +646,11 @@ namespace UnitTest
}
};
#if AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS
TEST_F(Parallel_Thread, DISABLED_Test)
#else
TEST_F(Parallel_Thread, Test)
#endif // AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS
{
run();
}
@@ -835,11 +835,11 @@ namespace UnitTest
m_testAssetManager->SetParallelDependentLoadingEnabled(true);
}
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
TEST_F(AssetJobsFloodTest, DISABLED_LoadTest_SameAsset_DifferentFilters)
#else
TEST_F(AssetJobsFloodTest, LoadTest_SameAsset_DifferentFilters)
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
{
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
@@ -1188,11 +1188,11 @@ namespace UnitTest
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
}
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadDependencies_NoLoadNotLoaded)
#else
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadDependencies_NoLoadNotLoaded)
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
{
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
// Setup has already created/destroyed assets
@@ -1229,11 +1229,11 @@ namespace UnitTest
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
}
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadContainerDependencies_LoadAllLoadsNoLoad)
#else
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadContainerDependencies_LoadAllLoadsNoLoad)
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
{
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
// Setup has already created/destroyed assets
@@ -1268,11 +1268,11 @@ namespace UnitTest
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusDisconnect();
}
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
TEST_F(AssetJobsFloodTest, DISABLED_AssetWithNoLoadReference_LoadDependencies_BehaviorObeyed)
#else
TEST_F(AssetJobsFloodTest, AssetWithNoLoadReference_LoadDependencies_BehaviorObeyed)
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_FAILED_ASSET_LOAD_TESTS
{
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
// Setup has already created/destroyed assets
@@ -808,6 +808,13 @@ namespace UnitTest
EXPECT_NE(assets.find(MyAsset1Id), assets.end());
AssetManager::Instance().ResumeAssetRelease();
// Sleep to allow for the assets to release
int retryCount = 100;
while ((--retryCount>0) && assets.size() > 0)
{
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(10));
}
EXPECT_EQ(assets.size(), 0);
}
@@ -517,6 +517,104 @@ namespace UnitTest
AZ_TEST_STOP_TRACE_SUPPRESSION(0);
}
TEST_F(BehaviorContextTestFixture, MethodWhichReturnsAzEvent_WithNoAzBehaviorAzEventDescription_FailsValidation)
{
using TestAzEvent = AZ::Event<float>;
auto TestMethodWhichReturnsAzEvent = [](TestAzEvent& testEvent) -> TestAzEvent&
{
return testEvent;
};
UnitTest::TestRunner::Instance().StartAssertTests();
// Test reflecting function which returns AZ::Event
m_behaviorContext.Method("TestMethodWhichReturnsAzEvent", TestMethodWhichReturnsAzEvent);
int numErrors = UnitTest::TestRunner::Instance().StopAssertTests();
EXPECT_EQ(1, numErrors);
}
TEST_F(BehaviorContextTestFixture, MethodWhichReturnsAzEvent_WithEmptyEventName_FailsValidation)
{
using TestAzEvent = AZ::Event<float>;
auto TestMethodWhichReturnsAzEvent = [](TestAzEvent& testEvent) -> TestAzEvent&
{
return testEvent;
};
// Test reflecting function which returns AZ::Event
AZ::BehaviorAzEventDescription behaviorEventDesc;
// m_eventName member is not set, validation should fail
behaviorEventDesc.m_parameterNames.push_back("Scale");
UnitTest::TestRunner::Instance().StartAssertTests();
m_behaviorContext.Method("TestMethodWhichReturnsAzEvent", TestMethodWhichReturnsAzEvent)
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(behaviorEventDesc));
int numErrors = UnitTest::TestRunner::Instance().StopAssertTests();
EXPECT_EQ(1, numErrors);
}
TEST_F(BehaviorContextTestFixture, MethodWhichReturnsAzEvent_WithParameterNameWhichIsEmpty_FailsValidation)
{
using TestAzEvent = AZ::Event<float>;
auto TestMethodWhichReturnsAzEvent = [](TestAzEvent& testEvent) -> TestAzEvent&
{
return testEvent;
};
// Test reflecting function which returns AZ::Event
AZ::BehaviorAzEventDescription behaviorEventDesc;
behaviorEventDesc.m_eventName = "TestAzEvent";
behaviorEventDesc.m_parameterNames.push_back(""); // Parameter name is empty, validation should fail
UnitTest::TestRunner::Instance().StartAssertTests();
m_behaviorContext.Method("TestMethodWhichReturnsAzEvent", TestMethodWhichReturnsAzEvent)
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(behaviorEventDesc));
int numErrors = UnitTest::TestRunner::Instance().StopAssertTests();
EXPECT_EQ(1, numErrors);
}
TEST_F(BehaviorContextTestFixture, MethodWhichReturnsAzEvent_WithMismatchNumberOfParameters_FailsValidation)
{
using TestAzEvent = AZ::Event<float>;
auto TestMethodWhichReturnsAzEvent = [](TestAzEvent& testEvent) -> TestAzEvent&
{
return testEvent;
};
// Test reflecting function which returns AZ::Event
AZ::BehaviorAzEventDescription behaviorEventDesc;
behaviorEventDesc.m_eventName = "TestAzEvent";
// The AZ Event accepts one parameters.
// Two parameter names are being added here
behaviorEventDesc.m_parameterNames.push_back("Scale");
behaviorEventDesc.m_parameterNames.push_back("Size");
UnitTest::TestRunner::Instance().StartAssertTests();
m_behaviorContext.Method("TestMethodWhichReturnsAzEvent", TestMethodWhichReturnsAzEvent)
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(behaviorEventDesc));
int numErrors = UnitTest::TestRunner::Instance().StopAssertTests();
EXPECT_LE(1, numErrors);
}
TEST_F(BehaviorContextTestFixture, MethodWhichReturnsAzEvent_WithCompleteAzBehaviorAzEventDescriptionription_PassesValidation)
{
using TestAzEvent = AZ::Event<float>;
auto TestMethodWhichReturnsAzEvent = [](TestAzEvent& testEvent) -> TestAzEvent&
{
return testEvent;
};
// Test reflecting function which returns AZ::Event
AZ::BehaviorAzEventDescription behaviorEventDesc;
behaviorEventDesc.m_eventName = "TestAzEvent";
behaviorEventDesc.m_parameterNames.push_back("Scale");
UnitTest::TestRunner::Instance().StartAssertTests();
m_behaviorContext.Method("TestMethodWhichReturnsAzEvent", TestMethodWhichReturnsAzEvent)
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(behaviorEventDesc));
int numErrors = UnitTest::TestRunner::Instance().StopAssertTests();
EXPECT_EQ(0, numErrors);
}
class ClassWithEnumClass
{
public:
@@ -1336,7 +1336,11 @@ namespace UnitTest
size_t m_numThreads;
};
#if AZ_TRAIT_DISABLE_FAILED_FRAMEPROFILER_TEST
TEST_F(FrameProfilerComponentTest, DISABLED_Test)
#else
TEST_F(FrameProfilerComponentTest, Test)
#endif
{
run();
}
@@ -0,0 +1,266 @@
/*
* 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 <limits>
#include <AzCore/Debug/LocalFileEventLogger.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/parallel/atomic.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace AZ::Debug
{
class LocalFileEventLoggerTest
: public UnitTest::AllocatorsFixture
{
public:
inline static constexpr EventNameHash MessageId = EventNameHash("Message");
inline static constexpr const char* LogFileName = "TestLog.azel";
};
TEST_F(LocalFileEventLoggerTest, RecordEvent_SingleString_WrittenToLog)
{
constexpr const char* message = "Hello world";
LocalFileEventLogger realLogger;
AZ::Test::ScopedAutoTempDirectory tempDir;
auto logFilePath = tempDir.Resolve(LogFileName);
auto logger = Interface<IEventLogger>::Get();
ASSERT_NE(logger, nullptr);
realLogger.Start(logFilePath.c_str());
logger->RecordStringEvent(MessageId, message);
realLogger.Stop();
EventLogReader reader;
ASSERT_TRUE(reader.ReadLog(logFilePath.c_str()));
EXPECT_EQ(reader.GetEventName(), PrologEventHash);
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), MessageId);
EXPECT_STREQ(reader.GetString().data(), message);
EXPECT_FALSE(reader.Next());
}
TEST_F(LocalFileEventLoggerTest, RecordEvent_SeveralStrings_WrittenToLog)
{
constexpr const char* messages[] = {
"Hello world",
"And goodbye",
"It has been a long and strange journey"
};
LocalFileEventLogger realLogger;
AZ::Test::ScopedAutoTempDirectory tempDir;
auto logFilePath = tempDir.Resolve(LogFileName);
auto logger = Interface<IEventLogger>::Get();
ASSERT_NE(logger, nullptr);
realLogger.Start(logFilePath.c_str());
for (auto message : messages)
{
logger->RecordStringEvent(MessageId, message);
}
realLogger.Stop();
EventLogReader reader;
ASSERT_TRUE(reader.ReadLog(logFilePath.c_str()));
EXPECT_EQ(reader.GetEventName(), PrologEventHash);
for (auto message : messages)
{
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), MessageId);
EXPECT_STREQ(reader.GetString().data(), message);
}
EXPECT_FALSE(reader.Next());
}
TEST_F(LocalFileEventLoggerTest, RecordEvent_StringsFromMultipleThreads_WrittenToLog)
{
constexpr const char* messages[] = {
"Hello world",
"And goodbye"
};
constexpr size_t totalThreads = 4;
AZ::Test::ScopedAutoTempDirectory tempDir;
LocalFileEventLogger realLogger;
auto logFilePath = tempDir.Resolve(LogFileName);
realLogger.Start(logFilePath.c_str());
AZStd::atomic_bool startLogging = false;
AZStd::thread threads[totalThreads];
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
threads[threadIndex] = AZStd::thread([&startLogging, &messages]()
{
while (!startLogging)
{
AZStd::this_thread::yield();
}
auto logger = Interface<IEventLogger>::Get();
ASSERT_NE(logger, nullptr);
for (auto message : messages)
{
logger->RecordStringEvent(MessageId, message);
}
});
}
startLogging = true;
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
threads[threadIndex].join();
}
realLogger.Stop();
EventLogReader reader;
ASSERT_TRUE(reader.ReadLog(logFilePath.c_str()));
uint64_t threadIds[totalThreads]{ 0 };
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
EXPECT_EQ(reader.GetEventName(), PrologEventHash);
threadIds[threadIndex] = reader.GetThreadId();
for (size_t otherThreadIndex = 0; otherThreadIndex < threadIndex; ++otherThreadIndex)
{
EXPECT_NE(threadIds[threadIndex], threadIds[otherThreadIndex]);
}
for (auto message : messages)
{
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), MessageId);
EXPECT_STREQ(reader.GetString().data(), message);
}
reader.Next();
}
}
TEST_F(LocalFileEventLoggerTest, RecordEvent_BufferGetsWrittenWhenFull_WrittenToLog)
{
constexpr EventNameHash largeBlockId = EventNameHash("Large block");
constexpr size_t largeBlockSizeOffset = 14;
constexpr size_t largeBlockSize = AZStd::numeric_limits<uint16_t>::max() - largeBlockSizeOffset;
struct LargeBlock
{
char m_block[largeBlockSize];
};
constexpr const char* message = "The message after the large block.";
LocalFileEventLogger realLogger;
AZ::Test::ScopedAutoTempDirectory tempDir;
auto logFilePath = tempDir.Resolve(LogFileName);
auto logger = Interface<IEventLogger>::Get();
ASSERT_NE(logger, nullptr);
realLogger.Start(logFilePath.c_str());
LargeBlock& block = logger->RecordEventBegin<LargeBlock>(largeBlockId);
logger->RecordEventEnd();
logger->RecordStringEvent(MessageId, message);
realLogger.Stop();
EventLogReader reader;
ASSERT_TRUE(reader.ReadLog(logFilePath.c_str()));
EXPECT_EQ(reader.GetEventName(), PrologEventHash);
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), largeBlockId);
EXPECT_EQ(reader.GetEventSize(), largeBlockSize);
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), PrologEventHash); // Another prolog as a new cache block started.
ASSERT_TRUE(reader.Next());
EXPECT_EQ(reader.GetEventName(), MessageId);
EXPECT_STREQ(reader.GetString().data(), message);
EXPECT_FALSE(reader.Next());
}
TEST_F(LocalFileEventLoggerTest, Flush_DuringMultipleRecords_FlushDoesNotDeadlock)
{
constexpr size_t totalThreads = 8;
constexpr size_t recordsPerThreadCount = 2000;
constexpr size_t recordsYieldCount = totalThreads * 1000;
constexpr const char* message = "This is a threaded message test.";
LocalFileEventLogger realLogger;
AZ::Test::ScopedAutoTempDirectory tempDir;
auto logFilePath = tempDir.Resolve(LogFileName);
realLogger.Start(logFilePath.c_str());
AZStd::atomic_int totalRecordsWritten = 0;
AZStd::atomic_bool startLogging = false;
AZStd::thread threads[totalThreads];
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
threads[threadIndex] = AZStd::thread([&startLogging, &totalRecordsWritten, &message, recordsPerThreadCount]()
{
while (!startLogging)
{
AZStd::this_thread::yield();
}
auto logger = Interface<IEventLogger>::Get();
ASSERT_NE(logger, nullptr);
for (size_t recordCount = 0; recordCount < recordsPerThreadCount; ++recordCount)
{
logger->RecordStringEvent(MessageId, message);
++totalRecordsWritten;
}
});
}
startLogging = true;
while (totalRecordsWritten < recordsYieldCount)
{
AZStd::this_thread::yield();
}
realLogger.Flush();
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
threads[threadIndex].join();
}
realLogger.Stop();
}
} // namespace AZ::Debug
@@ -496,6 +496,67 @@ namespace SettingsRegistryScriptUtilsTests
AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
}
TEST_P(SettingsRegistryBehaviorContextParamFixture, GetNotifyEvent_AllowsRegistrationOfAzEventHandler_Succeeds)
{
auto&& testParam = GetParam();
bool updateNotifySent{};
// Set the expected value within the SettingsRegistry
auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, setMethodName = testParam.m_setMethodName,
&updateNotifySent](auto&& value)
{
using ValueType = AZStd::remove_cvref_t<decltype(value)>;
const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
// Lookup the SettingsRegistry Proxy GetNotifyEvent
auto foundIt = settingsRegistryInterfaceClass->m_methods.find("GetNotifyEvent");
ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
// Create local settings registry proxy object
AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
// Register a notification call back
AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy::ScriptNotifyEvent::Handler scriptNotifyHandler(
[&updateNotifySent, jsonPath](AZStd::string_view path)
{
if (path == jsonPath)
{
updateNotifySent = true;
}
});
AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy::ScriptNotifyEvent* scriptNotifyEvent{};
EXPECT_TRUE(foundIt->second->InvokeResult(scriptNotifyEvent, &settingsRegistryObject));
ASSERT_NE(nullptr, scriptNotifyEvent);
// connect the scriptNotifyHandler to the settings registry script proxy event
scriptNotifyHandler.Connect(*scriptNotifyEvent);
// Find Reflected SettingsRegistryInterface Set* Method
foundIt = settingsRegistryInterfaceClass->m_methods.find(setMethodName);
ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
// Invoke Set* method
bool setResult{};
EXPECT_TRUE(foundIt->second->InvokeResult(setResult, &settingsRegistryObject, jsonPath, value));
EXPECT_TRUE(setResult);
// Check value set through the BehaviorContext against the Settings Registry instance
// SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
// So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
GetValueType outputValue{};
EXPECT_TRUE(m_registry->Get(outputValue, jsonPath));
EXPECT_EQ(value, outputValue);
};
AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
EXPECT_TRUE(updateNotifySent);
}
INSTANTIATE_TEST_CASE_P(
SettingsRegistryBehaviorContextGetFunctions,
SettingsRegistryBehaviorContextParamFixture,
@@ -73,6 +73,7 @@ set(FILES
UUIDTests.cpp
XML.cpp
Debug/AssetTracking.cpp
Debug/LocalFileEventLoggerTests.cpp
Debug/Trace.cpp
Name/NameJsonSerializerTests.cpp
Name/NameTests.cpp