Merge branch 'development' into cmake/SPEC-7484
This commit is contained in:
@@ -25,3 +25,4 @@ TestResults/**
|
||||
*.swatches
|
||||
/imgui.ini
|
||||
/scripts/project_manager/logs/
|
||||
/AutomatedTesting/Gem/PythonTests/scripting/TestResults
|
||||
|
||||
@@ -57,6 +57,12 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TARGETS Editor
|
||||
VARIANTS Tools)
|
||||
|
||||
# The Material Editor needs the Lyshine "Tools" gem variant for the custom LyShine pass
|
||||
ly_enable_gems(
|
||||
PROJECT_NAME AutomatedTesting GEMS LyShine
|
||||
TARGETS MaterialEditor
|
||||
VARIANTS Tools)
|
||||
|
||||
# The pipeline tools use "Builders" gem variants:
|
||||
ly_enable_gems(
|
||||
PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
|
||||
|
||||
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL TRUE
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_REQUIRES gpu
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE periodic
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
+11
-13
@@ -92,17 +92,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
AZ::AssetProcessor
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.AssetBundler
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_SERIAL
|
||||
TIMEOUT 2400
|
||||
TEST_SUITE periodic
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
AZ::AssetBundlerBatch
|
||||
)
|
||||
# Issue #3017
|
||||
#ly_add_pytest(
|
||||
# NAME AssetPipelineTests.AssetBundler
|
||||
# PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
|
||||
# EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
# TEST_SERIAL
|
||||
# TEST_SUITE periodic
|
||||
# RUNTIME_DEPENDENCIES
|
||||
# AZ::AssetProcessor
|
||||
# AZ::AssetBundlerBatch
|
||||
#)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.AssetBundler_SandBox
|
||||
@@ -111,7 +111,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
PYTEST_MARKS "SUITE_sandbox" # run only sandbox tests in this file
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_SERIAL
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
AZ::AssetBundlerBatch
|
||||
@@ -133,7 +132,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_SERIAL
|
||||
TIMEOUT 1500
|
||||
TEST_SUITE periodic
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessorBatch
|
||||
|
||||
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_main and not REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -28,7 +27,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_periodic and not REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -44,7 +42,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_REQUIRES gpu
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_main and REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -59,7 +56,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_sandbox"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -16,7 +16,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE main
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -33,7 +32,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE sandbox
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_sandbox"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -49,7 +47,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_filter"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -64,7 +61,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_modifier"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -79,7 +75,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_regression"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -94,7 +89,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_area"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -109,7 +103,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_misc"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -124,7 +117,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
|
||||
PYTEST_MARKS "SUITE_periodic and dynveg_surfacetagemitter"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -140,7 +132,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE main
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas
|
||||
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -155,7 +146,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas
|
||||
PYTEST_MARKS "SUITE_periodic"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
@@ -170,7 +160,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SERIAL
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
|
||||
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE periodic
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -38,7 +36,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE sandbox
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE periodic
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
@@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SUITE sandbox
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
|
||||
@@ -18,7 +18,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_smoke"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
AZ::PythonBindingsExample
|
||||
|
||||
@@ -1626,9 +1626,6 @@ bool CCryEditApp::InitInstance()
|
||||
ReflectedVarInit::setupReflection(serializeContext);
|
||||
RegisterReflectedVarHandlers();
|
||||
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
CreateSplashScreen();
|
||||
|
||||
// Register the application's document templates. Document templates
|
||||
|
||||
@@ -449,21 +449,21 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function<void(float)> call
|
||||
|
||||
if (!customPresets.empty())
|
||||
{
|
||||
for (size_t i = 0; i < customPresets.size(); ++i)
|
||||
for (const QString& customPreset : customPresets)
|
||||
{
|
||||
if (customPresets[i].isEmpty())
|
||||
if (customPreset.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
float fov = gSettings.viewports.fDefaultFov;
|
||||
bool ok;
|
||||
float f = customPresets[i].toDouble(&ok);
|
||||
float f = customPreset.toDouble(&ok);
|
||||
if (ok)
|
||||
{
|
||||
fov = std::max(1.0f, f);
|
||||
fov = std::min(120.0f, f);
|
||||
QAction* action = menu->addAction(customPresets[i]);
|
||||
QAction* action = menu->addAction(customPreset);
|
||||
connect(action, &QAction::triggered, action, [fov, callback](){ callback(fov); });
|
||||
}
|
||||
}
|
||||
@@ -535,15 +535,15 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::function<void(int,
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
for (size_t i = 0; i < customPresets.size(); ++i)
|
||||
for (const QString& customPreset : customPresets)
|
||||
{
|
||||
if (customPresets[i].isEmpty())
|
||||
if (customPreset.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
static QRegularExpression regex(QStringLiteral("^(\\d+):(\\d+)$"));
|
||||
QRegularExpressionMatch matches = regex.match(customPresets[i]);
|
||||
QRegularExpressionMatch matches = regex.match(customPreset);
|
||||
if (matches.hasMatch())
|
||||
{
|
||||
bool ok;
|
||||
@@ -551,7 +551,7 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::function<void(int,
|
||||
Q_ASSERT(ok);
|
||||
unsigned int height = matches.captured(2).toInt(&ok);
|
||||
Q_ASSERT(ok);
|
||||
QAction* action = menu->addAction(customPresets[i]);
|
||||
QAction* action = menu->addAction(customPreset);
|
||||
connect(action, &QAction::triggered, action, [width, height, callback]() {callback(width, height); });
|
||||
}
|
||||
}
|
||||
@@ -684,15 +684,15 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::function<void(int,
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
for (size_t i = 0; i < customPresets.size(); ++i)
|
||||
for (const QString& customPreset : customPresets)
|
||||
{
|
||||
if (customPresets[i].isEmpty())
|
||||
if (customPreset.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
static QRegularExpression regex(QStringLiteral("^(\\d+) x (\\d+)$"));
|
||||
QRegularExpressionMatch matches = regex.match(customPresets[i]);
|
||||
QRegularExpressionMatch matches = regex.match(customPreset);
|
||||
if (matches.hasMatch())
|
||||
{
|
||||
bool ok;
|
||||
@@ -700,7 +700,7 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::function<void(int,
|
||||
Q_ASSERT(ok);
|
||||
int height = matches.captured(2).toInt(&ok);
|
||||
Q_ASSERT(ok);
|
||||
QAction* action = menu->addAction(customPresets[i]);
|
||||
QAction* action = menu->addAction(customPreset);
|
||||
connect(action, &QAction::triggered, action, [width, height, callback](){ callback(width, height); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace AZ
|
||||
ScriptPropertyGenericClassArray::Reflect(reflection);
|
||||
|
||||
ScriptPropertyAsset::Reflect(reflection);
|
||||
ScriptPropertyEntityRef::Reflect(reflection);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
@@ -1358,53 +1357,4 @@ namespace AZ
|
||||
m_value = assetProperty->m_value;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// ScriptPropertyEntityRef
|
||||
////////////////////////////
|
||||
void ScriptPropertyEntityRef::Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
|
||||
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AZ::ScriptPropertyEntityRef, AZ::ScriptProperty>()->
|
||||
Version(1)->
|
||||
Field("value", &AZ::ScriptPropertyEntityRef::m_value);
|
||||
}
|
||||
}
|
||||
|
||||
const AZ::Uuid& ScriptPropertyEntityRef::GetDataTypeUuid() const
|
||||
{
|
||||
return AZ::SerializeTypeInfo<AZ::EntityId>::GetUuid();
|
||||
}
|
||||
|
||||
bool ScriptPropertyEntityRef::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
|
||||
{
|
||||
return context.IsRegisteredClass(valueIndex);
|
||||
}
|
||||
|
||||
AZ::ScriptPropertyEntityRef* ScriptPropertyEntityRef::Clone(const char* name) const
|
||||
{
|
||||
AZ::ScriptPropertyEntityRef* clonedValue = aznew AZ::ScriptPropertyEntityRef(name ? name : m_name.c_str());
|
||||
clonedValue->m_value = m_value;
|
||||
return clonedValue;
|
||||
}
|
||||
|
||||
bool ScriptPropertyEntityRef::Write(AZ::ScriptContext& context)
|
||||
{
|
||||
AZ::ScriptValue<AZ::EntityId>::StackPush(context.NativeContext(), m_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptPropertyEntityRef::CloneDataFrom(const AZ::ScriptProperty* scriptProperty)
|
||||
{
|
||||
const AZ::ScriptPropertyEntityRef* entityProperty = azrtti_cast<const AZ::ScriptPropertyEntityRef*>(scriptProperty);
|
||||
|
||||
AZ_Error("ScriptPropertyEntityRef", entityProperty, "Invalid call to CloneData. Types must match before clone attempt is made.\n");
|
||||
if (entityProperty)
|
||||
{
|
||||
m_value = entityProperty->m_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,34 +488,6 @@ namespace AZ
|
||||
protected:
|
||||
void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override;
|
||||
};
|
||||
|
||||
class ScriptPropertyEntityRef
|
||||
: public ScriptProperty
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ScriptPropertyEntityRef, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(AZ::ScriptPropertyEntityRef, "{68EDE6C3-0A89-4C50-A86E-06C058C9F862}", ScriptProperty);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* reflection);
|
||||
|
||||
ScriptPropertyEntityRef() {}
|
||||
ScriptPropertyEntityRef(const char* name)
|
||||
: ScriptProperty(name) {}
|
||||
virtual ~ScriptPropertyEntityRef() = default;
|
||||
const void* GetDataAddress() const override { return &m_value; }
|
||||
const AZ::Uuid& GetDataTypeUuid() const override;
|
||||
|
||||
bool DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const override;
|
||||
|
||||
ScriptPropertyEntityRef* Clone(const char* name = nullptr) const override;
|
||||
|
||||
bool Write(AZ::ScriptContext& context) override;
|
||||
|
||||
AZ::EntityId m_value;
|
||||
|
||||
protected:
|
||||
void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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/Script/ScriptPropertySerializer.h>
|
||||
#include <AzCore/Serialization/DynamicSerializableField.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(ScriptPropertySerializer, SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result ScriptPropertySerializer::Load
|
||||
( void* outputValue
|
||||
, [[maybe_unused]] const Uuid& outputValueTypeId
|
||||
, const rapidjson::Value& inputValue
|
||||
, JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
AZ_Assert(outputValueTypeId == azrtti_typeid<DynamicSerializableField>(), "ScriptPropertySerializer Load against output typeID that was not DynamicSerializableField");
|
||||
AZ_Assert(outputValue, "ScriptPropertySerializer Load against null output");
|
||||
|
||||
auto outputVariable = reinterpret_cast<DynamicSerializableField*>(outputValue);
|
||||
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
|
||||
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
|
||||
if (typeIdMember == inputValue.MemberEnd())
|
||||
{
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("ScriptPropertySerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier));
|
||||
}
|
||||
|
||||
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
|
||||
if (typeId.IsNull())
|
||||
{
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "ScriptPropertySerializer::Load failed to load the AZ TypeId of the value");
|
||||
}
|
||||
|
||||
AZStd::any storage = context.GetSerializeContext()->CreateAny(typeId);
|
||||
if (storage.empty() || storage.type() != typeId)
|
||||
{
|
||||
return context.Report(result, "ScriptPropertySerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed.");
|
||||
}
|
||||
|
||||
DynamicSerializableField storageField;
|
||||
storageField.m_data = AZStd::any_cast<void>(&storage);
|
||||
storageField.m_typeId = typeId;
|
||||
outputVariable->CopyDataFrom(storageField, context.GetSerializeContext());
|
||||
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(outputVariable->m_data, typeId, inputValue, "value", context));
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "ScriptPropertySerializer Load finished loading DynamicSerializableField"
|
||||
: "ScriptPropertySerializer Load failed to load DynamicSerializableField");
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result ScriptPropertySerializer::Store
|
||||
( rapidjson::Value& outputValue
|
||||
, const void* inputValue
|
||||
, const void* defaultValue
|
||||
, [[maybe_unused]] const Uuid& valueTypeId
|
||||
, JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
AZ_Assert(valueTypeId == azrtti_typeid<DynamicSerializableField>(), "DynamicSerializableField Store against value typeID that was not DynamicSerializableField");
|
||||
AZ_Assert(inputValue, "DynamicSerializableField Store against null inputValue pointer ");
|
||||
|
||||
auto inputScriptDataPtr = reinterpret_cast<const DynamicSerializableField*>(inputValue);
|
||||
auto inputFieldPtr = inputScriptDataPtr->m_data;
|
||||
auto defaultScriptDataPtr = reinterpret_cast<const DynamicSerializableField*>(defaultValue);
|
||||
auto defaultFieldPtr = defaultScriptDataPtr ? &defaultScriptDataPtr->m_data : nullptr;
|
||||
|
||||
if (defaultScriptDataPtr && inputScriptDataPtr->IsEqualTo(*defaultScriptDataPtr, context.GetSerializeContext()))
|
||||
{
|
||||
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptPropertySerializer Store used defaults for DynamicSerializableField");
|
||||
}
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||
outputValue.SetObject();
|
||||
|
||||
{
|
||||
rapidjson::Value typeValue;
|
||||
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->m_typeId, context));
|
||||
outputValue.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), AZStd::move(typeValue), context.GetJsonAllocator());
|
||||
}
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", inputFieldPtr, defaultFieldPtr, inputScriptDataPtr->m_typeId, context));
|
||||
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "ScriptPropertySerializer Store finished saving DynamicSerializableField"
|
||||
: "ScriptPropertySerializer Store failed to save DynamicSerializableField");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ScriptPropertySerializer
|
||||
: public BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ScriptPropertySerializer, "{C7BECA49-84EF-45E6-A89D-052D61766197}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
private:
|
||||
JsonSerializationResult::Result Load
|
||||
( void* outputValue
|
||||
, const Uuid& outputValueTypeId
|
||||
, const rapidjson::Value& inputValue
|
||||
, JsonDeserializerContext& context) override;
|
||||
|
||||
JsonSerializationResult::Result Store
|
||||
( rapidjson::Value& outputValue
|
||||
, const void* inputValue
|
||||
, const void* defaultValue
|
||||
, const Uuid& valueTypeId, JsonSerializerContext& context) override;
|
||||
};
|
||||
}
|
||||
@@ -8,10 +8,8 @@
|
||||
|
||||
#if !defined(AZCORE_EXCLUDE_LUA)
|
||||
|
||||
#include <AzCore/Script/ScriptSystemComponent.h>
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
@@ -21,13 +19,16 @@
|
||||
#include <AzCore/Math/MathReflection.h>
|
||||
#include <AzCore/PlatformId/PlatformId.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Script/ScriptAsset.h>
|
||||
#include <AzCore/Script/ScriptContextDebug.h>
|
||||
#include <AzCore/Script/ScriptDebug.h>
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/Script/ScriptPropertySerializer.h>
|
||||
#include <AzCore/Script/ScriptSystemComponent.h>
|
||||
#include <AzCore/Script/lua/lua.h>
|
||||
#include <AzCore/Serialization/DynamicSerializableField.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
@@ -921,6 +922,12 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection)
|
||||
}
|
||||
}
|
||||
|
||||
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(reflection))
|
||||
{
|
||||
jsonContext->Serializer<AZ::ScriptPropertySerializer>()
|
||||
->HandlesType<DynamicSerializableField>();
|
||||
}
|
||||
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(reflection))
|
||||
{
|
||||
// reflect default entity
|
||||
|
||||
@@ -98,14 +98,14 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other)
|
||||
void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext)
|
||||
{
|
||||
DestroyData();
|
||||
m_typeId = other.m_typeId;
|
||||
m_data = other.CloneData();
|
||||
m_data = other.CloneData(useContext);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext)
|
||||
bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext) const
|
||||
{
|
||||
if (other.m_typeId != m_typeId)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#define AZCORE_DYNAMIC_SERIALIZABLE_FIELD_H
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -24,6 +26,7 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(DynamicSerializableField, "{D761E0C2-A098-497C-B8EB-EA62F5ED896B}")
|
||||
AZ_CLASS_ALLOCATOR(DynamicSerializableField, AZ::SystemAllocator, 0);
|
||||
|
||||
DynamicSerializableField();
|
||||
DynamicSerializableField(const DynamicSerializableField& serializableField);
|
||||
@@ -33,8 +36,8 @@ namespace AZ
|
||||
void DestroyData(SerializeContext* useContext = nullptr);
|
||||
void* CloneData(SerializeContext* useContext = nullptr) const;
|
||||
|
||||
void CopyDataFrom(const DynamicSerializableField& other);
|
||||
bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr);
|
||||
void CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext = nullptr);
|
||||
bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr) const;
|
||||
|
||||
template<class T>
|
||||
void Set(T* object)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/Slice/SliceAsset.h>
|
||||
#include <AzCore/Serialization/DataPatch.h>
|
||||
#include <AzCore/Serialization/DynamicSerializableField.h>
|
||||
#include <AzCore/Serialization/IdUtils.h>
|
||||
|
||||
namespace AZ
|
||||
|
||||
@@ -462,6 +462,8 @@ set(FILES
|
||||
Script/ScriptTimePoint.h
|
||||
Script/ScriptProperty.h
|
||||
Script/ScriptProperty.cpp
|
||||
Script/ScriptPropertySerializer.h
|
||||
Script/ScriptPropertySerializer.cpp
|
||||
Script/ScriptPropertyTable.h
|
||||
Script/ScriptPropertyTable.cpp
|
||||
Script/ScriptPropertyWatcherBus.h
|
||||
|
||||
@@ -22,8 +22,6 @@ namespace AzQtComponents
|
||||
QApplication::setApplicationName("O3DE Tools Application");
|
||||
|
||||
AzQtComponents::PrepareQtPaths();
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
}
|
||||
|
||||
void AzQtApplication::InitializeDpiScaling()
|
||||
|
||||
@@ -129,8 +129,6 @@ int main(int argc, char **argv)
|
||||
QApplication::setOrganizationDomain("o3de.org");
|
||||
QApplication::setApplicationName("O3DEWidgetGallery");
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
|
||||
+52
-12
@@ -13,54 +13,94 @@
|
||||
|
||||
TEST(AzQtComponents, FloatToString_Truncate2Decimals)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
const int numDecimalPlaces = 2;
|
||||
EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator), "0.12");
|
||||
EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocale, showThousandsSeparator), "0.12");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_AllZerosButOne)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
int numDecimalPlaces = 2;
|
||||
EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator), "1.0");
|
||||
EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocale, showThousandsSeparator), "1.0");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateAllZerosButOne)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
int numDecimalPlaces = 2;
|
||||
EXPECT_EQ(AzQtComponents::toString(1.0001, numDecimalPlaces, testLocal, showThousandsSeparator), "1.0");
|
||||
EXPECT_EQ(AzQtComponents::toString(1.0001, numDecimalPlaces, testLocale, showThousandsSeparator), "1.0");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateNotRound)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
int numDecimalPlaces = 3;
|
||||
EXPECT_EQ(AzQtComponents::toString(0.1236, numDecimalPlaces, testLocal, showThousandsSeparator), "0.123");
|
||||
EXPECT_EQ(AzQtComponents::toString(0.1236, numDecimalPlaces, testLocale, showThousandsSeparator), "0.123");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRound)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = true;
|
||||
int numDecimalPlaces = 3;
|
||||
EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator), "1,000.123");
|
||||
EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocale, showThousandsSeparator), "1,000.123");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimal)
|
||||
{
|
||||
QLocale testLocal(QLocale::English, QLocale::UnitedStates);
|
||||
QLocale testLocale(QLocale::English, QLocale::UnitedStates);
|
||||
|
||||
const bool showThousandsSeparator = true;
|
||||
int numDecimalPlaces = 2;
|
||||
EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator), "1,000.0");
|
||||
EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocale, showThousandsSeparator), "1,000.0");
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_Truncate2DecimalsWithLocale)
|
||||
{
|
||||
QLocale testLocale{ QLocale() };
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
const int numDecimalPlaces = 2;
|
||||
QString testString = "0" + QString(testLocale.decimalPoint()) + "12";
|
||||
EXPECT_EQ(testString, AzQtComponents::toString(0.1234, numDecimalPlaces, testLocale, showThousandsSeparator));
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_AllZerosButOneWithLocale)
|
||||
{
|
||||
QLocale testLocale{ QLocale() };
|
||||
|
||||
const bool showThousandsSeparator = false;
|
||||
const int numDecimalPlaces = 2;
|
||||
QString testString = "1" + QString(testLocale.decimalPoint()) + "0";
|
||||
EXPECT_EQ(testString, AzQtComponents::toString(1.0000, numDecimalPlaces, testLocale, showThousandsSeparator));
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRoundWithLocale)
|
||||
{
|
||||
QLocale testLocale{ QLocale() };
|
||||
|
||||
const bool showThousandsSeparator = true;
|
||||
const int numDecimalPlaces = 3;
|
||||
QString testString = "1" + QString(testLocale.groupSeparator()) + "000" + QString(testLocale.decimalPoint()) + "123";
|
||||
EXPECT_EQ(testString, AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocale, showThousandsSeparator));
|
||||
}
|
||||
|
||||
TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimalWithLocale)
|
||||
{
|
||||
QLocale testLocale{ QLocale() };
|
||||
|
||||
const bool showThousandsSeparator = true;
|
||||
int numDecimalPlaces = 2;
|
||||
QString testString = "1" + QString(testLocale.groupSeparator()) + "000" + QString(testLocale.decimalPoint()) + "0";
|
||||
EXPECT_EQ(testString, AzQtComponents::toString(1000.000, numDecimalPlaces, testLocale, showThousandsSeparator));
|
||||
}
|
||||
|
||||
-10
@@ -1107,17 +1107,7 @@ namespace AzToolsFramework
|
||||
ElementAttribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
|
||||
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
|
||||
|
||||
ec->Class<AZ::ScriptPropertyAsset>("Script Property Asset(asset)", "A script asset property")->
|
||||
ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorAsset's class attributes.")->
|
||||
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
|
||||
DataElement("Asset", &AZ::ScriptPropertyAsset::m_value, "m_value", "An object")->
|
||||
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
|
||||
|
||||
ec->Class<AZ::ScriptPropertyEntityRef>("Script Property Entity(EntityRef)", "A script entity reference property")->
|
||||
ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorEntityRef's class attributes.")->
|
||||
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
|
||||
DataElement("EntityRef", &AZ::ScriptPropertyEntityRef::m_value, "m_entity", "An entity reference")->
|
||||
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Benchmark
|
||||
|
||||
void BM_Prefab::CreateEntities(const unsigned int entityCount, AZStd::vector<AZ::Entity*>& entities)
|
||||
{
|
||||
for (int entityIndex = 0; entityIndex < entityCount; ++entityIndex)
|
||||
for (unsigned int entityIndex = 0; entityIndex < entityCount; ++entityIndex)
|
||||
{
|
||||
AZStd::string entityName = "TestEntity";
|
||||
entityName = entityName + AZStd::to_string(entityIndex);
|
||||
@@ -101,7 +101,7 @@ namespace Benchmark
|
||||
void BM_Prefab::CreateFakePaths(const unsigned int pathCount)
|
||||
{
|
||||
//setup fake paths
|
||||
for (int number = 0; number < pathCount; ++number)
|
||||
for (unsigned int number = 0; number < pathCount; ++number)
|
||||
{
|
||||
AZStd::string path = m_pathString;
|
||||
m_paths.push_back(path + AZStd::to_string(number) + "_" + AZStd::to_string(pathCount));
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Benchmark
|
||||
|
||||
state.ResumeTiming();
|
||||
|
||||
for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
{
|
||||
newInstances.push_back(m_prefabSystemComponent->CreatePrefab(
|
||||
{ entities[instanceCounter] },
|
||||
@@ -110,7 +110,7 @@ namespace Benchmark
|
||||
AZStd::vector<AZStd::unique_ptr<Instance>> testInstances;
|
||||
testInstances.resize(numInstancesToAdd);
|
||||
|
||||
for (int instanceCounter = 0; instanceCounter < numInstancesToAdd; ++instanceCounter)
|
||||
for (unsigned int instanceCounter = 0; instanceCounter < numInstancesToAdd; ++instanceCounter)
|
||||
{
|
||||
testInstances[instanceCounter] = (m_prefabSystemComponent->CreatePrefab(
|
||||
{ entities[instanceCounter] }
|
||||
@@ -161,7 +161,7 @@ namespace Benchmark
|
||||
|
||||
state.ResumeTiming();
|
||||
|
||||
for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
{
|
||||
nestedInstanceRoot = m_prefabSystemComponent->CreatePrefab(
|
||||
{},
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ namespace Benchmark
|
||||
|
||||
state.ResumeTiming();
|
||||
|
||||
for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter)
|
||||
{
|
||||
newInstances[instanceCounter] = m_prefabSystemComponent->InstantiatePrefab(templateToInstantiateId);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Benchmark
|
||||
|
||||
state.ResumeTiming();
|
||||
|
||||
for (int templateCounter = 0; templateCounter < numTemplates; ++templateCounter)
|
||||
for (unsigned int templateCounter = 0; templateCounter < numTemplates; ++templateCounter)
|
||||
{
|
||||
m_prefabLoaderInterface->LoadTemplateFromFile(m_paths[templateCounter]);
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ namespace Benchmark
|
||||
AZStd::vector<AZStd::unique_ptr<AzFramework::Spawnable>> spawnables;
|
||||
spawnables.reserve(numSpawnables);
|
||||
|
||||
for (int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter)
|
||||
for (unsigned int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter)
|
||||
{
|
||||
AZStd::unique_ptr<AzFramework::Spawnable> spawnable = AZStd::make_unique<AzFramework::Spawnable>();
|
||||
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom);
|
||||
|
||||
@@ -245,12 +245,15 @@ namespace UnitTest
|
||||
{
|
||||
using testing::StrEq;
|
||||
|
||||
QLocale testLocale{ QLocale() };
|
||||
QString testString = "10" + QString(testLocale.decimalPoint()) + "0";
|
||||
|
||||
m_doubleSpinBox->setSuffix("m");
|
||||
m_doubleSpinBox->setValue(10.0);
|
||||
|
||||
// test internal logic (textFromValue() calls private StringValue())
|
||||
QString value = m_doubleSpinBox->textFromValue(10.0);
|
||||
EXPECT_THAT(value.toUtf8().constData(), StrEq("10.0"));
|
||||
EXPECT_THAT(value.toUtf8().constData(), testString);
|
||||
|
||||
m_doubleSpinBox->setFocus();
|
||||
EXPECT_THAT(m_doubleSpinBox->suffix().toUtf8().constData(), StrEq(""));
|
||||
@@ -293,31 +296,44 @@ namespace UnitTest
|
||||
|
||||
TEST_F(SpinBoxFixture, SpinBoxCheckHighValueTruncatesCorrectly)
|
||||
{
|
||||
QString value = setupTruncationTest("0.9999999");
|
||||
QLocale testLocale{ QLocale() };
|
||||
QString testString = "0" + QString(testLocale.decimalPoint()) + "9999999";
|
||||
QString value = setupTruncationTest(testString);
|
||||
|
||||
EXPECT_TRUE(value == "0.999");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "999";
|
||||
EXPECT_TRUE(value == testString);
|
||||
}
|
||||
|
||||
TEST_F(SpinBoxFixture, SpinBoxCheckLowValueTruncatesCorrectly)
|
||||
{
|
||||
QString value = setupTruncationTest("0.0000001");
|
||||
QLocale testLocale{ QLocale() };
|
||||
QString testString = "0" + QString(testLocale.decimalPoint()) + "0000001";
|
||||
QString value = setupTruncationTest(testString);
|
||||
|
||||
EXPECT_TRUE(value == "0.0");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "0";
|
||||
EXPECT_TRUE(value == testString);
|
||||
}
|
||||
|
||||
TEST_F(SpinBoxFixture, SpinBoxCheckBugValuesTruncatesCorrectly)
|
||||
{
|
||||
QString value = setupTruncationTest("0.12395");
|
||||
QLocale testLocale{ QLocale() };
|
||||
QString testString = "0" + QString(testLocale.decimalPoint()) + "12395";
|
||||
QString value = setupTruncationTest(testString);
|
||||
|
||||
EXPECT_TRUE(value == "0.123");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "123";
|
||||
EXPECT_TRUE(value == testString);
|
||||
|
||||
value = setupTruncationTest("0.94496");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "94496";
|
||||
value = setupTruncationTest(testString);
|
||||
|
||||
EXPECT_TRUE(value == "0.944");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "944";
|
||||
EXPECT_TRUE(value == testString);
|
||||
|
||||
value = setupTruncationTest("0.0009999");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "0009999";
|
||||
value = setupTruncationTest(testString);
|
||||
|
||||
EXPECT_TRUE(value == "0.0");
|
||||
testString = "0" + QString(testLocale.decimalPoint()) + "0";
|
||||
EXPECT_TRUE(value == testString);
|
||||
}
|
||||
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -393,7 +393,7 @@ void CSystem::debug_GetCallStack(const char** pFunctions, int& nCount)
|
||||
unsigned int numFrames = StackRecorder::Record(frames, nMaxCount, 1);
|
||||
SymbolStorage::StackLine* textLines = (SymbolStorage::StackLine*)AZ_ALLOCA(sizeof(SymbolStorage::StackLine)*nMaxCount);
|
||||
SymbolStorage::DecodeFrames(frames, numFrames, textLines);
|
||||
for (int i = 0; i < numFrames; i++)
|
||||
for (unsigned int i = 0; i < numFrames; i++)
|
||||
{
|
||||
pFunctions[i] = textLines[i];
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ namespace O3DE::ProjectManager
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace AZ
|
||||
AZStd::string AssImpMaterialWrapper::GetTextureFileName(MaterialMapType textureType) const
|
||||
{
|
||||
/// Engine currently doesn't support multiple textures. Right now we only use first texture.
|
||||
int textureIndex = 0;
|
||||
unsigned int textureIndex = 0;
|
||||
aiString absTexturePath;
|
||||
switch (textureType)
|
||||
{
|
||||
|
||||
@@ -445,11 +445,11 @@ namespace AZ
|
||||
|
||||
AZStd::unordered_set<AZStd::string> boneList;
|
||||
|
||||
for (int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
for (int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
{
|
||||
aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
@@ -612,10 +612,10 @@ namespace AZ
|
||||
ValueToKeyDataMap valueToKeyDataMap;
|
||||
// Key time can be less than zero, normalize to have zero be the lowest time.
|
||||
double keyOffset = 0;
|
||||
for (int keyIdx = 0; keyIdx < meshMorphAnim->mNumKeys; keyIdx++)
|
||||
for (unsigned int keyIdx = 0; keyIdx < meshMorphAnim->mNumKeys; keyIdx++)
|
||||
{
|
||||
aiMeshMorphKey& key = meshMorphAnim->mKeys[keyIdx];
|
||||
for (int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx)
|
||||
for (unsigned int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx)
|
||||
{
|
||||
int currentValue = key.mValues[valIdx];
|
||||
KeyData thisKey(key.mWeights[valIdx], key.mTime);
|
||||
|
||||
@@ -89,11 +89,11 @@ namespace AZ
|
||||
|
||||
bitangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
|
||||
bitangentStream->ReserveContainerSpace(vertexCount);
|
||||
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
for (unsigned int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
if (!mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace AZ
|
||||
{
|
||||
int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[nodeMeshIdx];
|
||||
const aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[sceneMeshIdx];
|
||||
for (int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++)
|
||||
for (unsigned int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++)
|
||||
{
|
||||
aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[animIdx];
|
||||
animToMeshToAnimMeshIndices[aiAnimMesh->mName.C_Str()].emplace_back(nodeMeshIdx, animIdx);
|
||||
@@ -130,7 +130,7 @@ namespace AZ
|
||||
blendShapeData->ReserveData(
|
||||
aiAnimMesh->mNumVertices, aiAnimMesh->HasTangentsAndBitangents(), uvSetUsedFlags, colorSetUsedFlags);
|
||||
|
||||
for (int vertIdx = 0; vertIdx < aiAnimMesh->mNumVertices; ++vertIdx)
|
||||
for (unsigned int vertIdx = 0; vertIdx < aiAnimMesh->mNumVertices; ++vertIdx)
|
||||
{
|
||||
AZ::Vector3 vertex(AssImpSDKWrapper::AssImpTypeConverter::ToVector3(aiAnimMesh->mVertices[vertIdx]));
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// aiAnimMesh just has a list of positions for vertices. The face indices are on the original mesh.
|
||||
for (int faceIdx = 0; faceIdx < aiMesh->mNumFaces; ++faceIdx)
|
||||
for (unsigned int faceIdx = 0; faceIdx < aiMesh->mNumFaces; ++faceIdx)
|
||||
{
|
||||
aiFace face = aiMesh->mFaces[faceIdx];
|
||||
DataTypes::IBlendShapeData::Face blendFace;
|
||||
@@ -199,7 +199,7 @@ namespace AZ
|
||||
face.mNumIndices);
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
for (unsigned int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
{
|
||||
blendFace.vertexIndex[idx] = face.mIndices[idx] + vertexOffset;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace AZ
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
// This node has at least one mesh, verify that the color channel counts are the same for all meshes.
|
||||
const int expectedColorChannels = scene->mMeshes[currentNode->mMeshes[0]]->GetNumColorChannels();
|
||||
const unsigned int expectedColorChannels = scene->mMeshes[currentNode->mMeshes[0]]->GetNumColorChannels();
|
||||
const bool allMeshesHaveSameNumberOfColorChannels =
|
||||
AZStd::all_of(currentNode->mMeshes + 1, currentNode->mMeshes + currentNode->mNumMeshes, [scene, expectedColorChannels](const unsigned int meshIndex)
|
||||
{
|
||||
@@ -80,17 +80,16 @@ namespace AZ
|
||||
const uint64_t vertexCount = GetVertexCountForAllMeshesOnNode(*currentNode, *scene);
|
||||
|
||||
Events::ProcessingResultCombiner combinedVertexColorResults;
|
||||
for (int colorSetIndex = 0; colorSetIndex < expectedColorChannels; ++colorSetIndex)
|
||||
for (unsigned int colorSetIndex = 0; colorSetIndex < expectedColorChannels; ++colorSetIndex)
|
||||
{
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshVertexColorData> vertexColors =
|
||||
AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexColorData>();
|
||||
vertexColors->ReserveContainerSpace(vertexCount);
|
||||
|
||||
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
for (unsigned int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
if (colorSetIndex < mesh->GetNumColorChannels())
|
||||
{
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace AZ
|
||||
nodesWithNoMesh.emplace(currentNode->mName.C_Str());
|
||||
}
|
||||
|
||||
for (int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex)
|
||||
for (unsigned int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex)
|
||||
{
|
||||
queue.push(currentNode->mChildren[childIndex]);
|
||||
}
|
||||
@@ -171,7 +171,7 @@ namespace AZ
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int childIndex = 0; childIndex < node->mNumChildren; ++childIndex)
|
||||
for (unsigned int childIndex = 0; childIndex < node->mNumChildren; ++childIndex)
|
||||
{
|
||||
const aiNode* childNode = node->mChildren[childIndex];
|
||||
if (RecursiveHasChildBone(childNode, boneByNameMap))
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace AZ
|
||||
Events::ProcessingResultCombiner combinedMaterialImportResults;
|
||||
|
||||
AZStd::unordered_map<int, AZStd::shared_ptr<SceneData::GraphData::MaterialData>> materialMap;
|
||||
for (int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx)
|
||||
for (unsigned int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx)
|
||||
{
|
||||
int meshIndex = context.m_sourceNode.m_assImpNode->mMeshes[idx];
|
||||
const aiMesh* assImpMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshIndex];
|
||||
|
||||
@@ -91,11 +91,11 @@ namespace AZ
|
||||
|
||||
tangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
|
||||
tangentStream->ReserveContainerSpace(vertexCount);
|
||||
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
for (unsigned int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
if (!mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
// so they can be separated by engine code instead.
|
||||
bool foundTextureCoordinates = false;
|
||||
AZStd::array<int, AI_MAX_NUMBER_OF_TEXTURECOORDS> meshesPerTextureCoordinateIndex = {};
|
||||
for (int localMeshIndex = 0; localMeshIndex < currentNode->mNumMeshes; ++localMeshIndex)
|
||||
for (unsigned int localMeshIndex = 0; localMeshIndex < currentNode->mNumMeshes; ++localMeshIndex)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[localMeshIndex]];
|
||||
for (int texCoordIndex = 0; texCoordIndex < meshesPerTextureCoordinateIndex.size(); ++texCoordIndex)
|
||||
@@ -110,7 +110,7 @@ namespace AZ
|
||||
uvMap->ReserveContainerSpace(vertexCount);
|
||||
bool customNameFound = false;
|
||||
AZStd::string name(AZStd::string::format("%s%d", m_defaultNodeName, texCoordIndex));
|
||||
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
if(mesh->mTextureCoords[texCoordIndex])
|
||||
@@ -136,7 +136,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
for (unsigned int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
if (mesh->mTextureCoords[texCoordIndex])
|
||||
{
|
||||
|
||||
+4
-4
@@ -40,7 +40,7 @@ namespace AZ::SceneAPI::SceneBuilder
|
||||
// This code re-combines them to match previous FBX SDK behavior,
|
||||
// so they can be separated by engine code instead.
|
||||
int vertOffset = 0;
|
||||
for (int m = 0; m < currentNode->mNumMeshes; ++m)
|
||||
for (unsigned int m = 0; m < currentNode->mNumMeshes; ++m)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]];
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace AZ::SceneAPI::SceneBuilder
|
||||
assImpMatIndexToLYIndex.insert(AZStd::pair<int, int>(mesh->mMaterialIndex, lyMeshIndex++));
|
||||
}
|
||||
|
||||
for (int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx)
|
||||
for (unsigned int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx)
|
||||
{
|
||||
AZ::Vector3 vertex(mesh->mVertices[vertIdx].x, mesh->mVertices[vertIdx].y, mesh->mVertices[vertIdx].z);
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace AZ::SceneAPI::SceneBuilder
|
||||
}
|
||||
}
|
||||
|
||||
for (int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx)
|
||||
for (unsigned int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx)
|
||||
{
|
||||
aiFace face = mesh->mFaces[faceIdx];
|
||||
AZ::SceneAPI::DataTypes::IMeshData::Face meshFace;
|
||||
@@ -82,7 +82,7 @@ namespace AZ::SceneAPI::SceneBuilder
|
||||
face.mNumIndices);
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
for (unsigned int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
{
|
||||
meshFace.vertexIndex[idx] = face.mIndices[idx] + vertOffset;
|
||||
}
|
||||
|
||||
+42
-14
@@ -6,6 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <TestImpactCommandLineOptions.h>
|
||||
#include <TestImpactCommandLineOptionsUtils.h>
|
||||
|
||||
@@ -19,8 +21,9 @@ namespace TestImpact
|
||||
{
|
||||
// Options
|
||||
ConfigKey,
|
||||
DataFileKey,
|
||||
ChangeListKey,
|
||||
OutputChangeListKey,
|
||||
SequenceReportKey,
|
||||
SequenceKey,
|
||||
TestPrioritizationPolicyKey,
|
||||
ExecutionFailurePolicyKey,
|
||||
@@ -55,8 +58,9 @@ namespace TestImpact
|
||||
{
|
||||
// Options
|
||||
"config",
|
||||
"datafile",
|
||||
"changelist",
|
||||
"ochangelist",
|
||||
"report",
|
||||
"sequence",
|
||||
"ppolicy",
|
||||
"epolicy",
|
||||
@@ -92,14 +96,19 @@ namespace TestImpact
|
||||
return ParsePathOption(OptionKeys[ConfigKey], cmd).value_or(LY_TEST_IMPACT_DEFAULT_CONFIG_FILE);
|
||||
}
|
||||
|
||||
AZStd::optional<RepoPath> ParseDataFile(const AZ::CommandLine& cmd)
|
||||
{
|
||||
return ParsePathOption(OptionKeys[DataFileKey], cmd);
|
||||
}
|
||||
|
||||
AZStd::optional<RepoPath> ParseChangeListFile(const AZ::CommandLine& cmd)
|
||||
{
|
||||
return ParsePathOption(OptionKeys[ChangeListKey], cmd);
|
||||
}
|
||||
|
||||
bool ParseOutputChangeList(const AZ::CommandLine& cmd)
|
||||
AZStd::optional<RepoPath> ParseSequenceReportFile(const AZ::CommandLine& cmd)
|
||||
{
|
||||
return ParseOnOffOption(OptionKeys[OutputChangeListKey], BinaryStateValue<bool>{ false, true }, cmd).value_or(false);
|
||||
return ParsePathOption(OptionKeys[SequenceReportKey], cmd);
|
||||
}
|
||||
|
||||
TestSequenceType ParseTestSequenceType(const AZ::CommandLine& cmd)
|
||||
@@ -255,9 +264,9 @@ namespace TestImpact
|
||||
{
|
||||
const AZStd::vector<AZStd::pair<AZStd::string, SuiteType>> states =
|
||||
{
|
||||
{GetSuiteTypeName(SuiteType::Main), SuiteType::Main},
|
||||
{GetSuiteTypeName(SuiteType::Periodic), SuiteType::Periodic},
|
||||
{GetSuiteTypeName(SuiteType::Sandbox), SuiteType::Sandbox}
|
||||
{ SuiteTypeAsString(SuiteType::Main), SuiteType::Main },
|
||||
{ SuiteTypeAsString(SuiteType::Periodic), SuiteType::Periodic },
|
||||
{ SuiteTypeAsString(SuiteType::Sandbox), SuiteType::Sandbox }
|
||||
};
|
||||
|
||||
return ParseMultiStateOption(OptionKeys[SuiteFilterKey], states, cmd).value_or(SuiteType::Main);
|
||||
@@ -270,8 +279,9 @@ namespace TestImpact
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
m_configurationFile = ParseConfigurationFile(cmd);
|
||||
m_dataFile = ParseDataFile(cmd);
|
||||
m_changeListFile = ParseChangeListFile(cmd);
|
||||
m_outputChangeList = ParseOutputChangeList(cmd);
|
||||
m_sequenceReportFile = ParseSequenceReportFile(cmd);
|
||||
m_testSequenceType = ParseTestSequenceType(cmd);
|
||||
m_testPrioritizationPolicy = ParseTestPrioritizationPolicy(cmd);
|
||||
m_executionFailurePolicy = ParseExecutionFailurePolicy(cmd);
|
||||
@@ -286,28 +296,43 @@ namespace TestImpact
|
||||
m_safeMode = ParseSafeMode(cmd);
|
||||
m_suiteFilter = ParseSuiteFilter(cmd);
|
||||
}
|
||||
|
||||
bool CommandLineOptions::HasDataFilePath() const
|
||||
{
|
||||
return m_dataFile.has_value();
|
||||
}
|
||||
|
||||
bool CommandLineOptions::HasChangeListFile() const
|
||||
bool CommandLineOptions::HasChangeListFilePath() const
|
||||
{
|
||||
return m_changeListFile.has_value();
|
||||
}
|
||||
|
||||
bool CommandLineOptions::HasSequenceReportFilePath() const
|
||||
{
|
||||
return m_sequenceReportFile.has_value();
|
||||
}
|
||||
|
||||
bool CommandLineOptions::HasSafeMode() const
|
||||
{
|
||||
return m_safeMode;
|
||||
}
|
||||
|
||||
const AZStd::optional<RepoPath>& CommandLineOptions::GetChangeListFile() const
|
||||
const AZStd::optional<RepoPath>& CommandLineOptions::GetDataFilePath() const
|
||||
{
|
||||
return m_dataFile;
|
||||
}
|
||||
|
||||
const AZStd::optional<RepoPath>& CommandLineOptions::GetChangeListFilePath() const
|
||||
{
|
||||
return m_changeListFile;
|
||||
}
|
||||
|
||||
bool CommandLineOptions::HasOutputChangeList() const
|
||||
const AZStd::optional<RepoPath>& CommandLineOptions::GetSequenceReportFilePath() const
|
||||
{
|
||||
return m_outputChangeList;
|
||||
return m_sequenceReportFile;
|
||||
}
|
||||
|
||||
const RepoPath& CommandLineOptions::GetConfigurationFile() const
|
||||
const RepoPath& CommandLineOptions::GetConfigurationFilePath() const
|
||||
{
|
||||
return m_configurationFile;
|
||||
}
|
||||
@@ -379,8 +404,12 @@ namespace TestImpact
|
||||
" options:\n"
|
||||
" -config=<filename> Path to the configuration file for the TIAF runtime (default: \n"
|
||||
" <tiaf binay build dir>.<tiaf binary build type>.json).\n"
|
||||
" -datafile=<filename> Optional path to a test impact data file that will used instead of that\n"
|
||||
" specified in the config file.\n"
|
||||
" -changelist=<filename> Path to the JSON of source file changes to perform test impact \n"
|
||||
" analysis on.\n"
|
||||
" -report=<filename> Path to where the sequence report file will be written (if this option \n"
|
||||
" is not specified, no report will be written).\n"
|
||||
" -gtimeout=<seconds> Global timeout value to terminate the entire test sequence should it \n"
|
||||
" be exceeded.\n"
|
||||
" -ttimeout=<seconds> Timeout value to terminate individual test targets should it be \n"
|
||||
@@ -443,7 +472,6 @@ namespace TestImpact
|
||||
" available, no prioritization will occur).\n"
|
||||
" -maxconcurrency=<number> The maximum number of concurrent test targets/shards to be in flight at \n"
|
||||
" any given moment.\n"
|
||||
" -ochangelist=<on,off> Outputs the change list used for test selection.\n"
|
||||
" -suite=<main, periodic, sandbox> The test suite to select from for this test sequence.";
|
||||
|
||||
return help;
|
||||
|
||||
+17
-7
@@ -36,20 +36,29 @@ namespace TestImpact
|
||||
CommandLineOptions(int argc, char** argv);
|
||||
static AZStd::string GetCommandLineUsageString();
|
||||
|
||||
//! Returns true if a test impact data file path has been supplied, otherwise false.
|
||||
bool HasDataFilePath() const;
|
||||
|
||||
//! Returns true if a change list file path has been supplied, otherwise false.
|
||||
bool HasChangeListFile() const;
|
||||
bool HasChangeListFilePath() const;
|
||||
|
||||
//! Returns true if a sequence report file path has been supplied, otherwise false.
|
||||
bool HasSequenceReportFilePath() const;
|
||||
|
||||
//! Returns true if the safe mode option has been enabled, otherwise false.
|
||||
bool HasSafeMode() const;
|
||||
|
||||
//! Returns true if the output change list option has been enabled, otherwise false.
|
||||
bool HasOutputChangeList() const;
|
||||
|
||||
//! Returns the path to the runtime configuration file.
|
||||
const RepoPath& GetConfigurationFile() const;
|
||||
const RepoPath& GetConfigurationFilePath() const;
|
||||
|
||||
//! Returns the path to the data file (if any).
|
||||
const AZStd::optional<RepoPath>& GetDataFilePath() const;
|
||||
|
||||
//! Returns the path to the change list file (if any).
|
||||
const AZStd::optional<RepoPath>& GetChangeListFile() const;
|
||||
const AZStd::optional<RepoPath>& GetChangeListFilePath() const;
|
||||
|
||||
//! Returns the path to the sequence report file (if any).
|
||||
const AZStd::optional<RepoPath>& GetSequenceReportFilePath() const;
|
||||
|
||||
//! Returns the test sequence type to run.
|
||||
TestSequenceType GetTestSequenceType() const;
|
||||
@@ -89,8 +98,9 @@ namespace TestImpact
|
||||
|
||||
private:
|
||||
RepoPath m_configurationFile;
|
||||
AZStd::optional<RepoPath> m_dataFile;
|
||||
AZStd::optional<RepoPath> m_changeListFile;
|
||||
bool m_outputChangeList = false;
|
||||
AZStd::optional<RepoPath> m_sequenceReportFile;
|
||||
TestSequenceType m_testSequenceType;
|
||||
Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None;
|
||||
Policy::ExecutionFailure m_executionFailurePolicy = Policy::ExecutionFailure::Continue;
|
||||
|
||||
+80
-98
@@ -9,14 +9,16 @@
|
||||
#include <TestImpactFramework/TestImpactException.h>
|
||||
#include <TestImpactFramework/TestImpactChangeListException.h>
|
||||
#include <TestImpactFramework/TestImpactConfigurationException.h>
|
||||
#include <TestImpactFramework/TestImpactSequenceReportException.h>
|
||||
#include <TestImpactFramework/TestImpactRuntimeException.h>
|
||||
#include <TestImpactFramework/TestImpactConsoleMain.h>
|
||||
#include <TestImpactFramework/TestImpactChangeListSerializer.h>
|
||||
#include <TestImpactFramework/TestImpactChangeList.h>
|
||||
#include <TestImpactFramework/TestImpactRuntime.h>
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
#include <TestImpactFramework/TestImpactClientTestSelection.h>
|
||||
#include <TestImpactFramework/TestImpactRuntime.h>
|
||||
#include <TestImpactFramework/TestImpactClientSequenceReportSerializer.h>
|
||||
|
||||
#include <TestImpactConsoleTestSequenceEventHandler.h>
|
||||
#include <TestImpactCommandLineOptions.h>
|
||||
@@ -33,31 +35,6 @@ namespace TestImpact
|
||||
{
|
||||
namespace Console
|
||||
{
|
||||
//! Generates a string to be used for printing to the console for the specified change list.
|
||||
AZStd::string GenerateChangeListString(const ChangeList& changeList)
|
||||
{
|
||||
AZStd::string output;
|
||||
|
||||
const auto& outputFiles = [&output](const AZStd::vector<RepoPath>& files)
|
||||
{
|
||||
for (const auto& file : files)
|
||||
{
|
||||
output += AZStd::string::format("\t%s\n", file.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
output += AZStd::string::format("Created files (%u):\n", changeList.m_createdFiles.size());
|
||||
outputFiles(changeList.m_createdFiles);
|
||||
|
||||
output += AZStd::string::format("Updated files (%u):\n", changeList.m_updatedFiles.size());
|
||||
outputFiles(changeList.m_updatedFiles);
|
||||
|
||||
output += AZStd::string::format("Deleted files (%u):\n", changeList.m_deletedFiles.size());
|
||||
outputFiles(changeList.m_deletedFiles);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//! Gets the appropriate console return code for the specified test sequence result.
|
||||
ReturnCode GetReturnCodeForTestSequenceResult(TestSequenceResult result)
|
||||
{
|
||||
@@ -75,6 +52,20 @@ namespace TestImpact
|
||||
}
|
||||
}
|
||||
|
||||
//! Wrapper around sequence reports to optionally serialize them and transform the result into a return code.
|
||||
template<typename SequenceReportType>
|
||||
ReturnCode ConsumeSequenceReportAndGetReturnCode(const SequenceReportType& sequenceReport, const CommandLineOptions& options)
|
||||
{
|
||||
if (options.HasSequenceReportFilePath())
|
||||
{
|
||||
std::cout << "Exporting sequence report '" << options.GetSequenceReportFilePath().value().c_str() << "'" << std::endl;
|
||||
const auto sequenceReportJson = SerializeSequenceReport(sequenceReport);
|
||||
WriteFileContents<SequenceReportException>(sequenceReportJson, options.GetSequenceReportFilePath().value());
|
||||
}
|
||||
|
||||
return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult());
|
||||
}
|
||||
|
||||
//! Wrapper around impact analysis sequences to handle the case where the safe mode option is active.
|
||||
ReturnCode WrappedImpactAnalysisTestSequence(
|
||||
const CommandLineOptions& options,
|
||||
@@ -88,35 +79,34 @@ namespace TestImpact
|
||||
CommandLineOptionsException,
|
||||
"Expected a change list for impact analysis but none was provided");
|
||||
|
||||
TestSequenceResult result = TestSequenceResult::Failure;
|
||||
if (options.HasSafeMode())
|
||||
{
|
||||
if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysis)
|
||||
{
|
||||
auto safeImpactAnalysisSequenceReport = runtime.SafeImpactAnalysisTestSequence(
|
||||
changeList.value(),
|
||||
options.GetTestPrioritizationPolicy(),
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
SafeImpactAnalysisTestSequenceStartCallback,
|
||||
SafeImpactAnalysisTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
result = safeImpactAnalysisSequenceReport.GetResult();
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.SafeImpactAnalysisTestSequence(
|
||||
changeList.value(),
|
||||
options.GetTestPrioritizationPolicy(),
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
SafeImpactAnalysisTestSequenceStartCallback,
|
||||
SafeImpactAnalysisTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
else if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysisNoWrite)
|
||||
{
|
||||
// A no-write impact analysis sequence with safe mode enabled is functionally identical to a regular sequence type
|
||||
// due to a) the selected tests being run without instrumentation and b) the discarded tests also being run without
|
||||
// instrumentation
|
||||
auto sequenceReport = runtime.RegularTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
TestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
result = sequenceReport.GetResult();
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.RegularTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
RegularTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -139,20 +129,18 @@ namespace TestImpact
|
||||
throw(Exception("Unexpected sequence type"));
|
||||
}
|
||||
|
||||
auto impactAnalysisSequenceReport = runtime.ImpactAnalysisTestSequence(
|
||||
changeList.value(),
|
||||
options.GetTestPrioritizationPolicy(),
|
||||
dynamicDependencyMapPolicy,
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
ImpactAnalysisTestSequenceStartCallback,
|
||||
ImpactAnalysisTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
result = impactAnalysisSequenceReport.GetResult();
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.ImpactAnalysisTestSequence(
|
||||
changeList.value(),
|
||||
options.GetTestPrioritizationPolicy(),
|
||||
dynamicDependencyMapPolicy,
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
ImpactAnalysisTestSequenceStartCallback,
|
||||
ImpactAnalysisTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
|
||||
return GetReturnCodeForTestSequenceResult(result);
|
||||
};
|
||||
|
||||
//! Entry point for the test impact analysis framework console front end application.
|
||||
@@ -164,28 +152,22 @@ namespace TestImpact
|
||||
AZStd::optional<ChangeList> changeList;
|
||||
|
||||
// If we have a change list, check to see whether or not the client has requested the printing of said change list
|
||||
if (options.HasChangeListFile())
|
||||
if (options.HasChangeListFilePath())
|
||||
{
|
||||
changeList = DeserializeChangeList(ReadFileContents<CommandLineOptionsException>(*options.GetChangeListFile()));
|
||||
if (options.HasOutputChangeList())
|
||||
{
|
||||
std::cout << "Change List:\n";
|
||||
std::cout << GenerateChangeListString(*changeList).c_str();
|
||||
|
||||
if (options.GetTestSequenceType() == TestSequenceType::None)
|
||||
{
|
||||
return ReturnCode::Success;
|
||||
}
|
||||
}
|
||||
changeList = DeserializeChangeList(ReadFileContents<CommandLineOptionsException>(*options.GetChangeListFilePath()));
|
||||
}
|
||||
|
||||
// As of now, there are no other non-test operations other than printing a change list so getting this far is considered an error
|
||||
AZ_TestImpact_Eval(options.GetTestSequenceType() != TestSequenceType::None, CommandLineOptionsException, "No action specified");
|
||||
// As of now, there are no non-test operations but leave this door open for the future
|
||||
if (options.GetTestSequenceType() == TestSequenceType::None)
|
||||
{
|
||||
return ReturnCode::Success;
|
||||
}
|
||||
|
||||
std::cout << "Constructing in-memory model of source tree and test coverage for test suite ";
|
||||
std::cout << GetSuiteTypeName(options.GetSuiteFilter()).c_str() << ", this may take a moment...\n";
|
||||
std::cout << SuiteTypeAsString(options.GetSuiteFilter()).c_str() << ", this may take a moment...\n";
|
||||
Runtime runtime(
|
||||
RuntimeConfigurationFactory(ReadFileContents<CommandLineOptionsException>(options.GetConfigurationFile())),
|
||||
RuntimeConfigurationFactory(ReadFileContents<CommandLineOptionsException>(options.GetConfigurationFilePath())),
|
||||
options.GetDataFilePath(),
|
||||
options.GetSuiteFilter(),
|
||||
options.GetExecutionFailurePolicy(),
|
||||
options.GetFailedTestCoveragePolicy(),
|
||||
@@ -208,25 +190,25 @@ namespace TestImpact
|
||||
{
|
||||
case TestSequenceType::Regular:
|
||||
{
|
||||
const auto sequenceReport = runtime.RegularTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
TestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult());
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.RegularTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
RegularTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
case TestSequenceType::Seed:
|
||||
{
|
||||
const auto sequenceReport = runtime.SeededTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
TestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult());
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.SeededTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
SeedTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
case TestSequenceType::ImpactAnalysisNoWrite:
|
||||
case TestSequenceType::ImpactAnalysis:
|
||||
@@ -241,14 +223,14 @@ namespace TestImpact
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sequenceReport = runtime.SeededTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
TestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback);
|
||||
|
||||
return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult());
|
||||
return ConsumeSequenceReportAndGetReturnCode(
|
||||
runtime.SeededTestSequence(
|
||||
options.GetTestTargetTimeout(),
|
||||
options.GetGlobalTimeout(),
|
||||
TestSequenceStartCallback,
|
||||
SeedTestSequenceCompleteCallback,
|
||||
TestRunCompleteCallback),
|
||||
options);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
+30
-28
@@ -6,8 +6,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactConsoleTestSequenceEventHandler.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <TestImpactConsoleTestSequenceEventHandler.h>
|
||||
#include <TestImpactConsoleUtils.h>
|
||||
|
||||
#include <iostream>
|
||||
@@ -20,7 +21,7 @@ namespace TestImpact
|
||||
{
|
||||
void TestSuiteFilter(SuiteType filter)
|
||||
{
|
||||
std::cout << "Test suite filter: " << GetSuiteTypeName(filter).c_str() << "\n";
|
||||
std::cout << "Test suite filter: " << SuiteTypeAsString(filter).c_str() << "\n";
|
||||
}
|
||||
|
||||
void ImpactAnalysisTestSelection(size_t numSelectedTests, size_t numDiscardedTests, size_t numExcludedTests, size_t numDraftedTests)
|
||||
@@ -36,69 +37,66 @@ namespace TestImpact
|
||||
{
|
||||
std::cout << "Sequence completed in " << (testRunReport.GetDuration().count() / 1000.f) << "s with";
|
||||
|
||||
if (!testRunReport.GetExecutionFailureTests().empty() ||
|
||||
!testRunReport.GetFailingTests().empty() ||
|
||||
!testRunReport.GetTimedOutTests().empty() ||
|
||||
!testRunReport.GetUnexecutedTests().empty())
|
||||
if (!testRunReport.GetExecutionFailureTestRuns().empty() ||
|
||||
!testRunReport.GetFailingTestRuns().empty() ||
|
||||
!testRunReport.GetTimedOutTestRuns().empty() ||
|
||||
!testRunReport.GetUnexecutedTestRuns().empty())
|
||||
{
|
||||
std::cout << ":\n";
|
||||
std::cout << SetColor(Foreground::White, Background::Red).c_str()
|
||||
<< testRunReport.GetFailingTests().size()
|
||||
<< testRunReport.GetFailingTestRuns().size()
|
||||
<< ResetColor().c_str() << " test failures\n";
|
||||
|
||||
std::cout << SetColor(Foreground::White, Background::Red).c_str()
|
||||
<< testRunReport.GetExecutionFailureTests().size()
|
||||
<< testRunReport.GetExecutionFailureTestRuns().size()
|
||||
<< ResetColor().c_str() << " execution failures\n";
|
||||
|
||||
std::cout << SetColor(Foreground::White, Background::Red).c_str()
|
||||
<< testRunReport.GetTimedOutTests().size()
|
||||
<< testRunReport.GetTimedOutTestRuns().size()
|
||||
<< ResetColor().c_str() << " test timeouts\n";
|
||||
|
||||
std::cout << SetColor(Foreground::White, Background::Red).c_str()
|
||||
<< testRunReport.GetUnexecutedTests().size()
|
||||
<< testRunReport.GetUnexecutedTestRuns().size()
|
||||
<< ResetColor().c_str() << " unexecuted tests\n";
|
||||
|
||||
if (!testRunReport.GetFailingTests().empty())
|
||||
if (!testRunReport.GetFailingTestRuns().empty())
|
||||
{
|
||||
std::cout << "\nTest failures:\n";
|
||||
for (const auto& testRunFailure : testRunReport.GetFailingTests())
|
||||
for (const auto& testRunFailure : testRunReport.GetFailingTestRuns())
|
||||
{
|
||||
for (const auto& testCaseFailure : testRunFailure.GetTestCaseFailures())
|
||||
for (const auto& test : testRunFailure.GetTests())
|
||||
{
|
||||
for (const auto& testFailure : testCaseFailure.GetTestFailures())
|
||||
if (test.GetResult() == Client::TestResult::Failed)
|
||||
{
|
||||
std::cout << " "
|
||||
<< testRunFailure.GetTargetName().c_str()
|
||||
<< "." << testCaseFailure.GetName().c_str()
|
||||
<< "." << testFailure.GetName().c_str() << "\n";
|
||||
std::cout << " " << test.GetName().c_str() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!testRunReport.GetExecutionFailureTests().empty())
|
||||
if (!testRunReport.GetExecutionFailureTestRuns().empty())
|
||||
{
|
||||
std::cout << "\nExecution failures:\n";
|
||||
for (const auto& executionFailure : testRunReport.GetExecutionFailureTests())
|
||||
for (const auto& executionFailure : testRunReport.GetExecutionFailureTestRuns())
|
||||
{
|
||||
std::cout << " " << executionFailure.GetTargetName().c_str() << "\n";
|
||||
std::cout << executionFailure.GetCommandString().c_str() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!testRunReport.GetTimedOutTests().empty())
|
||||
if (!testRunReport.GetTimedOutTestRuns().empty())
|
||||
{
|
||||
std::cout << "\nTimed out tests:\n";
|
||||
for (const auto& testTimeout : testRunReport.GetTimedOutTests())
|
||||
for (const auto& testTimeout : testRunReport.GetTimedOutTestRuns())
|
||||
{
|
||||
std::cout << " " << testTimeout.GetTargetName().c_str() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!testRunReport.GetUnexecutedTests().empty())
|
||||
if (!testRunReport.GetUnexecutedTestRuns().empty())
|
||||
{
|
||||
std::cout << "\nUnexecuted tests:\n";
|
||||
for (const auto& unexecutedTest : testRunReport.GetUnexecutedTests())
|
||||
for (const auto& unexecutedTest : testRunReport.GetUnexecutedTestRuns())
|
||||
{
|
||||
std::cout << " " << unexecutedTest.GetTargetName().c_str() << "\n";
|
||||
}
|
||||
@@ -106,7 +104,7 @@ namespace TestImpact
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << SetColor(Foreground::White, Background::Green).c_str() << " \100% passes!\n" << ResetColor().c_str() << "\n";
|
||||
std::cout << " " << SetColor(Foreground::White, Background::Green).c_str() << "100% passes!\n" << ResetColor().c_str() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,13 +147,17 @@ namespace TestImpact
|
||||
draftedTests.size());
|
||||
}
|
||||
|
||||
void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport)
|
||||
void RegularTestSequenceCompleteCallback(const Client::RegularSequenceReport& sequenceReport)
|
||||
{
|
||||
|
||||
Output::FailureReport(sequenceReport.GetSelectedTestRunReport());
|
||||
std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n";
|
||||
}
|
||||
|
||||
void SeedTestSequenceCompleteCallback(const Client::SeedSequenceReport& sequenceReport)
|
||||
{
|
||||
Output::FailureReport(sequenceReport.GetSelectedTestRunReport());
|
||||
}
|
||||
|
||||
void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport)
|
||||
{
|
||||
std::cout << "Selected test run:\n";
|
||||
@@ -181,7 +183,7 @@ namespace TestImpact
|
||||
std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n";
|
||||
}
|
||||
|
||||
void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns)
|
||||
void TestRunCompleteCallback(const Client::TestRunBase& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns)
|
||||
{
|
||||
const auto progress =
|
||||
AZStd::string::format("(%03u/%03u)", numTestRunsCompleted, totalNumTestRuns, testRun.GetTargetName().c_str());
|
||||
|
||||
+6
-3
@@ -38,8 +38,11 @@ namespace TestImpact
|
||||
const Client::TestRunSelection& discardedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests);
|
||||
|
||||
//! Handler for TestSequenceCompleteCallback event.
|
||||
void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport);
|
||||
//! Handler for RegularTestSequenceCompleteCallback event.
|
||||
void RegularTestSequenceCompleteCallback(const Client::RegularSequenceReport& sequenceReport);
|
||||
|
||||
//! Handler for SeedTestSequenceCompleteCallback event.
|
||||
void SeedTestSequenceCompleteCallback(const Client::SeedSequenceReport& sequenceReport);
|
||||
|
||||
//! Handler for ImpactAnalysisTestSequenceCompleteCallback event.
|
||||
void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport);
|
||||
@@ -48,6 +51,6 @@ namespace TestImpact
|
||||
void SafeImpactAnalysisTestSequenceCompleteCallback(const Client::SafeImpactAnalysisSequenceReport& sequenceReport);
|
||||
|
||||
//! Handler for TestRunCompleteCallback event.
|
||||
void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns);
|
||||
void TestRunCompleteCallback(const Client::TestRunBase& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns);
|
||||
} // namespace Console
|
||||
} // namespace TestImpact
|
||||
|
||||
+11
-10
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactConfigurationException.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <TestImpactRuntimeConfigurationFactory.h>
|
||||
|
||||
@@ -140,17 +141,17 @@ namespace TestImpact
|
||||
return tempWorkspaceConfig;
|
||||
}
|
||||
|
||||
AZStd::array<RepoPath, 3> ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTIAFile)
|
||||
AZStd::array<RepoPath, 3> ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTiaFile)
|
||||
{
|
||||
AZStd::array<RepoPath, 3> sparTIAFiles;
|
||||
sparTIAFiles[static_cast<size_t>(SuiteType::Main)] =
|
||||
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Main).c_str()].GetString());
|
||||
sparTIAFiles[static_cast<size_t>(SuiteType::Periodic)] =
|
||||
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Periodic).c_str()].GetString());
|
||||
sparTIAFiles[static_cast<size_t>(SuiteType::Sandbox)] =
|
||||
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Sandbox).c_str()].GetString());
|
||||
AZStd::array<RepoPath, 3> sparTiaFiles;
|
||||
sparTiaFiles[static_cast<size_t>(SuiteType::Main)] =
|
||||
GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Main).c_str()].GetString());
|
||||
sparTiaFiles[static_cast<size_t>(SuiteType::Periodic)] =
|
||||
GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Periodic).c_str()].GetString());
|
||||
sparTiaFiles[static_cast<size_t>(SuiteType::Sandbox)] =
|
||||
GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Sandbox).c_str()].GetString());
|
||||
|
||||
return sparTIAFiles;
|
||||
return sparTiaFiles;
|
||||
}
|
||||
|
||||
WorkspaceConfig::Active ParseActiveWorkspaceConfig(const rapidjson::Value& activeWorkspace)
|
||||
@@ -160,7 +161,7 @@ namespace TestImpact
|
||||
activeWorkspaceConfig.m_root = activeWorkspace[Config::Keys[Config::Root]].GetString();
|
||||
activeWorkspaceConfig.m_enumerationCacheDirectory
|
||||
= GetAbsPathFromRelPath(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::EnumerationCacheDir]].GetString());
|
||||
activeWorkspaceConfig.m_sparTIAFiles =
|
||||
activeWorkspaceConfig.m_sparTiaFiles =
|
||||
ParseTestImpactAnalysisDataFiles(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::TestImpactDataFiles]]);
|
||||
return activeWorkspaceConfig;
|
||||
}
|
||||
|
||||
+402
-98
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
@@ -11,10 +12,25 @@
|
||||
#include <TestImpactFramework/TestImpactClientTestSelection.h>
|
||||
#include <TestImpactFramework/TestImpactTestSequence.h>
|
||||
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
//! The report types generated by each sequence.
|
||||
enum class SequenceReportType : AZ::u8
|
||||
{
|
||||
RegularSequence,
|
||||
SeedSequence,
|
||||
ImpactAnalysisSequence,
|
||||
SafeImpactAnalysisSequence
|
||||
};
|
||||
|
||||
//! Calculates the final sequence result for a composite of multiple sequences.
|
||||
TestSequenceResult CalculateMultiTestSequenceResult(const AZStd::vector<TestSequenceResult>& results);
|
||||
|
||||
//! Report detailing the result and duration of a given set of test runs along with the details of each individual test run.
|
||||
class TestRunReport
|
||||
{
|
||||
@@ -23,20 +39,20 @@ namespace TestImpact
|
||||
//! @param result The result of this set of test runs.
|
||||
//! @param startTime The time point his set of test runs started.
|
||||
//! @param duration The duration this set of test runs took to complete.
|
||||
//! @param passingTests The set of test runs that executed successfully with no failing tests.
|
||||
//! @param failing tests The set of test runs that executed successfully but had one or more failing tests.
|
||||
//! @param executionFailureTests The set of test runs that failed to execute.
|
||||
//! @param timedOutTests The set of test runs that executed successfully but were terminated prematurely due to timing out.
|
||||
//! @param unexecutedTests The set of test runs that were queued up for execution but did not get the opportunity to execute.
|
||||
//! @param passingTestRuns The set of test runs that executed successfully with no failing test runs.
|
||||
//! @param failingTestRuns The set of test runs that executed successfully but had one or more failing tests.
|
||||
//! @param executionFailureTestRuns The set of test runs that failed to execute.
|
||||
//! @param timedOutTestRuns The set of test runs that executed successfully but were terminated prematurely due to timing out.
|
||||
//! @param unexecutedTestRuns The set of test runs that were queued up for execution but did not get the opportunity to execute.
|
||||
TestRunReport(
|
||||
TestSequenceResult result,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
AZStd::chrono::milliseconds duration,
|
||||
AZStd::vector<TestRun>&& passingTests,
|
||||
AZStd::vector<TestRunWithTestFailures>&& failingTests,
|
||||
AZStd::vector<TestRun>&& executionFailureTests,
|
||||
AZStd::vector<TestRun>&& timedOutTests,
|
||||
AZStd::vector<TestRun>&& unexecutedTests);
|
||||
AZStd::vector<PassingTestRun>&& passingTestRuns,
|
||||
AZStd::vector<FailingTestRun>&& failingTestRuns,
|
||||
AZStd::vector<TestRunWithExecutionFailure>&& executionFailureTestRuns,
|
||||
AZStd::vector<TimedOutTestRun>&& timedOutTestRuns,
|
||||
AZStd::vector<UnexecutedTestRun>&& unexecutedTestRuns);
|
||||
|
||||
//! Returns the result of this sequence of test runs.
|
||||
TestSequenceResult GetResult() const;
|
||||
@@ -50,190 +66,478 @@ namespace TestImpact
|
||||
//! Returns the duration this sequence of test runs took to complete.
|
||||
AZStd::chrono::milliseconds GetDuration() const;
|
||||
|
||||
//! Returns the total number of test runs.
|
||||
size_t GetTotalNumTestRuns() const;
|
||||
|
||||
//! Returns the number of passing test runs.
|
||||
size_t GetNumPassingTests() const;
|
||||
size_t GetNumPassingTestRuns() const;
|
||||
|
||||
//! Returns the number of failing test runs.
|
||||
size_t GetNumFailingTests() const;
|
||||
size_t GetNumFailingTestRuns() const;
|
||||
|
||||
//! Returns the number of test runs that failed to execute.
|
||||
size_t GetNumExecutionFailureTestRuns() const;
|
||||
|
||||
//! Returns the number of timed out test runs.
|
||||
size_t GetNumTimedOutTests() const;
|
||||
size_t GetNumTimedOutTestRuns() const;
|
||||
|
||||
//! Returns the number of unexecuted test runs.
|
||||
size_t GetNumUnexecutedTests() const;
|
||||
size_t GetNumUnexecutedTestRuns() const;
|
||||
|
||||
//! Returns the total number of passing tests across all test runs in the report.
|
||||
size_t GetTotalNumPassingTests() const;
|
||||
|
||||
//! Returns the total number of failing tests across all test runs in the report.
|
||||
size_t GetTotalNumFailingTests() const;
|
||||
|
||||
//! Returns the total number of disabled tests across all test runs in the report.
|
||||
size_t GetTotalNumDisabledTests() const;
|
||||
|
||||
//! Returns the set of test runs that executed successfully with no failing tests.
|
||||
const AZStd::vector<TestRun>& GetPassingTests() const;
|
||||
const AZStd::vector<PassingTestRun>& GetPassingTestRuns() const;
|
||||
|
||||
//! Returns the set of test runs that executed successfully but had one or more failing tests.
|
||||
const AZStd::vector<TestRunWithTestFailures>& GetFailingTests() const;
|
||||
const AZStd::vector<FailingTestRun>& GetFailingTestRuns() const;
|
||||
|
||||
//! Returns the set of test runs that failed to execute.
|
||||
const AZStd::vector<TestRun>& GetExecutionFailureTests() const;
|
||||
const AZStd::vector<TestRunWithExecutionFailure>& GetExecutionFailureTestRuns() const;
|
||||
|
||||
//! Returns the set of test runs that executed successfully but were terminated prematurely due to timing out.
|
||||
const AZStd::vector<TestRun>& GetTimedOutTests() const;
|
||||
const AZStd::vector<TimedOutTestRun>& GetTimedOutTestRuns() const;
|
||||
|
||||
//! Returns the set of test runs that were queued up for execution but did not get the opportunity to execute.
|
||||
const AZStd::vector<TestRun>& GetUnexecutedTests() const;
|
||||
const AZStd::vector<UnexecutedTestRun>& GetUnexecutedTestRuns() const;
|
||||
private:
|
||||
TestSequenceResult m_result;
|
||||
TestSequenceResult m_result = TestSequenceResult::Success;
|
||||
AZStd::chrono::high_resolution_clock::time_point m_startTime;
|
||||
AZStd::chrono::milliseconds m_duration;
|
||||
AZStd::vector<TestRun> m_passingTests;
|
||||
AZStd::vector<TestRunWithTestFailures> m_failingTests;
|
||||
AZStd::vector<TestRun> m_executionFailureTests;
|
||||
AZStd::vector<TestRun> m_timedOutTests;
|
||||
AZStd::vector<TestRun> m_unexecutedTests;
|
||||
AZStd::chrono::milliseconds m_duration = AZStd::chrono::milliseconds{ 0 };
|
||||
AZStd::vector<PassingTestRun> m_passingTestRuns;
|
||||
AZStd::vector<FailingTestRun> m_failingTestRuns;
|
||||
AZStd::vector<TestRunWithExecutionFailure> m_executionFailureTestRuns;
|
||||
AZStd::vector<TimedOutTestRun> m_timedOutTestRuns;
|
||||
AZStd::vector<UnexecutedTestRun> m_unexecutedTestRuns;
|
||||
size_t m_totalNumPassingTests = 0;
|
||||
size_t m_totalNumFailingTests = 0;
|
||||
size_t m_totalNumDisabledTests = 0;
|
||||
};
|
||||
|
||||
//! Report detailing a test run sequence of selected tests.
|
||||
class SequenceReport
|
||||
//! Base class for all sequence report types.
|
||||
template<typename PolicyStateType>
|
||||
class SequenceReportBase
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for a sequence of selected tests.
|
||||
//! @param type The type of sequence this report is generated for.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTests The target names of the selected tests.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport);
|
||||
SequenceReportBase(
|
||||
SequenceReportType type,
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const PolicyStateType& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport)
|
||||
: m_type(type)
|
||||
, m_maxConcurrency(maxConcurrency)
|
||||
, m_testTargetTimeout(testTargetTimeout)
|
||||
, m_globalTimeout(globalTimeout)
|
||||
, m_policyState(policyState)
|
||||
, m_suite(suiteType)
|
||||
, m_selectedTestRuns(selectedTestRuns)
|
||||
, m_selectedTestRunReport(AZStd::move(selectedTestRunReport))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SequenceReportBase() = default;
|
||||
|
||||
//! Returns the identifying type for this sequence report.
|
||||
SequenceReportType GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
//! Returns the maximum concurrency for this sequence.
|
||||
size_t GetMaxConcurrency() const
|
||||
{
|
||||
return m_maxConcurrency;
|
||||
}
|
||||
|
||||
//! Returns the global timeout for this sequence.
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& GetGlobalTimeout() const
|
||||
{
|
||||
return m_globalTimeout;
|
||||
}
|
||||
|
||||
//! Returns the test target timeout for this sequence.
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& GetTestTargetTimeout() const
|
||||
{
|
||||
return m_testTargetTimeout;
|
||||
}
|
||||
|
||||
//! Returns the policy state for this sequence.
|
||||
const PolicyStateType& GetPolicyState() const
|
||||
{
|
||||
return m_policyState;
|
||||
}
|
||||
|
||||
//! Returns the suite for this sequence.
|
||||
SuiteType GetSuite() const
|
||||
{
|
||||
return m_suite;
|
||||
}
|
||||
|
||||
//! Returns the result of the sequence.
|
||||
virtual TestSequenceResult GetResult() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetResult();
|
||||
}
|
||||
|
||||
//! Returns the tests selected for running in the sequence.
|
||||
TestRunSelection GetSelectedTests() const;
|
||||
TestRunSelection GetSelectedTestRuns() const
|
||||
{
|
||||
return m_selectedTestRuns;
|
||||
}
|
||||
|
||||
//! Returns the report for the selected test runs.
|
||||
TestRunReport GetSelectedTestRunReport() const;
|
||||
TestRunReport GetSelectedTestRunReport() const
|
||||
{
|
||||
return m_selectedTestRunReport;
|
||||
}
|
||||
|
||||
//! Returns the start time of the sequence.
|
||||
AZStd::chrono::high_resolution_clock::time_point GetStartTime() const;
|
||||
AZStd::chrono::high_resolution_clock::time_point GetStartTime() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetStartTime();
|
||||
}
|
||||
|
||||
//! Returns the end time of the sequence.
|
||||
AZStd::chrono::high_resolution_clock::time_point GetEndTime() const;
|
||||
|
||||
//! Returns the result of the sequence.
|
||||
virtual TestSequenceResult GetResult() const;
|
||||
AZStd::chrono::high_resolution_clock::time_point GetEndTime() const
|
||||
{
|
||||
return GetStartTime() + GetDuration();
|
||||
}
|
||||
|
||||
//! Returns the entire duration the sequence took from start to finish.
|
||||
virtual AZStd::chrono::milliseconds GetDuration() const;
|
||||
virtual AZStd::chrono::milliseconds GetDuration() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetDuration();
|
||||
}
|
||||
|
||||
//! Get the total number of tests in the sequence that passed.
|
||||
virtual size_t GetTotalNumPassingTests() const;
|
||||
//! Returns the total number of test runs across all test run reports.
|
||||
virtual size_t GetTotalNumTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetTotalNumTestRuns();
|
||||
}
|
||||
|
||||
//! Get the total number of tests in the sequence that contain one or more test failures.
|
||||
virtual size_t GetTotalNumFailingTests() const;
|
||||
//! Returns the total number of passing tests across all test targets in all test run reports.
|
||||
virtual size_t GetTotalNumPassingTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetTotalNumPassingTests();
|
||||
}
|
||||
|
||||
//! Get the total number of tests in the sequence that timed out whilst in flight.
|
||||
virtual size_t GetTotalNumTimedOutTests() const;
|
||||
//! Returns the total number of failing tests across all test targets in all test run reports.
|
||||
virtual size_t GetTotalNumFailingTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetTotalNumFailingTests();
|
||||
}
|
||||
|
||||
//! Get the total number of tests in the sequence that were queued for execution but did not get the oppurtunity to execute.
|
||||
virtual size_t GetTotalNumUnexecutedTests() const;
|
||||
//! Returns the total number of unexecuted tests across all test targets in all test run reports.
|
||||
virtual size_t GetTotalNumDisabledTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetTotalNumDisabledTests();
|
||||
}
|
||||
|
||||
//! Get the total number of test runs in the sequence that passed.
|
||||
virtual size_t GetTotalNumPassingTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumPassingTestRuns();
|
||||
}
|
||||
|
||||
//! Get the total number of test runs in the sequence that contain one or more test failures.
|
||||
virtual size_t GetTotalNumFailingTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumFailingTestRuns();
|
||||
}
|
||||
|
||||
//! Returns the total number of test runs that failed to execute.
|
||||
virtual size_t GetTotalNumExecutionFailureTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumExecutionFailureTestRuns();
|
||||
}
|
||||
|
||||
//! Get the total number of test runs in the sequence that timed out whilst in flight.
|
||||
virtual size_t GetTotalNumTimedOutTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumTimedOutTestRuns();
|
||||
}
|
||||
|
||||
//! Get the total number of test runs in the sequence that were queued for execution but did not get the opportunity to execute.
|
||||
virtual size_t GetTotalNumUnexecutedTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumUnexecutedTestRuns();
|
||||
}
|
||||
|
||||
private:
|
||||
SuiteType m_suite;
|
||||
TestRunSelection m_selectedTests;
|
||||
SequenceReportType m_type;
|
||||
size_t m_maxConcurrency = 0;
|
||||
AZStd::optional<AZStd::chrono::milliseconds> m_testTargetTimeout;
|
||||
AZStd::optional<AZStd::chrono::milliseconds> m_globalTimeout;
|
||||
PolicyStateType m_policyState;
|
||||
SuiteType m_suite = SuiteType::Main;
|
||||
TestRunSelection m_selectedTestRuns;
|
||||
TestRunReport m_selectedTestRunReport;
|
||||
};
|
||||
|
||||
//! Report detailing a test run sequence of selected and drafted tests.
|
||||
class DraftingSequenceReport
|
||||
: public SequenceReport
|
||||
//! Report type for regular test sequences.
|
||||
class RegularSequenceReport
|
||||
: public SequenceReportBase<SequencePolicyState>
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for a sequence of selected and drafted tests.
|
||||
//! Constructs the report for a regular sequence.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTests The target names of the selected tests.
|
||||
//! @param draftedTests The target names of the drafted tests.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
RegularSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport);
|
||||
};
|
||||
|
||||
//! Report type for seed test sequences.
|
||||
class SeedSequenceReport
|
||||
: public SequenceReportBase<SequencePolicyState>
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for a seed sequence.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
SeedSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport);
|
||||
};
|
||||
|
||||
//! Report detailing a test run sequence of selected and drafted tests.
|
||||
template<typename PolicyStateType>
|
||||
class DraftingSequenceReportBase
|
||||
: public SequenceReportBase<PolicyStateType>
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for sequences that draft in previously failed/newly added test targets.
|
||||
//! @param type The type of sequence this report is generated for.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param draftedTestRuns The target names of the drafted test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
//! @param draftedTestRunReport The report for the set of drafted test runs.
|
||||
DraftingSequenceReport(
|
||||
DraftingSequenceReportBase(
|
||||
SequenceReportType type,
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const PolicyStateType& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& draftedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport);
|
||||
TestRunReport&& draftedTestRunReport)
|
||||
: SequenceReportBase(
|
||||
type,
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTestRuns,
|
||||
AZStd::move(selectedTestRunReport))
|
||||
, m_draftedTestRuns(draftedTestRuns)
|
||||
, m_draftedTestRunReport(AZStd::move(draftedTestRunReport))
|
||||
{
|
||||
}
|
||||
|
||||
// SequenceReport overrides ...
|
||||
TestSequenceResult GetResult() const override;
|
||||
AZStd::chrono::milliseconds GetDuration() const override;
|
||||
size_t GetTotalNumPassingTests() const override;
|
||||
size_t GetTotalNumFailingTests() const override;
|
||||
size_t GetTotalNumTimedOutTests() const override;
|
||||
size_t GetTotalNumUnexecutedTests() const override;
|
||||
|
||||
//! Returns the tests drafted for running in the sequence.
|
||||
const AZStd::vector<AZStd::string>& GetDraftedTests() const;
|
||||
//! Returns the tests drafted for running in the sequence.
|
||||
const AZStd::vector<AZStd::string>& GetDraftedTestRuns() const
|
||||
{
|
||||
return m_draftedTestRuns;
|
||||
}
|
||||
|
||||
//! Returns the report for the drafted test runs.
|
||||
TestRunReport GetDraftedTestRunReport() const;
|
||||
TestRunReport GetDraftedTestRunReport() const
|
||||
{
|
||||
return m_draftedTestRunReport;
|
||||
}
|
||||
|
||||
// SequenceReport overrides ...
|
||||
AZStd::chrono::milliseconds GetDuration() const override
|
||||
{
|
||||
return SequenceReportBase::GetDuration() + m_draftedTestRunReport.GetDuration();
|
||||
}
|
||||
|
||||
TestSequenceResult GetResult() const override
|
||||
{
|
||||
return CalculateMultiTestSequenceResult({ SequenceReportBase::GetResult(), m_draftedTestRunReport.GetResult() });
|
||||
}
|
||||
|
||||
size_t GetTotalNumTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumTestRuns() + m_draftedTestRunReport.GetTotalNumTestRuns();
|
||||
}
|
||||
|
||||
size_t GetTotalNumPassingTests() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumPassingTests() + m_draftedTestRunReport.GetTotalNumPassingTests();
|
||||
}
|
||||
|
||||
size_t GetTotalNumFailingTests() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumFailingTests() + m_draftedTestRunReport.GetTotalNumFailingTests();
|
||||
}
|
||||
|
||||
size_t GetTotalNumDisabledTests() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumDisabledTests() + m_draftedTestRunReport.GetTotalNumDisabledTests();
|
||||
}
|
||||
|
||||
size_t GetTotalNumPassingTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumPassingTestRuns() + m_draftedTestRunReport.GetNumPassingTestRuns();
|
||||
}
|
||||
|
||||
size_t GetTotalNumFailingTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumFailingTestRuns() + m_draftedTestRunReport.GetNumFailingTestRuns();
|
||||
}
|
||||
|
||||
size_t GetTotalNumExecutionFailureTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumExecutionFailureTestRuns() + m_draftedTestRunReport.GetNumExecutionFailureTestRuns();
|
||||
}
|
||||
|
||||
size_t GetTotalNumTimedOutTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumTimedOutTestRuns() + m_draftedTestRunReport.GetNumTimedOutTestRuns();
|
||||
}
|
||||
|
||||
size_t GetTotalNumUnexecutedTestRuns() const override
|
||||
{
|
||||
return SequenceReportBase::GetTotalNumUnexecutedTestRuns() + m_draftedTestRunReport.GetNumUnexecutedTestRuns();
|
||||
}
|
||||
private:
|
||||
AZStd::vector<AZStd::string> m_draftedTests;
|
||||
AZStd::vector<AZStd::string> m_draftedTestRuns;
|
||||
TestRunReport m_draftedTestRunReport;
|
||||
};
|
||||
|
||||
//! Report detailing an impact analysis sequence of selected, discarded and drafted tests.
|
||||
class ImpactAnalysisSequenceReport
|
||||
: public DraftingSequenceReport
|
||||
: public DraftingSequenceReportBase<ImpactAnalysisSequencePolicyState>
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for a sequence of selected and drafted tests.
|
||||
//! Constructs the report for an impact analysis sequence.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTests The target names of the selected tests.
|
||||
//! @param discardedTests The target names of the discarded tests.
|
||||
//! @param draftedTests The target names of the drafted tests.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param draftedTestRuns The target names of the drafted test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
//! @param draftedTestRunReport The report for the set of drafted test runs.
|
||||
ImpactAnalysisSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const ImpactAnalysisSequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const AZStd::vector<AZStd::string>& discardedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& discardedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& draftedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport);
|
||||
|
||||
//! Returns the tests discarded from running in the sequence.
|
||||
const AZStd::vector<AZStd::string>& GetDiscardedTests() const;
|
||||
//! Returns the test runs discarded from running in the sequence.
|
||||
const AZStd::vector<AZStd::string>& GetDiscardedTestRuns() const;
|
||||
private:
|
||||
AZStd::vector<AZStd::string> m_discardedTests;
|
||||
AZStd::vector<AZStd::string> m_discardedTestRuns;
|
||||
};
|
||||
|
||||
//! Report detailing an impact analysis sequence of selected, discarded and drafted tests.
|
||||
//! Report detailing an impact analysis sequence of selected, discarded and drafted test runs.
|
||||
class SafeImpactAnalysisSequenceReport
|
||||
: public DraftingSequenceReport
|
||||
: public DraftingSequenceReportBase<SafeImpactAnalysisSequencePolicyState>
|
||||
{
|
||||
public:
|
||||
//! Constructs the report for a sequence of selected and drafted tests.
|
||||
//! Constructs the report for a sequence of selected, discarded and drafted test runs.
|
||||
//! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time.
|
||||
//! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty).
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param policyState The policy state this sequence was executed under.
|
||||
//! @param suiteType The suite from which the tests have been selected from.
|
||||
//! @param selectedTests The target names of the selected tests.
|
||||
//! @param discardedTests The target names of the discarded tests.
|
||||
//! @param draftedTests The target names of the drafted tests.
|
||||
//! @param selectedTestRuns The target names of the selected test runs.
|
||||
//! @param discardedTestRuns The target names of the discarded test runs.
|
||||
//! @param draftedTestRuns The target names of the drafted test runs.
|
||||
//! @param selectedTestRunReport The report for the set of selected test runs.
|
||||
//! @param discardedTestRunReport The report for the set of discarded test runs.
|
||||
//! @param draftedTestRunReport The report for the set of drafted test runs.
|
||||
SafeImpactAnalysisSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SafeImpactAnalysisSequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const TestRunSelection& discardedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
const TestRunSelection& discardedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& draftedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& discardedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport);
|
||||
|
||||
// DraftingSequenceReport overrides ...
|
||||
TestSequenceResult GetResult() const override;
|
||||
// SequenceReport overrides ...
|
||||
AZStd::chrono::milliseconds GetDuration() const override;
|
||||
TestSequenceResult GetResult() const override;
|
||||
size_t GetTotalNumTestRuns() const override;
|
||||
size_t GetTotalNumPassingTests() const override;
|
||||
size_t GetTotalNumFailingTests() const override;
|
||||
size_t GetTotalNumTimedOutTests() const override;
|
||||
size_t GetTotalNumUnexecutedTests() const override;
|
||||
size_t GetTotalNumDisabledTests() const override;
|
||||
size_t GetTotalNumPassingTestRuns() const override;
|
||||
size_t GetTotalNumFailingTestRuns() const override;
|
||||
size_t GetTotalNumExecutionFailureTestRuns() const override;
|
||||
size_t GetTotalNumTimedOutTestRuns() const override;
|
||||
size_t GetTotalNumUnexecutedTestRuns() const override;
|
||||
|
||||
//! Returns the report for the discarded test runs.
|
||||
const TestRunSelection GetDiscardedTests() const;
|
||||
const TestRunSelection GetDiscardedTestRuns() const;
|
||||
|
||||
//! Returns the report for the discarded test runs.
|
||||
TestRunReport GetDiscardedTestRunReport() const;
|
||||
|
||||
private:
|
||||
TestRunSelection m_discardedTests;
|
||||
TestRunSelection m_discardedTestRuns;
|
||||
TestRunReport m_discardedTestRunReport;
|
||||
};
|
||||
} // namespace Client
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <TestImpactFramework/TestImpactClientSequenceReport.h>
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
//! Serializes a regular sequence report to JSON format.
|
||||
AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport);
|
||||
|
||||
//! Serializes a seed sequence report to JSON format.
|
||||
AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport);
|
||||
|
||||
//! Serializes an impact analysis sequence report to JSON format.
|
||||
AZStd::string SerializeSequenceReport(const Client::ImpactAnalysisSequenceReport& sequenceReport);
|
||||
|
||||
//! Serializes a safe impact analysis sequence report to JSON format.
|
||||
AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport);
|
||||
} // namespace TestImpact
|
||||
+96
-49
@@ -26,8 +26,8 @@ namespace TestImpact
|
||||
AllTestsPass //!< The test run completed its run and all tests passed.
|
||||
};
|
||||
|
||||
//! Representation of a completed test run.
|
||||
class TestRun
|
||||
//! Representation of a test run.
|
||||
class TestRunBase
|
||||
{
|
||||
public:
|
||||
//! Constructs the client facing representation of a given test target's run.
|
||||
@@ -36,13 +36,15 @@ namespace TestImpact
|
||||
//! @param startTime The start time, relative to the sequence start, that this run started.
|
||||
//! @param duration The duration that this test run took to complete.
|
||||
//! @param result The result of the run.
|
||||
TestRun(
|
||||
TestRunBase(
|
||||
const AZStd::string& name,
|
||||
const AZStd::string& commandString,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
AZStd::chrono::milliseconds duration,
|
||||
TestRunResult result);
|
||||
|
||||
virtual ~TestRunBase() = default;
|
||||
|
||||
//! Returns the test target name.
|
||||
const AZStd::string& GetTargetName() const;
|
||||
|
||||
@@ -69,75 +71,120 @@ namespace TestImpact
|
||||
AZStd::chrono::milliseconds m_duration;
|
||||
};
|
||||
|
||||
//! Represents an individual test of a test target that failed.
|
||||
class TestFailure
|
||||
//! Representation of a test run that failed to execute.
|
||||
class TestRunWithExecutionFailure
|
||||
: public TestRunBase
|
||||
{
|
||||
public:
|
||||
TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage);
|
||||
using TestRunBase::TestRunBase;
|
||||
TestRunWithExecutionFailure(TestRunBase&& testRun);
|
||||
};
|
||||
|
||||
//! Returns the name of the test that failed.
|
||||
//! Representation of a test run that was terminated in-flight due to timing out.
|
||||
class TimedOutTestRun
|
||||
: public TestRunBase
|
||||
{
|
||||
public:
|
||||
using TestRunBase::TestRunBase;
|
||||
TimedOutTestRun(TestRunBase&& testRun);
|
||||
};
|
||||
|
||||
//! Representation of a test run that was not executed.
|
||||
class UnexecutedTestRun
|
||||
: public TestRunBase
|
||||
{
|
||||
public:
|
||||
using TestRunBase::TestRunBase;
|
||||
UnexecutedTestRun(TestRunBase&& testRun);
|
||||
};
|
||||
|
||||
// Result of a test executed during a test run.
|
||||
enum class TestResult : AZ::u8
|
||||
{
|
||||
Passed,
|
||||
Failed,
|
||||
NotRun
|
||||
};
|
||||
|
||||
//! Representation of a single test in a test target.
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
//! Constructs the test with the specified name and result.
|
||||
Test(const AZStd::string& testName, TestResult result);
|
||||
|
||||
//! Returns the name of this test.
|
||||
const AZStd::string& GetName() const;
|
||||
|
||||
//! Returns the error message of the test that failed.
|
||||
const AZStd::string& GetErrorMessage() const;
|
||||
//! Returns the result of executing this test.
|
||||
TestResult GetResult() const;
|
||||
|
||||
private:
|
||||
AZStd::string m_name;
|
||||
AZStd::string m_errorMessage;
|
||||
TestResult m_result;
|
||||
};
|
||||
|
||||
//! Represents a collection of tests that failed.
|
||||
//! @note Only the failing tests are included in the collection.
|
||||
class TestCaseFailure
|
||||
//! Representation of a test run that completed with or without test failures.
|
||||
class CompletedTestRun
|
||||
: public TestRunBase
|
||||
{
|
||||
public:
|
||||
TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector<TestFailure>&& testFailures);
|
||||
|
||||
//! Returns the name of the test case containing the failing tests.
|
||||
const AZStd::string& GetName() const;
|
||||
|
||||
//! Returns the collection of tests in this test case that failed.
|
||||
const AZStd::vector<TestFailure>& GetTestFailures() const;
|
||||
|
||||
private:
|
||||
AZStd::string m_name;
|
||||
AZStd::vector<TestFailure> m_testFailures;
|
||||
};
|
||||
|
||||
//! Representation of a test run's failing tests.
|
||||
class TestRunWithTestFailures
|
||||
: public TestRun
|
||||
{
|
||||
public:
|
||||
//! Constructs the client facing representation of a given test target's run.
|
||||
//! @param name The name of the test target.
|
||||
//! @param commandString The command string used to execute this test target.
|
||||
//! @param startTime The start time, relative to the sequence start, that this run started.
|
||||
//! Constructs the test run from the specified test target executaion data.
|
||||
//! @param name The name of the test target for this run.
|
||||
//! @param commandString The command string used to execute the test target for this run.
|
||||
//! @param startTime The start time, offset from the sequence start time, that this test run started.
|
||||
//! @param duration The duration that this test run took to complete.
|
||||
//! @param result The result of the run.
|
||||
//! @param testFailures The failing tests for this test run.
|
||||
TestRunWithTestFailures(
|
||||
//! @param result The result of this test run.
|
||||
//! @param tests The tests contained in the test target for this test run.
|
||||
CompletedTestRun(
|
||||
const AZStd::string& name,
|
||||
const AZStd::string& commandString,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
AZStd::chrono::milliseconds duration,
|
||||
TestRunResult result,
|
||||
AZStd::vector<TestCaseFailure>&& testFailures);
|
||||
AZStd::vector<Test>&& tests);
|
||||
|
||||
//! Constructs the client facing representation of a given test target's run.
|
||||
//! @param testRun The test run this run is to be derived from.
|
||||
//! @param testFailures The failing tests for this run.
|
||||
TestRunWithTestFailures(TestRun&& testRun, AZStd::vector<TestCaseFailure>&& testFailures);
|
||||
//! Constructs the test run from the specified test target executaion data.
|
||||
CompletedTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests);
|
||||
|
||||
//! Returns the total number of failing tests in this run.
|
||||
size_t GetNumTestFailures() const;
|
||||
//! Returns the total number of tests in the run.
|
||||
size_t GetTotalNumTests() const;
|
||||
|
||||
//! Returns the test cases in this run containing failing tests.
|
||||
const AZStd::vector<TestCaseFailure>& GetTestCaseFailures() const;
|
||||
//! Returns the total number of passing tests in the run.
|
||||
size_t GetTotalNumPassingTests() const;
|
||||
|
||||
//! Returns the total number of failing tests in the run.
|
||||
size_t GetTotalNumFailingTests() const;
|
||||
|
||||
//! Returns the total number of disabled tests in the run.
|
||||
size_t GetTotalNumDisabledTests() const;
|
||||
|
||||
//! Returns the tests in the run.
|
||||
const AZStd::vector<Test>& GetTests() const;
|
||||
|
||||
private:
|
||||
AZStd::vector<TestCaseFailure> m_testCaseFailures;
|
||||
size_t m_numTestFailures = 0;
|
||||
AZStd::vector<Test> m_tests;
|
||||
size_t m_totalNumPassingTests = 0;
|
||||
size_t m_totalNumFailingTests = 0;
|
||||
size_t m_totalNumDisabledTests = 0;
|
||||
};
|
||||
|
||||
//! Representation of a test run that completed with no test failures.
|
||||
class PassingTestRun
|
||||
: public CompletedTestRun
|
||||
{
|
||||
public:
|
||||
using CompletedTestRun::CompletedTestRun;
|
||||
PassingTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests);
|
||||
};
|
||||
|
||||
//! Representation of a test run that completed with one or more test failures.
|
||||
class FailingTestRun
|
||||
: public CompletedTestRun
|
||||
{
|
||||
public:
|
||||
using CompletedTestRun::CompletedTestRun;
|
||||
FailingTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests);
|
||||
};
|
||||
} // namespace Client
|
||||
} // namespace TestImpact
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ namespace TestImpact
|
||||
{
|
||||
RepoPath m_root; //!< Path to the persistent workspace tracked by the repository.
|
||||
RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache.
|
||||
AZStd::array<RepoPath, 3> m_sparTIAFiles; //!< Paths to the test impact analysis data files for each test suite.
|
||||
AZStd::array<RepoPath, 3> m_sparTiaFiles; //!< Paths to the test impact analysis data files for each test suite.
|
||||
};
|
||||
|
||||
Temp m_temp;
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
namespace Policy
|
||||
{
|
||||
//! Policy for handling of test targets that fail to execute (e.g. due to the binary not being found).
|
||||
//! @note Test targets that fail to execute will be tagged such that their execution can be attempted at a later date. This is
|
||||
//! important as otherwise it would be erroneously assumed that they cover no sources due to having no entries in the dynamic
|
||||
//! dependency map.
|
||||
enum class ExecutionFailure : AZ::u8
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report a failure.
|
||||
Continue, //!< Continue the test sequence but treat the execution failures as test failures after the run.
|
||||
Ignore //!< Continue the test sequence and ignore the execution failures.
|
||||
};
|
||||
|
||||
//! Policy for handling the coverage data of failed tests targets (both tests that failed to execute and tests that ran but failed).
|
||||
enum class FailedTestCoverage : AZ::u8
|
||||
{
|
||||
Discard, //!< Discard the coverage data produced by the failing tests, causing them to be drafted into future test runs.
|
||||
Keep //!< Keep any existing coverage data and update the coverage data for failed test targets that produce coverage.
|
||||
};
|
||||
|
||||
//! Policy for prioritizing selected tests.
|
||||
enum class TestPrioritization : AZ::u8
|
||||
{
|
||||
None, //!< Do not attempt any test prioritization.
|
||||
DependencyLocality //!< Prioritize test targets according to the locality of the production targets they cover in the build
|
||||
//!< dependency graph.
|
||||
};
|
||||
|
||||
//! Policy for handling test targets that report failing tests.
|
||||
enum class TestFailure : AZ::u8
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report the test failure.
|
||||
Continue //!< Continue the test sequence and report the test failures after the run.
|
||||
};
|
||||
|
||||
//! Policy for handling integrity failures of the dynamic dependency map and the source to target mappings.
|
||||
enum class IntegrityFailure : AZ::u8
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report the test failure.
|
||||
Continue //!< Continue the test sequence and report the test failures after the run.
|
||||
};
|
||||
|
||||
//! Policy for updating the dynamic dependency map with the coverage data of produced by test sequences.
|
||||
enum class DynamicDependencyMap : AZ::u8
|
||||
{
|
||||
Discard, //!< Discard the coverage data produced by test sequences.
|
||||
Update //!< Update the dynamic dependency map with the coverage data produced by test sequences.
|
||||
};
|
||||
|
||||
//! Policy for sharding test targets that have been marked for test sharding.
|
||||
enum class TestSharding : AZ::u8
|
||||
{
|
||||
Never, //!< Do not shard any test targets.
|
||||
Always //!< Shard all test targets that have been marked for test sharding.
|
||||
};
|
||||
|
||||
//! Standard output capture of test target runs.
|
||||
enum class TargetOutputCapture : AZ::u8
|
||||
{
|
||||
None, //!< Do not capture any output.
|
||||
StdOut, //!< Send captured output to standard output
|
||||
File, //!< Write captured output to file.
|
||||
StdOutAndFile //!< Send captured output to standard output and write to file.
|
||||
};
|
||||
|
||||
} // namespace Policy
|
||||
} // namespace TestImpact
|
||||
+23
-7
@@ -78,7 +78,7 @@ namespace TestImpact
|
||||
//! @param testRunMeta The test that has completed.
|
||||
//! @param numTestRunsCompleted The number of test runs that have completed.
|
||||
//! @param totalNumTestRuns The total number of test runs in the sequence.
|
||||
using TestRunCompleteCallback = AZStd::function<void(Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns)>;
|
||||
using TestRunCompleteCallback = AZStd::function<void(Client::TestRunBase& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns)>;
|
||||
|
||||
//! The API exposed to the client responsible for all test runs and persistent data management.
|
||||
class Runtime
|
||||
@@ -86,6 +86,7 @@ namespace TestImpact
|
||||
public:
|
||||
//! Constructs a runtime with the specified configuration and policies.
|
||||
//! @param config The configuration used for this runtime instance.
|
||||
//! @param dataFile The optional data file to be used instead of that specified in the config file.
|
||||
//! @param suiteFilter The test suite for which the coverage data and test selection will draw from.
|
||||
//! @param executionFailurePolicy Determines how to handle test targets that fail to execute.
|
||||
//! @param executionFailureDraftingPolicy Determines how test targets that previously failed to execute are drafted into subsequent test sequences.
|
||||
@@ -94,6 +95,7 @@ namespace TestImpact
|
||||
//! @param testShardingPolicy Determines how to handle test targets that have opted in to test sharding.
|
||||
Runtime(
|
||||
RuntimeConfig&& config,
|
||||
AZStd::optional<RepoPath> dataFile,
|
||||
SuiteType suiteFilter,
|
||||
Policy::ExecutionFailure executionFailurePolicy,
|
||||
Policy::FailedTestCoverage failedTestCoveragePolicy,
|
||||
@@ -112,11 +114,11 @@ namespace TestImpact
|
||||
//! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed.
|
||||
//! @param testRunCompleteCallback The client function to be called after an individual test run has completed.
|
||||
//! @returns The test run and sequence report for the selected test sequence.
|
||||
Client::SequenceReport RegularTestSequence(
|
||||
Client::RegularSequenceReport RegularTestSequence(
|
||||
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
|
||||
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
|
||||
AZStd::optional<TestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SequenceReport>> testSequenceCompleteCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::RegularSequenceReport>> testSequenceCompleteCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testRunCompleteCallback);
|
||||
|
||||
//! Runs a test sequence where tests are selected according to test impact analysis so long as they are not on the excluded list.
|
||||
@@ -164,11 +166,11 @@ namespace TestImpact
|
||||
//! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed.
|
||||
//! @param testRunCompleteCallback The client function to be called after an individual test run has completed.
|
||||
//! @returns The test run and sequence report for the selected test sequence.
|
||||
Client::SequenceReport SeededTestSequence(
|
||||
Client::SeedSequenceReport SeededTestSequence(
|
||||
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
|
||||
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
|
||||
AZStd::optional<TestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SequenceReport>> testSequenceCompleteCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SeedSequenceReport>> testSequenceCompleteCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testRunCompleteCallback);
|
||||
|
||||
//! Returns true if the runtime has test impact analysis data (either preexisting or generated).
|
||||
@@ -184,7 +186,7 @@ namespace TestImpact
|
||||
//! @param changeList The change list for which the covering tests and enumeration cache updates will be generated for.
|
||||
//! @param testPrioritizationPolicy The test prioritization strategy to use for the selected test targets.
|
||||
//! @returns The pair of selected test targets and discarded test targets.
|
||||
AZStd::pair<AZStd::vector<const TestTarget*>, AZStd::vector<const TestTarget*>> SelectCoveringTestTargetsAndUpdateEnumerationCache(
|
||||
AZStd::pair<AZStd::vector<const TestTarget*>, AZStd::vector<const TestTarget*>> SelectCoveringTestTargets(
|
||||
const ChangeList& changeList,
|
||||
Policy::TestPrioritization testPrioritizationPolicy);
|
||||
|
||||
@@ -204,8 +206,22 @@ namespace TestImpact
|
||||
//! Updates the dynamic dependency map and serializes the entire map to disk.
|
||||
void UpdateAndSerializeDynamicDependencyMap(const AZStd::vector<TestEngineInstrumentedRun>& jobs);
|
||||
|
||||
//! Generates a base policy state for the current runtime policy runtime configuration.
|
||||
PolicyStateBase GeneratePolicyStateBase() const;
|
||||
|
||||
//! Generates a regular/seed sequence policy state for the current runtime policy runtime configuration.
|
||||
SequencePolicyState GenerateSequencePolicyState() const;
|
||||
|
||||
//! Generates a safe impact analysis sequence policy state for the current runtime policy runtime configuration.
|
||||
SafeImpactAnalysisSequencePolicyState GenerateSafeImpactAnalysisSequencePolicyState(
|
||||
Policy::TestPrioritization testPrioritizationPolicy) const;
|
||||
|
||||
//! Generates an impact analysis sequence policy state for the current runtime policy runtime configuration.
|
||||
ImpactAnalysisSequencePolicyState GenerateImpactAnalysisSequencePolicyState(
|
||||
Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy) const;
|
||||
|
||||
RuntimeConfig m_config;
|
||||
RepoPath m_sparTIAFile;
|
||||
RepoPath m_sparTiaFile;
|
||||
SuiteType m_suiteFilter;
|
||||
Policy::ExecutionFailure m_executionFailurePolicy;
|
||||
Policy::FailedTestCoverage m_failedTestCoveragePolicy;
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <TestImpactFramework/TestImpactException.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
//! Exception for sequence report operations.
|
||||
class SequenceReportException
|
||||
: public Exception
|
||||
{
|
||||
public:
|
||||
using Exception::Exception;
|
||||
};
|
||||
} // namespace TestImpact
|
||||
+33
-81
@@ -9,76 +9,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <TestImpactFramework/TestImpactRuntimeException.h>
|
||||
#include <TestImpactFramework/TestImpactPolicy.h>
|
||||
|
||||
#include <AzCore/std/containers/array.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
namespace Policy
|
||||
{
|
||||
//! Policy for handling of test targets that fail to execute (e.g. due to the binary not being found).
|
||||
//! @note Test targets that fail to execute will be tagged such that their execution can be attempted at a later date. This is
|
||||
//! important as otherwise it would be erroneously assumed that they cover no sources due to having no entries in the dynamic
|
||||
//! dependency map.
|
||||
enum class ExecutionFailure
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report a failure.
|
||||
Continue, //!< Continue the test sequence but treat the execution failures as test failures after the run.
|
||||
Ignore //!< Continue the test sequence and ignore the execution failures.
|
||||
};
|
||||
|
||||
//! Policy for handling the coverage data of failed tests targets (both test that failed to execute and tests that ran but failed).
|
||||
enum class FailedTestCoverage
|
||||
{
|
||||
Discard, //!< Discard the coverage data produced by the failing tests, causing them to be drafted into future test runs.
|
||||
Keep //!< Keep any existing coverage data and update the coverage data for failed test targetss that produce coverage.
|
||||
};
|
||||
|
||||
//! Policy for prioritizing selected tests.
|
||||
enum class TestPrioritization
|
||||
{
|
||||
None, //!< Do not attempt any test prioritization.
|
||||
DependencyLocality //!< Prioritize test targets according to the locality of the production targets they cover in the build dependency graph.
|
||||
};
|
||||
|
||||
//! Policy for handling test targets that report failing tests.
|
||||
enum class TestFailure
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report the test failure.
|
||||
Continue //!< Continue the test sequence and report the test failures after the run.
|
||||
};
|
||||
|
||||
//! Policy for handling integrity failures of the dynamic dependency map and the source to target mappings.
|
||||
enum class IntegrityFailure
|
||||
{
|
||||
Abort, //!< Abort the test sequence and report the test failure.
|
||||
Continue //!< Continue the test sequence and report the test failures after the run.
|
||||
};
|
||||
|
||||
//! Policy for updating the dynamic dependency map with the coverage data of produced by test sequences.
|
||||
enum class DynamicDependencyMap
|
||||
{
|
||||
Discard, //!< Discard the coverage data produced by test sequences.
|
||||
Update //!< Update the dynamic dependency map with the coverage data produced by test sequences.
|
||||
};
|
||||
|
||||
//! Policy for sharding test targets that have been marked for test sharding.
|
||||
enum class TestSharding
|
||||
{
|
||||
Never, //!< Do not shard any test targets.
|
||||
Always //!< Shard all test targets that have been marked for test sharding.
|
||||
};
|
||||
|
||||
//! Standard output capture of test target runs.
|
||||
enum class TargetOutputCapture
|
||||
{
|
||||
None, //!< Do not capture any output.
|
||||
StdOut, //!< Send captured output to standard output
|
||||
File, //!< Write captured output to file.
|
||||
StdOutAndFile //!< Send captured output to standard output and write to file.
|
||||
};
|
||||
}
|
||||
|
||||
//! Configuration for test targets that opt in to test sharding.
|
||||
enum class ShardConfiguration
|
||||
{
|
||||
@@ -97,22 +33,6 @@ namespace TestImpact
|
||||
Sandbox
|
||||
};
|
||||
|
||||
//! User-friendly names for the test suite types.
|
||||
inline AZStd::string GetSuiteTypeName(SuiteType suiteType)
|
||||
{
|
||||
switch (suiteType)
|
||||
{
|
||||
case SuiteType::Main:
|
||||
return "main";
|
||||
case SuiteType::Periodic:
|
||||
return "periodic";
|
||||
case SuiteType::Sandbox:
|
||||
return "sandbox";
|
||||
default:
|
||||
throw(RuntimeException("Unexpected suite type"));
|
||||
}
|
||||
}
|
||||
|
||||
//! Result of a test sequence that was run.
|
||||
enum class TestSequenceResult
|
||||
{
|
||||
@@ -120,4 +40,36 @@ namespace TestImpact
|
||||
Failure, //!< One or more tests failed and/or timed out and/or failed to launch and/or an integrity failure was encountered.
|
||||
Timeout //!< The global timeout for the sequence was exceeded.
|
||||
};
|
||||
|
||||
//! Base representation of runtime policies.
|
||||
struct PolicyStateBase
|
||||
{
|
||||
Policy::ExecutionFailure m_executionFailurePolicy = Policy::ExecutionFailure::Continue;
|
||||
Policy::FailedTestCoverage m_failedTestCoveragePolicy = Policy::FailedTestCoverage::Keep;
|
||||
Policy::TestFailure m_testFailurePolicy = Policy::TestFailure::Abort;
|
||||
Policy::IntegrityFailure m_integrityFailurePolicy = Policy::IntegrityFailure::Abort;
|
||||
Policy::TestSharding m_testShardingPolicy = Policy::TestSharding::Never;
|
||||
Policy::TargetOutputCapture m_targetOutputCapture = Policy::TargetOutputCapture::None;
|
||||
};
|
||||
|
||||
//! Representation of regular and seed sequence policies.
|
||||
struct SequencePolicyState
|
||||
{
|
||||
PolicyStateBase m_basePolicies;
|
||||
};
|
||||
|
||||
//! Representation of impact analysis sequence policies.
|
||||
struct ImpactAnalysisSequencePolicyState
|
||||
{
|
||||
PolicyStateBase m_basePolicies;
|
||||
Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None;
|
||||
Policy::DynamicDependencyMap m_dynamicDependencyMap = Policy::DynamicDependencyMap::Update;
|
||||
};
|
||||
|
||||
//! Representation of safe impact analysis sequence policies.
|
||||
struct SafeImpactAnalysisSequencePolicyState
|
||||
{
|
||||
PolicyStateBase m_basePolicies;
|
||||
Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None;
|
||||
};
|
||||
} // namespace TestImpact
|
||||
|
||||
+45
-20
@@ -6,12 +6,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactException.h>
|
||||
#include <TestImpactFramework/TestImpactRuntime.h>
|
||||
#include <TestImpactFramework/TestImpactRepoPath.h>
|
||||
#include <TestImpactFramework/TestImpactTestSequence.h>
|
||||
#include <TestImpactFramework/TestImpactClientSequenceReport.h>
|
||||
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -59,23 +59,48 @@ namespace TestImpact
|
||||
//! Delete the files that match the pattern from the specified directory.
|
||||
//! @param path The path to the directory to pattern match the files for deletion.
|
||||
//! @param pattern The pattern to match files for deletion.
|
||||
inline void DeleteFiles(const RepoPath& path, const AZStd::string& pattern)
|
||||
{
|
||||
AZ::IO::SystemFile::FindFiles(AZStd::string::format("%s/%s", path.c_str(), pattern.c_str()).c_str(),
|
||||
[&path](const char* file, bool isFile)
|
||||
{
|
||||
if (isFile)
|
||||
{
|
||||
AZ::IO::SystemFile::Delete(AZStd::string::format("%s/%s", path.c_str(), file).c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
//! @return The number of files that were deleted.
|
||||
size_t DeleteFiles(const RepoPath& path, const AZStd::string& pattern);
|
||||
|
||||
//! Deletes the specified file.
|
||||
inline void DeleteFile(const RepoPath& file)
|
||||
{
|
||||
DeleteFiles(file.ParentPath(), file.Filename().Native());
|
||||
}
|
||||
void DeleteFile(const RepoPath& file);
|
||||
|
||||
//! User-friendly names for the test suite types.
|
||||
AZStd::string SuiteTypeAsString(SuiteType suiteType);
|
||||
|
||||
//! User-friendly names for the sequence report types.
|
||||
AZStd::string SequenceReportTypeAsString(Client::SequenceReportType type);
|
||||
|
||||
//! User-friendly names for the sequence result types.
|
||||
AZStd::string TestSequenceResultAsString(TestSequenceResult result);
|
||||
|
||||
//! User-friendly names for the test run result types.
|
||||
AZStd::string TestRunResultAsString(Client::TestRunResult result);
|
||||
|
||||
//! User-friendly names for the execution failure policy types.
|
||||
AZStd::string ExecutionFailurePolicyAsString(Policy::ExecutionFailure executionFailurePolicy);
|
||||
|
||||
//! User-friendly names for the failed test coverage policy types.
|
||||
AZStd::string FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage failedTestCoveragePolicy);
|
||||
|
||||
//! User-friendly names for the test prioritization policy types.
|
||||
AZStd::string TestPrioritizationPolicyAsString(Policy::TestPrioritization testPrioritizationPolicy);
|
||||
|
||||
//! User-friendly names for the test failure policy types.
|
||||
AZStd::string TestFailurePolicyAsString(Policy::TestFailure testFailurePolicy);
|
||||
|
||||
//! User-friendly names for the integrity failure policy types.
|
||||
AZStd::string IntegrityFailurePolicyAsString(Policy::IntegrityFailure integrityFailurePolicy);
|
||||
|
||||
//! User-friendly names for the dynamic dependency map policy types.
|
||||
AZStd::string DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap dynamicDependencyMapPolicy);
|
||||
|
||||
//! User-friendly names for the test sharding policy types.
|
||||
AZStd::string TestShardingPolicyAsString(Policy::TestSharding testShardingPolicy);
|
||||
|
||||
//! User-friendly names for the target output capture policy types.
|
||||
AZStd::string TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture targetOutputCapturePolicy);
|
||||
|
||||
//! User-friendly names for the client test result types.
|
||||
AZStd::string ClientTestResultAsString(Client::TestResult result);
|
||||
} // namespace TestImpact
|
||||
+3
-1
@@ -6,6 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <Artifact/Factory/TestImpactTestTargetMetaMapFactory.h>
|
||||
#include <Artifact/TestImpactArtifactException.h>
|
||||
|
||||
@@ -67,7 +69,7 @@ namespace TestImpact
|
||||
{
|
||||
// Check to see if this test target has the suite we're looking for
|
||||
if (const auto suiteName = suite[Keys[SuiteKey]].GetString();
|
||||
strcmp(GetSuiteTypeName(suiteType).c_str(), suiteName) == 0)
|
||||
strcmp(SuiteTypeAsString(suiteType).c_str(), suiteName) == 0)
|
||||
{
|
||||
testMeta.m_suite = suiteName;
|
||||
testMeta.m_customArgs = suite[Keys[CommandKey]].GetString();
|
||||
|
||||
-2
@@ -156,8 +156,6 @@ namespace TestImpact
|
||||
{
|
||||
coveringTestTargetIt->second.erase(source);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 2.
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <TestImpactFramework/TestImpactChangeList.h>
|
||||
#include <TestImpactFramework/TestImpactTestSequence.h>
|
||||
#include <TestImpactFramework/TestImpactPolicy.h>
|
||||
|
||||
#include <Artifact/Static/TestImpactProductionTargetDescriptor.h>
|
||||
#include <Artifact/Static/TestImpactTestTargetDescriptor.h>
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <TestImpactFramework/TestImpactTestSequence.h>
|
||||
#include <TestImpactFramework/TestImpactPolicy.h>
|
||||
|
||||
#include <Artifact/Static/TestImpactDependencyGraphData.h>
|
||||
#include <Dependency/TestImpactChangeDependencyList.h>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <Artifact/Factory/TestImpactTestEnumerationSuiteFactory.h>
|
||||
#include <TestEngine/TestImpactTestEngineException.h>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <Artifact/Factory/TestImpactModuleCoverageFactory.h>
|
||||
#include <Artifact/Factory/TestImpactTestRunSuiteFactory.h>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <Artifact/Factory/TestImpactTestRunSuiteFactory.h>
|
||||
#include <TestEngine/TestImpactTestEngineException.h>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <Target/TestImpactTestTarget.h>
|
||||
#include <TestEngine/TestImpactTestEngineException.h>
|
||||
|
||||
+169
-155
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
@@ -11,7 +12,6 @@ namespace TestImpact
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
//! Calculates the final sequence result for a composite of multiple sequences.
|
||||
TestSequenceResult CalculateMultiTestSequenceResult(const AZStd::vector<TestSequenceResult>& results)
|
||||
{
|
||||
// Order of precedence:
|
||||
@@ -19,14 +19,12 @@ namespace TestImpact
|
||||
// 2. TestSequenceResult::Timeout
|
||||
// 3. TestSequenceResult::Success
|
||||
|
||||
if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Failure);
|
||||
it != results.end())
|
||||
if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Failure); it != results.end())
|
||||
{
|
||||
return TestSequenceResult::Failure;
|
||||
}
|
||||
|
||||
if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Timeout);
|
||||
it != results.end())
|
||||
|
||||
if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Timeout); it != results.end())
|
||||
{
|
||||
return TestSequenceResult::Timeout;
|
||||
}
|
||||
@@ -38,20 +36,32 @@ namespace TestImpact
|
||||
TestSequenceResult result,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
AZStd::chrono::milliseconds duration,
|
||||
AZStd::vector<TestRun>&& passingTests,
|
||||
AZStd::vector<TestRunWithTestFailures>&& failingTests,
|
||||
AZStd::vector<TestRun>&& executionFailureTests,
|
||||
AZStd::vector<TestRun>&& timedOutTests,
|
||||
AZStd::vector<TestRun>&& unexecutedTests)
|
||||
AZStd::vector<PassingTestRun>&& passingTestRuns,
|
||||
AZStd::vector<FailingTestRun>&& failingTestRuns,
|
||||
AZStd::vector<TestRunWithExecutionFailure>&& executionFailureTestRuns,
|
||||
AZStd::vector<TimedOutTestRun>&& timedOutTestRuns,
|
||||
AZStd::vector<UnexecutedTestRun>&& unexecutedTestRuns)
|
||||
: m_startTime(startTime)
|
||||
, m_result(result)
|
||||
, m_duration(duration)
|
||||
, m_passingTests(AZStd::move(passingTests))
|
||||
, m_failingTests(AZStd::move(failingTests))
|
||||
, m_executionFailureTests(AZStd::move(executionFailureTests))
|
||||
, m_timedOutTests(AZStd::move(timedOutTests))
|
||||
, m_unexecutedTests(AZStd::move(unexecutedTests))
|
||||
, m_passingTestRuns(AZStd::move(passingTestRuns))
|
||||
, m_failingTestRuns(AZStd::move(failingTestRuns))
|
||||
, m_executionFailureTestRuns(AZStd::move(executionFailureTestRuns))
|
||||
, m_timedOutTestRuns(AZStd::move(timedOutTestRuns))
|
||||
, m_unexecutedTestRuns(AZStd::move(unexecutedTestRuns))
|
||||
{
|
||||
for (const auto& failingTestRun : m_failingTestRuns)
|
||||
{
|
||||
m_totalNumPassingTests += failingTestRun.GetTotalNumPassingTests();
|
||||
m_totalNumFailingTests += failingTestRun.GetTotalNumFailingTests();
|
||||
m_totalNumDisabledTests += failingTestRun.GetTotalNumDisabledTests();
|
||||
}
|
||||
|
||||
for (const auto& passingTestRun : m_passingTestRuns)
|
||||
{
|
||||
m_totalNumPassingTests += passingTestRun.GetTotalNumPassingTests();
|
||||
m_totalNumDisabledTests += passingTestRun.GetTotalNumDisabledTests();
|
||||
}
|
||||
}
|
||||
|
||||
TestSequenceResult TestRunReport::GetResult() const
|
||||
@@ -74,234 +84,238 @@ namespace TestImpact
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
size_t TestRunReport::GetNumPassingTests() const
|
||||
size_t TestRunReport::GetTotalNumTestRuns() const
|
||||
{
|
||||
return m_passingTests.size();
|
||||
return
|
||||
GetNumPassingTestRuns() +
|
||||
GetNumFailingTestRuns() +
|
||||
GetNumExecutionFailureTestRuns() +
|
||||
GetNumTimedOutTestRuns() +
|
||||
GetNumUnexecutedTestRuns();
|
||||
}
|
||||
|
||||
size_t TestRunReport::GetNumFailingTests() const
|
||||
size_t TestRunReport::GetNumPassingTestRuns() const
|
||||
{
|
||||
return m_failingTests.size();
|
||||
return m_passingTestRuns.size();
|
||||
}
|
||||
|
||||
size_t TestRunReport::GetNumTimedOutTests() const
|
||||
size_t TestRunReport::GetNumFailingTestRuns() const
|
||||
{
|
||||
return m_timedOutTests.size();
|
||||
return m_failingTestRuns.size();
|
||||
}
|
||||
|
||||
size_t TestRunReport::GetNumUnexecutedTests() const
|
||||
size_t TestRunReport::GetNumExecutionFailureTestRuns() const
|
||||
{
|
||||
return m_unexecutedTests.size();
|
||||
return m_executionFailureTestRuns.size();
|
||||
}
|
||||
|
||||
const AZStd::vector<TestRun>& TestRunReport::GetPassingTests() const
|
||||
size_t TestRunReport::TestRunReport::GetNumTimedOutTestRuns() const
|
||||
{
|
||||
return m_passingTests;
|
||||
return m_timedOutTestRuns.size();
|
||||
}
|
||||
|
||||
const AZStd::vector<TestRunWithTestFailures>& TestRunReport::GetFailingTests() const
|
||||
size_t TestRunReport::GetNumUnexecutedTestRuns() const
|
||||
{
|
||||
return m_failingTests;
|
||||
return m_unexecutedTestRuns.size();
|
||||
}
|
||||
|
||||
const AZStd::vector<TestRun>& TestRunReport::GetExecutionFailureTests() const
|
||||
const AZStd::vector<PassingTestRun>& TestRunReport::GetPassingTestRuns() const
|
||||
{
|
||||
return m_executionFailureTests;
|
||||
return m_passingTestRuns;
|
||||
}
|
||||
|
||||
const AZStd::vector<TestRun>& TestRunReport::GetTimedOutTests() const
|
||||
const AZStd::vector<FailingTestRun>& TestRunReport::GetFailingTestRuns() const
|
||||
{
|
||||
return m_timedOutTests;
|
||||
return m_failingTestRuns;
|
||||
}
|
||||
|
||||
const AZStd::vector<TestRun>& TestRunReport::GetUnexecutedTests() const
|
||||
const AZStd::vector<TestRunWithExecutionFailure>& TestRunReport::GetExecutionFailureTestRuns() const
|
||||
{
|
||||
return m_unexecutedTests;
|
||||
return m_executionFailureTestRuns;
|
||||
}
|
||||
|
||||
SequenceReport::SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport)
|
||||
: m_suite(suiteType)
|
||||
, m_selectedTests(selectedTests)
|
||||
, m_selectedTestRunReport(AZStd::move(selectedTestRunReport))
|
||||
const AZStd::vector<TimedOutTestRun>& TestRunReport::GetTimedOutTestRuns() const
|
||||
{
|
||||
return m_timedOutTestRuns;
|
||||
}
|
||||
|
||||
TestSequenceResult SequenceReport::GetResult() const
|
||||
const AZStd::vector<UnexecutedTestRun>& TestRunReport::GetUnexecutedTestRuns() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetResult();
|
||||
return m_unexecutedTestRuns;
|
||||
}
|
||||
|
||||
AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetStartTime() const
|
||||
size_t TestRunReport::GetTotalNumPassingTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetStartTime();
|
||||
return m_totalNumPassingTests;
|
||||
}
|
||||
|
||||
AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetEndTime() const
|
||||
size_t TestRunReport::GetTotalNumFailingTests() const
|
||||
{
|
||||
return GetStartTime() + GetDuration();
|
||||
return m_totalNumFailingTests;
|
||||
}
|
||||
|
||||
AZStd::chrono::milliseconds SequenceReport::GetDuration() const
|
||||
size_t TestRunReport::GetTotalNumDisabledTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetDuration();
|
||||
return m_totalNumDisabledTests;
|
||||
}
|
||||
|
||||
TestRunSelection SequenceReport::GetSelectedTests() const
|
||||
{
|
||||
return m_selectedTests;
|
||||
}
|
||||
|
||||
TestRunReport SequenceReport::GetSelectedTestRunReport() const
|
||||
{
|
||||
return m_selectedTestRunReport;
|
||||
}
|
||||
|
||||
size_t SequenceReport::GetTotalNumPassingTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumPassingTests();
|
||||
}
|
||||
|
||||
size_t SequenceReport::GetTotalNumFailingTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumFailingTests();
|
||||
}
|
||||
|
||||
size_t SequenceReport::GetTotalNumTimedOutTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumTimedOutTests();
|
||||
}
|
||||
|
||||
size_t SequenceReport::GetTotalNumUnexecutedTests() const
|
||||
{
|
||||
return m_selectedTestRunReport.GetNumUnexecutedTests();
|
||||
}
|
||||
|
||||
DraftingSequenceReport::DraftingSequenceReport(
|
||||
RegularSequenceReport::RegularSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport)
|
||||
: SequenceReport(suiteType, selectedTests, AZStd::move(selectedTestRunReport))
|
||||
, m_draftedTests(draftedTests)
|
||||
, m_draftedTestRunReport(AZStd::move(draftedTestRunReport))
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport)
|
||||
: SequenceReportBase(
|
||||
SequenceReportType::RegularSequence,
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTestRuns,
|
||||
AZStd::move(selectedTestRunReport))
|
||||
{
|
||||
}
|
||||
|
||||
TestSequenceResult DraftingSequenceReport::GetResult() const
|
||||
SeedSequenceReport::SeedSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport)
|
||||
: SequenceReportBase(
|
||||
SequenceReportType::SeedSequence,
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTestRuns,
|
||||
AZStd::move(selectedTestRunReport))
|
||||
{
|
||||
return CalculateMultiTestSequenceResult({SequenceReport::GetResult(), m_draftedTestRunReport.GetResult()});
|
||||
}
|
||||
|
||||
AZStd::chrono::milliseconds DraftingSequenceReport::GetDuration() const
|
||||
{
|
||||
return SequenceReport::GetDuration() + m_draftedTestRunReport.GetDuration();
|
||||
}
|
||||
|
||||
size_t DraftingSequenceReport::GetTotalNumPassingTests() const
|
||||
{
|
||||
return SequenceReport::GetTotalNumPassingTests() + m_draftedTestRunReport.GetNumPassingTests();
|
||||
}
|
||||
|
||||
size_t DraftingSequenceReport::GetTotalNumFailingTests() const
|
||||
{
|
||||
return SequenceReport::GetTotalNumFailingTests() + m_draftedTestRunReport.GetNumFailingTests();
|
||||
}
|
||||
|
||||
size_t DraftingSequenceReport::GetTotalNumTimedOutTests() const
|
||||
{
|
||||
return SequenceReport::GetTotalNumTimedOutTests() + m_draftedTestRunReport.GetNumTimedOutTests();
|
||||
}
|
||||
|
||||
size_t DraftingSequenceReport::GetTotalNumUnexecutedTests() const
|
||||
{
|
||||
return SequenceReport::GetTotalNumUnexecutedTests() + m_draftedTestRunReport.GetNumUnexecutedTests();
|
||||
}
|
||||
|
||||
const AZStd::vector<AZStd::string>& DraftingSequenceReport::GetDraftedTests() const
|
||||
{
|
||||
return m_draftedTests;
|
||||
}
|
||||
|
||||
TestRunReport DraftingSequenceReport::GetDraftedTestRunReport() const
|
||||
{
|
||||
return m_draftedTestRunReport;
|
||||
}
|
||||
|
||||
ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const ImpactAnalysisSequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const AZStd::vector<AZStd::string>& discardedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& discardedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& draftedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport)
|
||||
: DraftingSequenceReport(
|
||||
suiteType,
|
||||
selectedTests,
|
||||
draftedTests,
|
||||
AZStd::move(selectedTestRunReport),
|
||||
AZStd::move(draftedTestRunReport))
|
||||
, m_discardedTests(discardedTests)
|
||||
: DraftingSequenceReportBase(
|
||||
SequenceReportType::ImpactAnalysisSequence,
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTestRuns,
|
||||
draftedTestRuns,
|
||||
AZStd::move(selectedTestRunReport),
|
||||
AZStd::move(draftedTestRunReport))
|
||||
, m_discardedTestRuns(discardedTestRuns)
|
||||
{
|
||||
}
|
||||
|
||||
const AZStd::vector<AZStd::string>& ImpactAnalysisSequenceReport::GetDiscardedTests() const
|
||||
const AZStd::vector<AZStd::string>& ImpactAnalysisSequenceReport::GetDiscardedTestRuns() const
|
||||
{
|
||||
return m_discardedTests;
|
||||
return m_discardedTestRuns;
|
||||
}
|
||||
|
||||
SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport(
|
||||
size_t maxConcurrency,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
const SafeImpactAnalysisSequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const TestRunSelection& selectedTests,
|
||||
const TestRunSelection& discardedTests,
|
||||
const AZStd::vector<AZStd::string>& draftedTests,
|
||||
const TestRunSelection& selectedTestRuns,
|
||||
const TestRunSelection& discardedTestRuns,
|
||||
const AZStd::vector<AZStd::string>& draftedTestRuns,
|
||||
TestRunReport&& selectedTestRunReport,
|
||||
TestRunReport&& discardedTestRunReport,
|
||||
TestRunReport&& draftedTestRunReport)
|
||||
: DraftingSequenceReport(
|
||||
suiteType,
|
||||
selectedTests,
|
||||
draftedTests,
|
||||
AZStd::move(selectedTestRunReport),
|
||||
AZStd::move(draftedTestRunReport))
|
||||
, m_discardedTests(discardedTests)
|
||||
: DraftingSequenceReportBase(
|
||||
SequenceReportType::SafeImpactAnalysisSequence,
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTestRuns,
|
||||
draftedTestRuns,
|
||||
AZStd::move(selectedTestRunReport),
|
||||
AZStd::move(draftedTestRunReport))
|
||||
, m_discardedTestRuns(discardedTestRuns)
|
||||
, m_discardedTestRunReport(AZStd::move(discardedTestRunReport))
|
||||
{
|
||||
}
|
||||
|
||||
TestSequenceResult SafeImpactAnalysisSequenceReport::GetResult() const
|
||||
{
|
||||
return CalculateMultiTestSequenceResult({ DraftingSequenceReport::GetResult(), m_discardedTestRunReport.GetResult() });
|
||||
return CalculateMultiTestSequenceResult({ DraftingSequenceReportBase::GetResult(), m_discardedTestRunReport.GetResult() });
|
||||
}
|
||||
|
||||
AZStd::chrono::milliseconds SafeImpactAnalysisSequenceReport::GetDuration() const
|
||||
{
|
||||
return DraftingSequenceReport::GetDuration() + m_discardedTestRunReport.GetDuration();
|
||||
return DraftingSequenceReportBase::GetDuration() + m_discardedTestRunReport.GetDuration();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReportBase::GetTotalNumTestRuns() + m_discardedTestRunReport.GetTotalNumTestRuns();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumPassingTests() const
|
||||
{
|
||||
return DraftingSequenceReport::GetTotalNumPassingTests() + m_discardedTestRunReport.GetNumPassingTests();
|
||||
return DraftingSequenceReportBase::GetTotalNumPassingTests() + m_discardedTestRunReport.GetTotalNumPassingTests();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumFailingTests() const
|
||||
{
|
||||
return DraftingSequenceReport::GetTotalNumFailingTests() + m_discardedTestRunReport.GetNumFailingTests();
|
||||
return DraftingSequenceReportBase::GetTotalNumFailingTests() + m_discardedTestRunReport.GetTotalNumFailingTests();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumTimedOutTests() const
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumDisabledTests() const
|
||||
{
|
||||
return DraftingSequenceReport::GetTotalNumTimedOutTests() + m_discardedTestRunReport.GetNumTimedOutTests();
|
||||
return DraftingSequenceReportBase::GetTotalNumDisabledTests() + m_discardedTestRunReport.GetTotalNumDisabledTests();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumUnexecutedTests() const
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumPassingTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReport::GetTotalNumUnexecutedTests() + m_discardedTestRunReport.GetNumUnexecutedTests();
|
||||
return DraftingSequenceReportBase::GetTotalNumPassingTestRuns() + m_discardedTestRunReport.GetNumPassingTestRuns();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumFailingTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReportBase::GetTotalNumFailingTestRuns() + m_discardedTestRunReport.GetNumFailingTestRuns();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumExecutionFailureTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReportBase::GetTotalNumExecutionFailureTestRuns() + m_discardedTestRunReport.GetNumExecutionFailureTestRuns();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumTimedOutTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReportBase::GetTotalNumTimedOutTestRuns() + m_discardedTestRunReport.GetNumTimedOutTestRuns();
|
||||
}
|
||||
|
||||
size_t SafeImpactAnalysisSequenceReport::GetTotalNumUnexecutedTestRuns() const
|
||||
{
|
||||
return DraftingSequenceReportBase::GetTotalNumUnexecutedTestRuns() + m_discardedTestRunReport.GetNumUnexecutedTestRuns();
|
||||
}
|
||||
|
||||
const TestRunSelection SafeImpactAnalysisSequenceReport::GetDiscardedTests() const
|
||||
const TestRunSelection SafeImpactAnalysisSequenceReport::GetDiscardedTestRuns() const
|
||||
{
|
||||
return m_discardedTests;
|
||||
return m_discardedTestRuns;
|
||||
}
|
||||
|
||||
TestRunReport SafeImpactAnalysisSequenceReport::GetDiscardedTestRunReport() const
|
||||
|
||||
+606
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* 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 <TestImpactFramework/TestImpactClientSequenceReportSerializer.h>
|
||||
#include <TestImpactFramework/TestImpactSequenceReportException.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/JSON/prettywriter.h>
|
||||
#include <AzCore/JSON/rapidjson.h>
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace SequenceReportFields
|
||||
{
|
||||
// Keys for pertinent JSON node and attribute names
|
||||
constexpr const char* Keys[] =
|
||||
{
|
||||
"name",
|
||||
"command_args",
|
||||
"start_time",
|
||||
"end_time",
|
||||
"duration",
|
||||
"result",
|
||||
"num_passing_tests",
|
||||
"num_failing_tests",
|
||||
"num_disabled_tests",
|
||||
"tests",
|
||||
"num_passing_test_runs",
|
||||
"num_failing_test_runs",
|
||||
"num_execution_failure_test_runs",
|
||||
"num_timed_out_test_runs",
|
||||
"num_unexecuted_test_runs",
|
||||
"passing_test_runs",
|
||||
"failing_test_runs",
|
||||
"execution_failure_test_runs",
|
||||
"timed_out_test_runs",
|
||||
"unexecuted_test_runs",
|
||||
"total_num_passing_tests",
|
||||
"total_num_failing_tests",
|
||||
"total_num_disabled_tests",
|
||||
"total_num_test_runs",
|
||||
"num_included_test_runs",
|
||||
"num_excluded_test_runs",
|
||||
"included_test_runs",
|
||||
"excluded_test_runs",
|
||||
"execution_failure",
|
||||
"coverage_failure",
|
||||
"test_failure",
|
||||
"integrity_failure",
|
||||
"test_sharding",
|
||||
"target_output_capture",
|
||||
"test_prioritization",
|
||||
"dynamic_dependency_map",
|
||||
"type",
|
||||
"test_target_timeout",
|
||||
"global_timeout",
|
||||
"max_concurrency",
|
||||
"policy",
|
||||
"suite",
|
||||
"selected_test_runs",
|
||||
"selected_test_run_report",
|
||||
"total_num_passing_test_runs",
|
||||
"total_num_failing_test_runs",
|
||||
"total_num_execution_failure_test_runs",
|
||||
"total_num_timed_out_test_runs",
|
||||
"total_num_unexecuted_test_runs",
|
||||
"drafted_test_runs",
|
||||
"drafted_test_run_report",
|
||||
"discarded_test_runs",
|
||||
"discarded_test_run_report"
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Name,
|
||||
CommandArgs,
|
||||
StartTime,
|
||||
EndTime,
|
||||
Duration,
|
||||
Result,
|
||||
NumPassingTests,
|
||||
NumFailingTests,
|
||||
NumDisabledTests,
|
||||
Tests,
|
||||
NumPassingTestRuns,
|
||||
NumFailingTestRuns,
|
||||
NumExecutionFailureTestRuns,
|
||||
NumTimedOutTestRuns,
|
||||
NumUnexecutedTestRuns,
|
||||
PassingTestRuns,
|
||||
FailingTestRuns,
|
||||
ExecutionFailureTestRuns,
|
||||
TimedOutTestRuns,
|
||||
UnexecutedTestRuns,
|
||||
TotalNumPassingTests,
|
||||
TotalNumFailingTests,
|
||||
TotalNumDisabledTests,
|
||||
TotalNumTestRuns,
|
||||
NumIncludedTestRuns,
|
||||
NumExcludedTestRuns,
|
||||
IncludedTestRuns,
|
||||
ExcludedTestRuns,
|
||||
ExecutionFailure,
|
||||
CoverageFailure,
|
||||
TestFailure,
|
||||
IntegrityFailure,
|
||||
TestSharding,
|
||||
TargetOutputCapture,
|
||||
TestPrioritization,
|
||||
DynamicDependencyMap,
|
||||
Type,
|
||||
TestTargetTimeout,
|
||||
GlobalTimeout,
|
||||
MaxConcurrency,
|
||||
Policy,
|
||||
Suite,
|
||||
SelectedTestRuns,
|
||||
SelectedTestRunReport,
|
||||
TotalNumPassingTestRuns,
|
||||
TotalNumFailingTestRuns,
|
||||
TotalNumExecutionFailureTestRuns,
|
||||
TotalNumTimedOutTestRuns,
|
||||
TotalNumUnexecutedTestRuns,
|
||||
DraftedTestRuns,
|
||||
DraftedTestRunReport,
|
||||
DiscardedTestRuns,
|
||||
DiscardedTestRunReport
|
||||
};
|
||||
} // namespace SequenceReportFields
|
||||
|
||||
AZ::u64 TimePointInMsAsInt64(AZStd::chrono::high_resolution_clock::time_point timePoint)
|
||||
{
|
||||
return AZStd::chrono::duration_cast<AZStd::chrono::milliseconds>(timePoint.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
void SerializeTestRunMembers(const Client::TestRunBase& testRun, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
// Name
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Name]);
|
||||
writer.String(testRun.GetTargetName().c_str());
|
||||
|
||||
// Command string
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::CommandArgs]);
|
||||
writer.String(testRun.GetCommandString().c_str());
|
||||
|
||||
// Start time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(testRun.GetStartTime()));
|
||||
|
||||
// End time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(testRun.GetEndTime()));
|
||||
|
||||
// Duration
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]);
|
||||
writer.Uint64(testRun.GetDuration().count());
|
||||
|
||||
// Result
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]);
|
||||
writer.String(TestRunResultAsString(testRun.GetResult()).c_str());
|
||||
}
|
||||
|
||||
void SerializeTestRun(const Client::TestRunBase& testRun, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeTestRunMembers(testRun, writer);
|
||||
}
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
void SerializeCompletedTestRun(const Client::CompletedTestRun& testRun, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeTestRunMembers(testRun, writer);
|
||||
|
||||
// Number of passing test cases
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumPassingTests]);
|
||||
writer.Uint64(testRun.GetTotalNumPassingTests());
|
||||
|
||||
// Number of failing test cases
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumFailingTests]);
|
||||
writer.Uint64(testRun.GetTotalNumFailingTests());
|
||||
|
||||
// Number of disabled test cases
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumDisabledTests]);
|
||||
writer.Uint64(testRun.GetTotalNumDisabledTests());
|
||||
|
||||
// Tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Tests]);
|
||||
writer.StartArray();
|
||||
|
||||
for (const auto& test : testRun.GetTests())
|
||||
{
|
||||
// Test
|
||||
writer.StartObject();
|
||||
|
||||
// Name
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Name]);
|
||||
writer.String(test.GetName().c_str());
|
||||
|
||||
// Result
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]);
|
||||
writer.String(ClientTestResultAsString(test.GetResult()).c_str());
|
||||
|
||||
writer.EndObject(); // Test
|
||||
}
|
||||
|
||||
writer.EndArray(); // Tests
|
||||
}
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
void SerializeTestRunReport(
|
||||
const Client::TestRunReport& testRunReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
writer.StartObject();
|
||||
{
|
||||
// Result
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]);
|
||||
writer.String(TestSequenceResultAsString(testRunReport.GetResult()).c_str());
|
||||
|
||||
// Start time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(testRunReport.GetStartTime()));
|
||||
|
||||
// End time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(testRunReport.GetEndTime()));
|
||||
|
||||
// Duration
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]);
|
||||
writer.Uint64(testRunReport.GetDuration().count());
|
||||
|
||||
// Number of passing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumPassingTestRuns]);
|
||||
writer.Uint64(testRunReport.GetNumPassingTestRuns());
|
||||
|
||||
// Number of failing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumFailingTestRuns]);
|
||||
writer.Uint64(testRunReport.GetNumFailingTestRuns());
|
||||
|
||||
// Number of test runs that failed to execute
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumExecutionFailureTestRuns]);
|
||||
writer.Uint64(testRunReport.GetNumExecutionFailureTestRuns());
|
||||
|
||||
// Number of timed out test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumTimedOutTestRuns]);
|
||||
writer.Uint64(testRunReport.GetNumTimedOutTestRuns());
|
||||
|
||||
// Number of unexecuted test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumUnexecutedTestRuns]);
|
||||
writer.Uint64(testRunReport.GetNumUnexecutedTestRuns());
|
||||
|
||||
// Passing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::PassingTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testRunReport.GetPassingTestRuns())
|
||||
{
|
||||
SerializeCompletedTestRun(testRun, writer);
|
||||
}
|
||||
writer.EndArray(); // Passing test runs
|
||||
|
||||
// Failing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::FailingTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testRunReport.GetFailingTestRuns())
|
||||
{
|
||||
SerializeCompletedTestRun(testRun, writer);
|
||||
}
|
||||
writer.EndArray(); // Failing test runs
|
||||
|
||||
// Execution failures
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExecutionFailureTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testRunReport.GetExecutionFailureTestRuns())
|
||||
{
|
||||
SerializeTestRun(testRun, writer);
|
||||
}
|
||||
writer.EndArray(); // Execution failures
|
||||
|
||||
// Timed out test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TimedOutTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testRunReport.GetTimedOutTestRuns())
|
||||
{
|
||||
SerializeTestRun(testRun, writer);
|
||||
}
|
||||
writer.EndArray(); // Timed out test runs
|
||||
|
||||
// Unexecuted test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::UnexecutedTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testRunReport.GetUnexecutedTestRuns())
|
||||
{
|
||||
SerializeTestRun(testRun, writer);
|
||||
}
|
||||
writer.EndArray(); // Unexecuted test runs
|
||||
|
||||
// Number of passing tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTests]);
|
||||
writer.Uint64(testRunReport.GetTotalNumPassingTests());
|
||||
|
||||
// Number of failing tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTests]);
|
||||
writer.Uint64(testRunReport.GetTotalNumFailingTests());
|
||||
|
||||
// Number of disabled tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumDisabledTests]);
|
||||
writer.Uint64(testRunReport.GetTotalNumDisabledTests());
|
||||
}
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
void SerializeTestSelection(
|
||||
const Client::TestRunSelection& testSelection, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
writer.StartObject();
|
||||
{
|
||||
// Total number of test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTestRuns]);
|
||||
writer.Uint64(testSelection.GetTotalNumTests());
|
||||
|
||||
// Number of included test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumIncludedTestRuns]);
|
||||
writer.Uint64(testSelection.GetNumIncludedTestRuns());
|
||||
|
||||
// Number of excluded test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumExcludedTestRuns]);
|
||||
writer.Uint64(testSelection.GetNumExcludedTestRuns());
|
||||
|
||||
// Included test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::IncludedTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testSelection.GetIncludededTestRuns())
|
||||
{
|
||||
writer.String(testRun.c_str());
|
||||
}
|
||||
writer.EndArray(); // Included test runs
|
||||
|
||||
// Excluded test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExcludedTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : testSelection.GetExcludedTestRuns())
|
||||
{
|
||||
writer.String(testRun.c_str());
|
||||
}
|
||||
writer.EndArray(); // Excluded test runs
|
||||
}
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
void SerializePolicyStateBaseMembers(const PolicyStateBase& policyState, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
// Execution failure
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExecutionFailure]);
|
||||
writer.String(ExecutionFailurePolicyAsString(policyState.m_executionFailurePolicy).c_str());
|
||||
|
||||
// Failed test coverage
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::CoverageFailure]);
|
||||
writer.String(FailedTestCoveragePolicyAsString(policyState.m_failedTestCoveragePolicy).c_str());
|
||||
|
||||
// Test failure
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestFailure]);
|
||||
writer.String(TestFailurePolicyAsString(policyState.m_testFailurePolicy).c_str());
|
||||
|
||||
// Integrity failure
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::IntegrityFailure]);
|
||||
writer.String(IntegrityFailurePolicyAsString(policyState.m_integrityFailurePolicy).c_str());
|
||||
|
||||
// Test sharding
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestSharding]);
|
||||
writer.String(TestShardingPolicyAsString(policyState.m_testShardingPolicy).c_str());
|
||||
|
||||
// Target output capture
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TargetOutputCapture]);
|
||||
writer.String(TargetOutputCapturePolicyAsString(policyState.m_targetOutputCapture).c_str());
|
||||
}
|
||||
|
||||
void SerializePolicyStateMembers(
|
||||
const SequencePolicyState& policyState, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer);
|
||||
}
|
||||
|
||||
void SerializePolicyStateMembers(
|
||||
const SafeImpactAnalysisSequencePolicyState& policyState, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer);
|
||||
|
||||
// Test prioritization
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]);
|
||||
writer.String(TestPrioritizationPolicyAsString(policyState.m_testPrioritizationPolicy).c_str());
|
||||
}
|
||||
|
||||
void SerializePolicyStateMembers(
|
||||
const ImpactAnalysisSequencePolicyState& policyState, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer);
|
||||
|
||||
// Test prioritization
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]);
|
||||
writer.String(TestPrioritizationPolicyAsString(policyState.m_testPrioritizationPolicy).c_str());
|
||||
|
||||
// Dynamic dependency map
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DynamicDependencyMap]);
|
||||
writer.String(DynamicDependencyMapPolicyAsString(policyState.m_dynamicDependencyMap).c_str());
|
||||
}
|
||||
|
||||
template<typename PolicyStateType>
|
||||
void SerializeSequenceReportBaseMembers(
|
||||
const Client::SequenceReportBase<PolicyStateType>& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
// Type
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Type]);
|
||||
writer.String(SequenceReportTypeAsString(sequenceReport.GetType()).c_str());
|
||||
|
||||
// Test target timeout
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]);
|
||||
writer.Uint64(sequenceReport.GetTestTargetTimeout().value_or(AZStd::chrono::milliseconds{0}).count());
|
||||
|
||||
// Global timeout
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::GlobalTimeout]);
|
||||
writer.Uint64(sequenceReport.GetGlobalTimeout().value_or(AZStd::chrono::milliseconds{ 0 }).count());
|
||||
|
||||
// Maximum concurrency
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::MaxConcurrency]);
|
||||
writer.Uint64(sequenceReport.GetMaxConcurrency());
|
||||
|
||||
// Policies
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Policy]);
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializePolicyStateMembers(sequenceReport.GetPolicyState(), writer);
|
||||
}
|
||||
writer.EndObject(); // Policies
|
||||
|
||||
// Suite
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Suite]);
|
||||
writer.String(SuiteTypeAsString(sequenceReport.GetSuite()).c_str());
|
||||
|
||||
// Selected test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::SelectedTestRuns]);
|
||||
SerializeTestSelection(sequenceReport.GetSelectedTestRuns(), writer);
|
||||
|
||||
// Selected test run report
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::SelectedTestRunReport]);
|
||||
SerializeTestRunReport(sequenceReport.GetSelectedTestRunReport(), writer);
|
||||
|
||||
// Start time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(sequenceReport.GetStartTime()));
|
||||
|
||||
// End time
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]);
|
||||
writer.Int64(TimePointInMsAsInt64(sequenceReport.GetEndTime()));
|
||||
|
||||
// Duration
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]);
|
||||
writer.Uint64(sequenceReport.GetDuration().count());
|
||||
|
||||
// Result
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]);
|
||||
writer.String(TestSequenceResultAsString(sequenceReport.GetResult()).c_str());
|
||||
|
||||
// Total number of test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumTestRuns());
|
||||
|
||||
// Total number of passing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumPassingTestRuns());
|
||||
|
||||
// Total number of failing test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumFailingTestRuns());
|
||||
|
||||
// Total number of test runs that failed to execute
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumExecutionFailureTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumExecutionFailureTestRuns());
|
||||
|
||||
// Total number of timed out test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTimedOutTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumTimedOutTestRuns());
|
||||
|
||||
// Total number of unexecuted test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumUnexecutedTestRuns]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumUnexecutedTestRuns());
|
||||
|
||||
// Total number of passing tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTests]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumPassingTests());
|
||||
|
||||
// Total number of failing tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTests]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumFailingTests());
|
||||
|
||||
// Total number of disabled tests
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumDisabledTests]);
|
||||
writer.Uint64(sequenceReport.GetTotalNumDisabledTests());
|
||||
}
|
||||
|
||||
template<typename PolicyStateType>
|
||||
void SerializeDraftingSequenceReportMembers(
|
||||
const Client::DraftingSequenceReportBase<PolicyStateType>& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
||||
{
|
||||
SerializeSequenceReportBaseMembers(sequenceReport, writer);
|
||||
|
||||
// Drafted test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : sequenceReport.GetDraftedTestRuns())
|
||||
{
|
||||
writer.String(testRun.c_str());
|
||||
}
|
||||
writer.EndArray(); // Drafted test runs
|
||||
|
||||
// Drafted test run report
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DraftedTestRunReport]);
|
||||
SerializeTestRunReport(sequenceReport.GetDraftedTestRunReport(), writer);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport)
|
||||
{
|
||||
rapidjson::StringBuffer stringBuffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(stringBuffer);
|
||||
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeSequenceReportBaseMembers(sequenceReport, writer);
|
||||
}
|
||||
writer.EndObject();
|
||||
|
||||
return stringBuffer.GetString();
|
||||
}
|
||||
|
||||
AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport)
|
||||
{
|
||||
rapidjson::StringBuffer stringBuffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(stringBuffer);
|
||||
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeSequenceReportBaseMembers(sequenceReport, writer);
|
||||
}
|
||||
writer.EndObject();
|
||||
|
||||
return stringBuffer.GetString();
|
||||
}
|
||||
|
||||
AZStd::string SerializeSequenceReport(const Client::ImpactAnalysisSequenceReport& sequenceReport)
|
||||
{
|
||||
rapidjson::StringBuffer stringBuffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(stringBuffer);
|
||||
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeDraftingSequenceReportMembers(sequenceReport, writer);
|
||||
|
||||
// Discarded test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]);
|
||||
writer.StartArray();
|
||||
for (const auto& testRun : sequenceReport.GetDiscardedTestRuns())
|
||||
{
|
||||
writer.String(testRun.c_str());
|
||||
}
|
||||
writer.EndArray(); // Discarded test runs
|
||||
}
|
||||
writer.EndObject();
|
||||
|
||||
return stringBuffer.GetString();
|
||||
}
|
||||
|
||||
AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport)
|
||||
{
|
||||
rapidjson::StringBuffer stringBuffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(stringBuffer);
|
||||
|
||||
writer.StartObject();
|
||||
{
|
||||
SerializeDraftingSequenceReportMembers(sequenceReport, writer);
|
||||
|
||||
// Discarded test runs
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]);
|
||||
SerializeTestSelection(sequenceReport.GetDiscardedTestRuns(), writer);
|
||||
|
||||
// Discarded test run report
|
||||
writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRunReport]);
|
||||
SerializeTestRunReport(sequenceReport.GetDiscardedTestRunReport(), writer);
|
||||
}
|
||||
writer.EndObject();
|
||||
|
||||
return stringBuffer.GetString();
|
||||
}
|
||||
} // namespace TestImpact
|
||||
@@ -8,11 +8,13 @@
|
||||
|
||||
#include <TestImpactFramework/TestImpactClientTestRun.h>
|
||||
|
||||
#include <AzCore/std/tuple.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
TestRun::TestRun(
|
||||
TestRunBase::TestRunBase(
|
||||
const AZStd::string& name,
|
||||
const AZStd::string& commandString,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
@@ -26,107 +28,145 @@ namespace TestImpact
|
||||
{
|
||||
}
|
||||
|
||||
const AZStd::string& TestRun::GetTargetName() const
|
||||
const AZStd::string& TestRunBase::GetTargetName() const
|
||||
{
|
||||
return m_targetName;
|
||||
}
|
||||
|
||||
const AZStd::string& TestRun::GetCommandString() const
|
||||
const AZStd::string& TestRunBase::GetCommandString() const
|
||||
{
|
||||
return m_commandString;
|
||||
}
|
||||
|
||||
AZStd::chrono::high_resolution_clock::time_point TestRun::GetStartTime() const
|
||||
AZStd::chrono::high_resolution_clock::time_point TestRunBase::GetStartTime() const
|
||||
{
|
||||
return m_startTime;
|
||||
}
|
||||
|
||||
AZStd::chrono::high_resolution_clock::time_point TestRun::GetEndTime() const
|
||||
AZStd::chrono::high_resolution_clock::time_point TestRunBase::GetEndTime() const
|
||||
{
|
||||
return m_startTime + m_duration;
|
||||
}
|
||||
|
||||
AZStd::chrono::milliseconds TestRun::GetDuration() const
|
||||
AZStd::chrono::milliseconds TestRunBase::GetDuration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
TestRunResult TestRun::GetResult() const
|
||||
TestRunResult TestRunBase::GetResult() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
TestFailure::TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage)
|
||||
TestRunWithExecutionFailure::TestRunWithExecutionFailure(TestRunBase&& testRun)
|
||||
: TestRunBase(AZStd::move(testRun))
|
||||
{
|
||||
}
|
||||
|
||||
TimedOutTestRun::TimedOutTestRun(TestRunBase&& testRun)
|
||||
: TestRunBase(AZStd::move(testRun))
|
||||
{
|
||||
}
|
||||
|
||||
UnexecutedTestRun::UnexecutedTestRun(TestRunBase&& testRun)
|
||||
: TestRunBase(AZStd::move(testRun))
|
||||
{
|
||||
}
|
||||
|
||||
Test::Test(const AZStd::string& testName, TestResult result)
|
||||
: m_name(testName)
|
||||
, m_errorMessage(errorMessage)
|
||||
, m_result(result)
|
||||
{
|
||||
}
|
||||
|
||||
const AZStd::string& TestFailure::GetName() const
|
||||
const AZStd::string& Test::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const AZStd::string& TestFailure::GetErrorMessage() const
|
||||
TestResult Test::GetResult() const
|
||||
{
|
||||
return m_errorMessage;
|
||||
return m_result;
|
||||
}
|
||||
|
||||
TestCaseFailure::TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector<TestFailure>&& testFailures)
|
||||
: m_name(testCaseName)
|
||||
, m_testFailures(AZStd::move(testFailures))
|
||||
AZStd::tuple<size_t, size_t, size_t> CalculateTestCaseMetrics(const AZStd::vector<Test>& tests)
|
||||
{
|
||||
}
|
||||
size_t totalNumPassingTests = 0;
|
||||
size_t totalNumFailingTests = 0;
|
||||
size_t totalNumDisabledTests = 0;
|
||||
|
||||
const AZStd::string& TestCaseFailure::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const AZStd::vector<TestFailure>& TestCaseFailure::GetTestFailures() const
|
||||
{
|
||||
return m_testFailures;
|
||||
}
|
||||
|
||||
static size_t CalculateNumTestRunFailures(const AZStd::vector<TestCaseFailure>& testFailures)
|
||||
{
|
||||
size_t numTestFailures = 0;
|
||||
for (const auto& testCase : testFailures)
|
||||
for (const auto& test : tests)
|
||||
{
|
||||
numTestFailures += testCase.GetTestFailures().size();
|
||||
if (test.GetResult() == Client::TestResult::Passed)
|
||||
{
|
||||
totalNumPassingTests++;
|
||||
}
|
||||
else if (test.GetResult() == Client::TestResult::Failed)
|
||||
{
|
||||
totalNumFailingTests++;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalNumDisabledTests++;
|
||||
}
|
||||
}
|
||||
|
||||
return numTestFailures;
|
||||
return { totalNumPassingTests, totalNumFailingTests, totalNumDisabledTests };
|
||||
}
|
||||
|
||||
TestRunWithTestFailures::TestRunWithTestFailures(
|
||||
CompletedTestRun::CompletedTestRun(
|
||||
const AZStd::string& name,
|
||||
const AZStd::string& commandString,
|
||||
AZStd::chrono::high_resolution_clock::time_point startTime,
|
||||
AZStd::chrono::milliseconds duration,
|
||||
TestRunResult result,
|
||||
AZStd::vector<TestCaseFailure>&& testFailures)
|
||||
: TestRun(name, commandString, startTime, duration, result)
|
||||
, m_testCaseFailures(AZStd::move(testFailures))
|
||||
AZStd::vector<Test>&& tests)
|
||||
: TestRunBase(name, commandString, startTime, duration, result)
|
||||
, m_tests(AZStd::move(tests))
|
||||
{
|
||||
m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures);
|
||||
AZStd::tie(m_totalNumPassingTests, m_totalNumFailingTests, m_totalNumDisabledTests) = CalculateTestCaseMetrics(m_tests);
|
||||
}
|
||||
|
||||
TestRunWithTestFailures::TestRunWithTestFailures(TestRun&& testRun, AZStd::vector<TestCaseFailure>&& testFailures)
|
||||
: TestRun(AZStd::move(testRun))
|
||||
, m_testCaseFailures(AZStd::move(testFailures))
|
||||
CompletedTestRun::CompletedTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests)
|
||||
: TestRunBase(AZStd::move(testRun))
|
||||
, m_tests(AZStd::move(tests))
|
||||
{
|
||||
m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures);
|
||||
AZStd::tie(m_totalNumPassingTests, m_totalNumFailingTests, m_totalNumDisabledTests) = CalculateTestCaseMetrics(m_tests);
|
||||
}
|
||||
|
||||
size_t TestRunWithTestFailures::GetNumTestFailures() const
|
||||
size_t CompletedTestRun::GetTotalNumTests() const
|
||||
{
|
||||
return m_numTestFailures;
|
||||
return m_tests.size();
|
||||
}
|
||||
|
||||
const AZStd::vector<TestCaseFailure>& TestRunWithTestFailures::GetTestCaseFailures() const
|
||||
size_t CompletedTestRun::GetTotalNumPassingTests() const
|
||||
{
|
||||
return m_totalNumPassingTests;
|
||||
}
|
||||
|
||||
size_t CompletedTestRun::GetTotalNumFailingTests() const
|
||||
{
|
||||
return m_totalNumFailingTests;
|
||||
}
|
||||
|
||||
size_t CompletedTestRun::GetTotalNumDisabledTests() const
|
||||
{
|
||||
return m_totalNumDisabledTests;
|
||||
}
|
||||
|
||||
const AZStd::vector<Test>& CompletedTestRun::GetTests() const
|
||||
{
|
||||
return m_tests;
|
||||
}
|
||||
|
||||
PassingTestRun::PassingTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests)
|
||||
: CompletedTestRun(AZStd::move(testRun), AZStd::move(tests))
|
||||
{
|
||||
}
|
||||
|
||||
FailingTestRun::FailingTestRun(TestRunBase&& testRun, AZStd::vector<Test>&& tests)
|
||||
: CompletedTestRun(AZStd::move(testRun), AZStd::move(tests))
|
||||
{
|
||||
return m_testCaseFailures;
|
||||
}
|
||||
} // namespace Client
|
||||
} // namespace TestImpact
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
#include <TestImpactFramework/TestImpactRuntime.h>
|
||||
#include <TestImpactFramework/TestImpactRuntimeException.h>
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace TestImpact
|
||||
{
|
||||
if (m_testCompleteCallback.has_value())
|
||||
{
|
||||
Client::TestRun testRun(
|
||||
Client::TestRunBase testRun(
|
||||
testJob.GetTestTarget()->GetName(),
|
||||
testJob.GetCommandString(),
|
||||
testJob.GetStartTime(),
|
||||
@@ -110,8 +110,140 @@ namespace TestImpact
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Utility structure for holding the pertinent data for test run reports.
|
||||
template<typename TestJob>
|
||||
struct TestRunData
|
||||
{
|
||||
TestSequenceResult m_result = TestSequenceResult::Success;
|
||||
AZStd::vector<TestJob> m_jobs;
|
||||
AZStd::chrono::high_resolution_clock::time_point m_relativeStartTime;
|
||||
AZStd::chrono::milliseconds m_duration = AZStd::chrono::milliseconds{ 0 };
|
||||
};
|
||||
|
||||
//! Wrapper for the impact analysis test sequence to handle both the updating and non-updating policies through a common pathway.
|
||||
//! @tparam TestRunnerFunctor The functor for running the specified tests.
|
||||
//! @tparam TestJob The test engine job type returned by the functor.
|
||||
//! @param maxConcurrency The maximum concurrency being used for this sequence.
|
||||
//! @param policyState The policy state being used for the sequence.
|
||||
//! @param suiteType The suite type used for this sequence.
|
||||
//! @param timer The timer to use for the test run timings.
|
||||
//! @param testRunner The test runner functor to use for each of the test runs.
|
||||
//! @param includedSelectedTestTargets The subset of test targets that were selected to run and not also fully excluded from running.
|
||||
//! @param excludedSelectedTestTargets The subset of test targets that were selected to run but were fully excluded running.
|
||||
//! @param discardedTestTargets The subset of test targets that were discarded from the test selection and will not be run.
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the
|
||||
//! tests.
|
||||
//! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed.
|
||||
//! @param testRunCompleteCallback The client function to be called after an individual test run has completed.
|
||||
//! @param updateCoverage The function to call to update the dynamic dependency map with test coverage (if any).
|
||||
template<typename TestRunnerFunctor, typename TestJob>
|
||||
Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequenceWrapper(
|
||||
size_t maxConcurrency,
|
||||
const ImpactAnalysisSequencePolicyState& policyState,
|
||||
SuiteType suiteType,
|
||||
const Timer& sequenceTimer,
|
||||
const TestRunnerFunctor& testRunner,
|
||||
const AZStd::vector<const TestTarget*>& includedSelectedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& excludedSelectedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& discardedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& draftedTestTargets,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
|
||||
AZStd::optional<ImpactAnalysisTestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::ImpactAnalysisSequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testCompleteCallback,
|
||||
AZStd::optional<AZStd::function<void(const AZStd::vector<TestJob>& jobs)>> updateCoverage)
|
||||
{
|
||||
TestRunData<TestJob> selectedTestRunData, draftedTestRunData;
|
||||
AZStd::optional<AZStd::chrono::milliseconds> sequenceTimeout = globalTimeout;
|
||||
|
||||
// Extract the client facing representation of selected, discarded and drafted test targets
|
||||
const Client::TestRunSelection selectedTests(
|
||||
ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets));
|
||||
const auto discardedTests = ExtractTestTargetNames(discardedTestTargets);
|
||||
const auto draftedTests = ExtractTestTargetNames(draftedTestTargets);
|
||||
|
||||
// Inform the client that the sequence is about to start
|
||||
if (testSequenceStartCallback.has_value())
|
||||
{
|
||||
(*testSequenceStartCallback)(suiteType, selectedTests, discardedTests, draftedTests);
|
||||
}
|
||||
|
||||
// We share the test run complete handler between the selected and drafted test runs as to present them together as one
|
||||
// continuous test sequence to the client rather than two discrete test runs
|
||||
const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size();
|
||||
TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback);
|
||||
|
||||
const auto gatherTestRunData = [&sequenceTimer, &testRunner, &testRunCompleteHandler, &globalTimeout]
|
||||
(const AZStd::vector<const TestTarget*>& testsTargets, TestRunData<TestJob>& testRunData)
|
||||
{
|
||||
const Timer testRunTimer;
|
||||
testRunData.m_relativeStartTime = testRunTimer.GetStartTimePointRelative(sequenceTimer);
|
||||
auto [result, jobs] = testRunner(testsTargets, testRunCompleteHandler, globalTimeout);
|
||||
testRunData.m_result = result;
|
||||
testRunData.m_jobs = AZStd::move(jobs);
|
||||
testRunData.m_duration = testRunTimer.GetElapsedMs();
|
||||
};
|
||||
|
||||
if (!includedSelectedTestTargets.empty())
|
||||
{
|
||||
// Run the selected test targets and collect the test run results
|
||||
gatherTestRunData(includedSelectedTestTargets, selectedTestRunData);
|
||||
|
||||
// Carry the remaining global sequence time over to the drafted test run
|
||||
if (globalTimeout.has_value())
|
||||
{
|
||||
const auto elapsed = selectedTestRunData.m_duration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!draftedTestTargets.empty())
|
||||
{
|
||||
// Run the drafted test targets and collect the test run results
|
||||
gatherTestRunData(draftedTestTargets, draftedTestRunData);
|
||||
}
|
||||
|
||||
// Generate the sequence report for the client
|
||||
const auto sequenceReport = Client::ImpactAnalysisSequenceReport(
|
||||
maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
policyState,
|
||||
suiteType,
|
||||
selectedTests,
|
||||
discardedTests,
|
||||
draftedTests,
|
||||
GenerateTestRunReport(
|
||||
selectedTestRunData.m_result,
|
||||
selectedTestRunData.m_relativeStartTime,
|
||||
selectedTestRunData.m_duration,
|
||||
selectedTestRunData.m_jobs),
|
||||
GenerateTestRunReport(
|
||||
draftedTestRunData.m_result,
|
||||
draftedTestRunData.m_relativeStartTime,
|
||||
draftedTestRunData.m_duration,
|
||||
draftedTestRunData.m_jobs));
|
||||
|
||||
// Inform the client that the sequence has ended
|
||||
if (testSequenceEndCallback.has_value())
|
||||
{
|
||||
(*testSequenceEndCallback)(sequenceReport);
|
||||
}
|
||||
|
||||
// Update the dynamic dependency map with the latest coverage data (if any)
|
||||
if (updateCoverage.has_value())
|
||||
{
|
||||
(*updateCoverage)(ConcatenateVectors(selectedTestRunData.m_jobs, draftedTestRunData.m_jobs));
|
||||
}
|
||||
|
||||
return sequenceReport;
|
||||
}
|
||||
|
||||
Runtime::Runtime(
|
||||
RuntimeConfig&& config,
|
||||
AZStd::optional<RepoPath> dataFile,
|
||||
SuiteType suiteFilter,
|
||||
Policy::ExecutionFailure executionFailurePolicy,
|
||||
Policy::FailedTestCoverage failedTestCoveragePolicy,
|
||||
@@ -151,27 +283,22 @@ namespace TestImpact
|
||||
|
||||
try
|
||||
{
|
||||
if (dataFile.has_value())
|
||||
{
|
||||
m_sparTiaFile = dataFile.value().String();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sparTiaFile = m_config.m_workspace.m_active.m_sparTiaFiles[static_cast<size_t>(m_suiteFilter)].String();
|
||||
}
|
||||
|
||||
// Populate the dynamic dependency map with the existing source coverage data (if any)
|
||||
m_sparTIAFile = m_config.m_workspace.m_active.m_sparTIAFiles[static_cast<size_t>(m_suiteFilter)].String();
|
||||
const auto tiaDataRaw = ReadFileContents<Exception>(m_sparTIAFile);
|
||||
const auto tiaDataRaw = ReadFileContents<Exception>(m_sparTiaFile);
|
||||
const auto tiaData = DeserializeSourceCoveringTestsList(tiaDataRaw);
|
||||
if (tiaData.GetNumSources())
|
||||
{
|
||||
m_dynamicDependencyMap->ReplaceSourceCoverage(tiaData);
|
||||
m_hasImpactAnalysisData = true;
|
||||
|
||||
// Enumerate new test targets
|
||||
const auto testTargetsWithNoEnumeration = m_dynamicDependencyMap->GetNotCoveringTests();
|
||||
if (!testTargetsWithNoEnumeration.empty())
|
||||
{
|
||||
m_testEngine->UpdateEnumerationCache(
|
||||
testTargetsWithNoEnumeration,
|
||||
Policy::ExecutionFailure::Ignore,
|
||||
Policy::TestFailure::Continue,
|
||||
AZStd::nullopt,
|
||||
AZStd::nullopt,
|
||||
AZStd::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const DependencyException& e)
|
||||
@@ -186,7 +313,7 @@ namespace TestImpact
|
||||
AZ_Printf(
|
||||
LogCallSite,
|
||||
AZStd::string::format(
|
||||
"No test impact analysis data found for suite '%s' at %s\n", GetSuiteTypeName(m_suiteFilter).c_str(), m_sparTIAFile.c_str()).c_str());
|
||||
"No test impact analysis data found for suite '%s' at %s\n", SuiteTypeAsString(m_suiteFilter).c_str(), m_sparTiaFile.c_str()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +357,7 @@ namespace TestImpact
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::pair<AZStd::vector<const TestTarget*>, AZStd::vector<const TestTarget*>> Runtime::SelectCoveringTestTargetsAndUpdateEnumerationCache(
|
||||
AZStd::pair<AZStd::vector<const TestTarget*>, AZStd::vector<const TestTarget*>> Runtime::SelectCoveringTestTargets(
|
||||
const ChangeList& changeList,
|
||||
Policy::TestPrioritization testPrioritizationPolicy)
|
||||
{
|
||||
@@ -243,9 +370,6 @@ namespace TestImpact
|
||||
// Populate a set with the selected test targets so that we can infer the discarded test target not selected for this change list
|
||||
const AZStd::unordered_set<const TestTarget*> selectedTestTargetSet(selectedTestTargets.begin(), selectedTestTargets.end());
|
||||
|
||||
// Update the enumeration caches of mutated targets regardless of the current sharding policy
|
||||
EnumerateMutatedTestTargets(changeDependencyList);
|
||||
|
||||
// The test targets in the main list not in the selected test target set are the test targets not selected for this change list
|
||||
for (const auto& testTarget : m_dynamicDependencyMap->GetTestTargetList().GetTargets())
|
||||
{
|
||||
@@ -287,7 +411,7 @@ namespace TestImpact
|
||||
void Runtime::ClearDynamicDependencyMapAndRemoveExistingFile()
|
||||
{
|
||||
m_dynamicDependencyMap->ClearAllSourceCoverage();
|
||||
DeleteFile(m_sparTIAFile);
|
||||
DeleteFile(m_sparTiaFile);
|
||||
}
|
||||
|
||||
SourceCoveringTestsList Runtime::CreateSourceCoveringTestFromTestCoverages(const AZStd::vector<TestEngineInstrumentedRun>& jobs)
|
||||
@@ -368,9 +492,9 @@ namespace TestImpact
|
||||
}
|
||||
|
||||
m_dynamicDependencyMap->ReplaceSourceCoverage(sourceCoverageTestsList);
|
||||
const auto sparTIA = m_dynamicDependencyMap->ExportSourceCoverage();
|
||||
const auto sparTIAData = SerializeSourceCoveringTestsList(sparTIA);
|
||||
WriteFileContents<RuntimeException>(sparTIAData, m_sparTIAFile);
|
||||
const auto sparTia = m_dynamicDependencyMap->ExportSourceCoverage();
|
||||
const auto sparTiaData = SerializeSourceCoveringTestsList(sparTia);
|
||||
WriteFileContents<RuntimeException>(sparTiaData, m_sparTiaFile);
|
||||
m_hasImpactAnalysisData = true;
|
||||
}
|
||||
catch(const RuntimeException& e)
|
||||
@@ -386,11 +510,42 @@ namespace TestImpact
|
||||
}
|
||||
}
|
||||
|
||||
Client::SequenceReport Runtime::RegularTestSequence(
|
||||
PolicyStateBase Runtime::GeneratePolicyStateBase() const
|
||||
{
|
||||
PolicyStateBase policyState;
|
||||
|
||||
policyState.m_executionFailurePolicy = m_executionFailurePolicy;
|
||||
policyState.m_failedTestCoveragePolicy = m_failedTestCoveragePolicy;
|
||||
policyState.m_integrityFailurePolicy = m_integrationFailurePolicy;
|
||||
policyState.m_targetOutputCapture = m_targetOutputCapture;
|
||||
policyState.m_testFailurePolicy = m_testFailurePolicy;
|
||||
policyState.m_testShardingPolicy = m_testShardingPolicy;
|
||||
|
||||
return policyState;
|
||||
}
|
||||
|
||||
SequencePolicyState Runtime::GenerateSequencePolicyState() const
|
||||
{
|
||||
return { GeneratePolicyStateBase() };
|
||||
}
|
||||
|
||||
SafeImpactAnalysisSequencePolicyState Runtime::GenerateSafeImpactAnalysisSequencePolicyState(
|
||||
Policy::TestPrioritization testPrioritizationPolicy) const
|
||||
{
|
||||
return { GeneratePolicyStateBase(), testPrioritizationPolicy };
|
||||
}
|
||||
|
||||
ImpactAnalysisSequencePolicyState Runtime::GenerateImpactAnalysisSequencePolicyState(
|
||||
Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy) const
|
||||
{
|
||||
return { GeneratePolicyStateBase(), testPrioritizationPolicy, dynamicDependencyMapPolicy };
|
||||
}
|
||||
|
||||
Client::RegularSequenceReport Runtime::RegularTestSequence(
|
||||
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
|
||||
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
|
||||
AZStd::optional<TestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::RegularSequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testCompleteCallback)
|
||||
{
|
||||
const Timer sequenceTimer;
|
||||
@@ -434,7 +589,11 @@ namespace TestImpact
|
||||
const auto testRunDuration = testRunTimer.GetElapsedMs();
|
||||
|
||||
// Generate the sequence report for the client
|
||||
const auto sequenceReport = Client::SequenceReport(
|
||||
const auto sequenceReport = Client::RegularSequenceReport(
|
||||
m_maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
GenerateSequencePolicyState(),
|
||||
m_suiteFilter,
|
||||
selectedTests,
|
||||
GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs));
|
||||
@@ -448,95 +607,6 @@ namespace TestImpact
|
||||
return sequenceReport;
|
||||
}
|
||||
|
||||
//! Wrapper for the impact analysis test sequence to handle both the updating and non-updating policies through a common pathway.
|
||||
//! @tparam TestRunnerFunctor The functor for running the specified tests.
|
||||
//! @tparam TestJob The test engine job type returned by the functor.
|
||||
//! @param suiteType The suite type used for this sequence.
|
||||
//! @param timer The timer to use for the test run timings.
|
||||
//! @param testRunner The test runner functor to use for each of the test runs.
|
||||
//! @param includedSelectedTestTargets The subset of test targets that were selected to run and not also fully excluded from running.
|
||||
//! @param excludedSelectedTestTargets The subset of test targets that were selected to run but were fully excluded running.
|
||||
//! @param discardedTestTargets The subset of test targets that were discarded from the test selection and will not be run.
|
||||
//! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty).
|
||||
//! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests.
|
||||
//! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed.
|
||||
//! @param testRunCompleteCallback The client function to be called after an individual test run has completed.
|
||||
//! @param updateCoverage The function to call to update the dynamic dependency map with test coverage (if any).
|
||||
template<typename TestRunnerFunctor, typename TestJob>
|
||||
Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequenceWrapper(
|
||||
SuiteType suiteType,
|
||||
const Timer& sequenceTimer,
|
||||
const TestRunnerFunctor& testRunner,
|
||||
const AZStd::vector<const TestTarget*>& includedSelectedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& excludedSelectedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& discardedTestTargets,
|
||||
const AZStd::vector<const TestTarget*>& draftedTestTargets,
|
||||
const AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
|
||||
AZStd::optional<ImpactAnalysisTestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::ImpactAnalysisSequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testCompleteCallback,
|
||||
AZStd::optional<AZStd::function<void(const AZStd::vector<TestJob>& jobs)>> updateCoverage)
|
||||
{
|
||||
AZStd::optional<AZStd::chrono::milliseconds> sequenceTimeout = globalTimeout;
|
||||
|
||||
// Extract the client facing representation of selected, discarded and drafted test targets
|
||||
const Client::TestRunSelection selectedTests(
|
||||
ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets));
|
||||
const auto discardedTests = ExtractTestTargetNames(discardedTestTargets);
|
||||
const auto draftedTests = ExtractTestTargetNames(draftedTestTargets);
|
||||
|
||||
// Inform the client that the sequence is about to start
|
||||
if (testSequenceStartCallback.has_value())
|
||||
{
|
||||
(*testSequenceStartCallback)(suiteType, selectedTests, discardedTests, draftedTests);
|
||||
}
|
||||
|
||||
// We share the test run complete handler between the selected and drafted test runs as to present them together as one
|
||||
// continuous test sequence to the client rather than two discrete test runs
|
||||
const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size();
|
||||
TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback);
|
||||
|
||||
// Run the selected test targets and collect the test run results
|
||||
const Timer selectedTestRunTimer;
|
||||
const auto [selectedResult, selectedTestJobs] = testRunner(includedSelectedTestTargets, testRunCompleteHandler, globalTimeout);
|
||||
const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs();
|
||||
|
||||
// Carry the remaining global sequence time over to the drafted test run
|
||||
if (globalTimeout.has_value())
|
||||
{
|
||||
const auto elapsed = selectedTestRunDuration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
}
|
||||
|
||||
// Run the drafted test targets and collect the test run results
|
||||
Timer draftedTestRunTimer;
|
||||
const auto [draftedResult, draftedTestJobs] = testRunner(draftedTestTargets, testRunCompleteHandler, globalTimeout);
|
||||
const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs();
|
||||
|
||||
// Generate the sequence report for the client
|
||||
const auto sequenceReport = Client::ImpactAnalysisSequenceReport(
|
||||
suiteType,
|
||||
selectedTests,
|
||||
discardedTests,
|
||||
draftedTests,
|
||||
GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs),
|
||||
GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs));
|
||||
|
||||
// Inform the client that the sequence has ended
|
||||
if (testSequenceEndCallback.has_value())
|
||||
{
|
||||
(*testSequenceEndCallback)(sequenceReport);
|
||||
}
|
||||
|
||||
// Update the dynamic dependency map with the latest coverage data (if any)
|
||||
if (updateCoverage.has_value())
|
||||
{
|
||||
(*updateCoverage)(ConcatenateVectors(selectedTestJobs, draftedTestJobs));
|
||||
}
|
||||
|
||||
return sequenceReport;
|
||||
}
|
||||
|
||||
Client::ImpactAnalysisSequenceReport Runtime::ImpactAnalysisTestSequence(
|
||||
const ChangeList& changeList,
|
||||
Policy::TestPrioritization testPrioritizationPolicy,
|
||||
@@ -550,10 +620,30 @@ namespace TestImpact
|
||||
const Timer sequenceTimer;
|
||||
|
||||
// Draft in the test targets that have no coverage entries in the dynamic dependency map
|
||||
AZStd::vector<const TestTarget*> draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests();
|
||||
const AZStd::vector<const TestTarget*> draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests();
|
||||
|
||||
// The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not
|
||||
auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargetsAndUpdateEnumerationCache(changeList, testPrioritizationPolicy);
|
||||
const auto selectCoveringTestTargetsAndPruneDraftedFromDiscarded =
|
||||
[this, &draftedTestTargets, &changeList, testPrioritizationPolicy]()
|
||||
{
|
||||
// The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not
|
||||
const auto [selectedTestTargets, discardedTestTargets] =
|
||||
SelectCoveringTestTargets(changeList, testPrioritizationPolicy);
|
||||
|
||||
const AZStd::unordered_set<const TestTarget*> draftedTestTargetsSet(draftedTestTargets.begin(), draftedTestTargets.end());
|
||||
|
||||
AZStd::vector<const TestTarget*> discardedNotDraftedTestTargets;
|
||||
for (const auto* testTarget : discardedTestTargets)
|
||||
{
|
||||
if (!draftedTestTargetsSet.count(testTarget))
|
||||
{
|
||||
discardedNotDraftedTestTargets.push_back(testTarget);
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::pair{ selectedTestTargets, discardedNotDraftedTestTargets };
|
||||
};
|
||||
|
||||
const auto [selectedTestTargets, discardedTestTargets] = selectCoveringTestTargetsAndPruneDraftedFromDiscarded();
|
||||
|
||||
// The subset of selected test targets that are not on the configuration's exclude list and those that are
|
||||
auto [includedSelectedTestTargets, excludedSelectedTestTargets] = SelectTestTargetsByExcludeList(selectedTestTargets);
|
||||
@@ -604,6 +694,8 @@ namespace TestImpact
|
||||
};
|
||||
|
||||
return ImpactAnalysisTestSequenceWrapper(
|
||||
m_maxConcurrency,
|
||||
GenerateImpactAnalysisSequencePolicyState(testPrioritizationPolicy, dynamicDependencyMapPolicy),
|
||||
m_suiteFilter,
|
||||
sequenceTimer,
|
||||
instrumentedTestRun,
|
||||
@@ -611,6 +703,7 @@ namespace TestImpact
|
||||
excludedSelectedTestTargets,
|
||||
discardedTestTargets,
|
||||
draftedTestTargets,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
testSequenceStartCallback,
|
||||
testSequenceEndCallback,
|
||||
@@ -620,6 +713,8 @@ namespace TestImpact
|
||||
else
|
||||
{
|
||||
return ImpactAnalysisTestSequenceWrapper(
|
||||
m_maxConcurrency,
|
||||
GenerateImpactAnalysisSequencePolicyState(testPrioritizationPolicy, dynamicDependencyMapPolicy),
|
||||
m_suiteFilter,
|
||||
sequenceTimer,
|
||||
regularTestRun,
|
||||
@@ -627,6 +722,7 @@ namespace TestImpact
|
||||
excludedSelectedTestTargets,
|
||||
discardedTestTargets,
|
||||
draftedTestTargets,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
testSequenceStartCallback,
|
||||
testSequenceEndCallback,
|
||||
@@ -645,13 +741,15 @@ namespace TestImpact
|
||||
AZStd::optional<TestRunCompleteCallback> testCompleteCallback)
|
||||
{
|
||||
const Timer sequenceTimer;
|
||||
auto sequenceTimeout = globalTimeout;
|
||||
TestRunData<TestEngineInstrumentedRun> selectedTestRunData, draftedTestRunData;
|
||||
TestRunData<TestEngineRegularRun> discardedTestRunData;
|
||||
AZStd::optional<AZStd::chrono::milliseconds> sequenceTimeout = globalTimeout;
|
||||
|
||||
// Draft in the test targets that have no coverage entries in the dynamic dependency map
|
||||
AZStd::vector<const TestTarget*> draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests();
|
||||
|
||||
// The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not
|
||||
auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargetsAndUpdateEnumerationCache(changeList, testPrioritizationPolicy);
|
||||
const auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargets(changeList, testPrioritizationPolicy);
|
||||
|
||||
// The subset of selected test targets that are not on the configuration's exclude list and those that are
|
||||
auto [includedSelectedTestTargets, excludedSelectedTestTargets] = SelectTestTargetsByExcludeList(selectedTestTargets);
|
||||
@@ -675,71 +773,107 @@ namespace TestImpact
|
||||
// continuous test sequence to the client rather than three discrete test runs
|
||||
const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size() + includedDiscardedTestTargets.size();
|
||||
TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback);
|
||||
|
||||
// Run the selected test targets and collect the test run results
|
||||
const Timer selectedTestRunTimer;
|
||||
const auto [selectedResult, selectedTestJobs] = m_testEngine->InstrumentedRun(
|
||||
includedSelectedTestTargets,
|
||||
m_testShardingPolicy,
|
||||
m_executionFailurePolicy,
|
||||
m_integrationFailurePolicy,
|
||||
m_testFailurePolicy,
|
||||
m_targetOutputCapture,
|
||||
testTargetTimeout,
|
||||
sequenceTimeout,
|
||||
AZStd::ref(testRunCompleteHandler));
|
||||
const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs();
|
||||
|
||||
// Carry the remaining global sequence time over to the discarded test run
|
||||
if (globalTimeout.has_value())
|
||||
|
||||
// Functor for running instrumented test targets
|
||||
const auto instrumentedTestRun =
|
||||
[this, &testTargetTimeout, &sequenceTimeout, &testRunCompleteHandler](const AZStd::vector<const TestTarget*>& testsTargets)
|
||||
{
|
||||
const auto elapsed = selectedTestRunDuration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
return m_testEngine->InstrumentedRun(
|
||||
testsTargets,
|
||||
m_testShardingPolicy,
|
||||
m_executionFailurePolicy,
|
||||
m_integrationFailurePolicy,
|
||||
m_testFailurePolicy,
|
||||
m_targetOutputCapture,
|
||||
testTargetTimeout,
|
||||
sequenceTimeout,
|
||||
AZStd::ref(testRunCompleteHandler));
|
||||
};
|
||||
|
||||
// Functor for running uninstrumented test targets
|
||||
const auto regularTestRun =
|
||||
[this, &testTargetTimeout, &sequenceTimeout, &testRunCompleteHandler](const AZStd::vector<const TestTarget*>& testsTargets)
|
||||
{
|
||||
return m_testEngine->RegularRun(
|
||||
testsTargets,
|
||||
m_testShardingPolicy,
|
||||
m_executionFailurePolicy,
|
||||
m_testFailurePolicy,
|
||||
m_targetOutputCapture,
|
||||
testTargetTimeout,
|
||||
sequenceTimeout,
|
||||
AZStd::ref(testRunCompleteHandler));
|
||||
};
|
||||
|
||||
// Functor for running instrumented test targets
|
||||
const auto gatherTestRunData = [&sequenceTimer]
|
||||
(const AZStd::vector<const TestTarget*>& testsTargets, const auto& testRunner, auto& testRunData)
|
||||
{
|
||||
const Timer testRunTimer;
|
||||
testRunData.m_relativeStartTime = testRunTimer.GetStartTimePointRelative(sequenceTimer);
|
||||
auto [result, jobs] = testRunner(testsTargets);
|
||||
testRunData.m_result = result;
|
||||
testRunData.m_jobs = AZStd::move(jobs);
|
||||
testRunData.m_duration = testRunTimer.GetElapsedMs();
|
||||
};
|
||||
|
||||
if (!includedSelectedTestTargets.empty())
|
||||
{
|
||||
// Run the selected test targets and collect the test run results
|
||||
gatherTestRunData(includedSelectedTestTargets, instrumentedTestRun, selectedTestRunData);
|
||||
|
||||
// Carry the remaining global sequence time over to the discarded test run
|
||||
if (globalTimeout.has_value())
|
||||
{
|
||||
const auto elapsed = selectedTestRunData.m_duration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the discarded test targets and collect the test run results
|
||||
const Timer discardedTestRunTimer;
|
||||
const auto [discardedResult, discardedTestJobs] = m_testEngine->RegularRun(
|
||||
includedDiscardedTestTargets,
|
||||
m_testShardingPolicy,
|
||||
m_executionFailurePolicy,
|
||||
m_testFailurePolicy,
|
||||
m_targetOutputCapture,
|
||||
testTargetTimeout,
|
||||
sequenceTimeout,
|
||||
AZStd::ref(testRunCompleteHandler));
|
||||
const auto discardedTestRunDuration = discardedTestRunTimer.GetElapsedMs();
|
||||
|
||||
// Carry the remaining global sequence time over to the drafted test run
|
||||
if (globalTimeout.has_value())
|
||||
if (!includedDiscardedTestTargets.empty())
|
||||
{
|
||||
const auto elapsed = selectedTestRunDuration + discardedTestRunDuration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
// Run the discarded test targets and collect the test run results
|
||||
gatherTestRunData(includedDiscardedTestTargets, regularTestRun, discardedTestRunData);
|
||||
|
||||
// Carry the remaining global sequence time over to the drafted test run
|
||||
if (globalTimeout.has_value())
|
||||
{
|
||||
const auto elapsed = selectedTestRunData.m_duration + discardedTestRunData.m_duration;
|
||||
sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the drafted test targets and collect the test run results
|
||||
const Timer draftedTestRunTimer;
|
||||
const auto [draftedResult, draftedTestJobs] = m_testEngine->InstrumentedRun(
|
||||
draftedTestTargets,
|
||||
m_testShardingPolicy,
|
||||
m_executionFailurePolicy,
|
||||
m_integrationFailurePolicy,
|
||||
m_testFailurePolicy,
|
||||
m_targetOutputCapture,
|
||||
testTargetTimeout,
|
||||
sequenceTimeout,
|
||||
AZStd::ref(testRunCompleteHandler));
|
||||
const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs();
|
||||
if (!draftedTestTargets.empty())
|
||||
{
|
||||
// Run the drafted test targets and collect the test run results
|
||||
gatherTestRunData(draftedTestTargets, instrumentedTestRun, draftedTestRunData);
|
||||
}
|
||||
|
||||
// Generate the sequence report for the client
|
||||
const auto sequenceReport = Client::SafeImpactAnalysisSequenceReport(
|
||||
m_maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
GenerateSafeImpactAnalysisSequencePolicyState(testPrioritizationPolicy),
|
||||
m_suiteFilter,
|
||||
selectedTests,
|
||||
discardedTests,
|
||||
draftedTests,
|
||||
GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs),
|
||||
GenerateTestRunReport(discardedResult, discardedTestRunTimer.GetStartTimePointRelative(sequenceTimer), discardedTestRunDuration, discardedTestJobs),
|
||||
GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs));
|
||||
GenerateTestRunReport(
|
||||
selectedTestRunData.m_result,
|
||||
selectedTestRunData.m_relativeStartTime,
|
||||
selectedTestRunData.m_duration,
|
||||
selectedTestRunData.m_jobs),
|
||||
GenerateTestRunReport(
|
||||
discardedTestRunData.m_result,
|
||||
discardedTestRunData.m_relativeStartTime,
|
||||
discardedTestRunData.m_duration,
|
||||
discardedTestRunData.m_jobs),
|
||||
GenerateTestRunReport(
|
||||
draftedTestRunData.m_result,
|
||||
draftedTestRunData.m_relativeStartTime,
|
||||
draftedTestRunData.m_duration,
|
||||
draftedTestRunData.m_jobs));
|
||||
|
||||
// Inform the client that the sequence has ended
|
||||
if (testSequenceEndCallback.has_value())
|
||||
@@ -747,15 +881,15 @@ namespace TestImpact
|
||||
(*testSequenceEndCallback)(sequenceReport);
|
||||
}
|
||||
|
||||
UpdateAndSerializeDynamicDependencyMap(ConcatenateVectors(selectedTestJobs, draftedTestJobs));
|
||||
UpdateAndSerializeDynamicDependencyMap(ConcatenateVectors(selectedTestRunData.m_jobs, draftedTestRunData.m_jobs));
|
||||
return sequenceReport;
|
||||
}
|
||||
|
||||
Client::SequenceReport Runtime::SeededTestSequence(
|
||||
Client::SeedSequenceReport Runtime::SeededTestSequence(
|
||||
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
|
||||
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
|
||||
AZStd::optional<TestSequenceStartCallback> testSequenceStartCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestSequenceCompleteCallback<Client::SeedSequenceReport>> testSequenceEndCallback,
|
||||
AZStd::optional<TestRunCompleteCallback> testCompleteCallback)
|
||||
{
|
||||
const Timer sequenceTimer;
|
||||
@@ -799,7 +933,11 @@ namespace TestImpact
|
||||
const auto testRunDuration = testRunTimer.GetElapsedMs();
|
||||
|
||||
// Generate the sequence report for the client
|
||||
const auto sequenceReport = Client::SequenceReport(
|
||||
const auto sequenceReport = Client::SeedSequenceReport(
|
||||
m_maxConcurrency,
|
||||
testTargetTimeout,
|
||||
globalTimeout,
|
||||
GenerateSequencePolicyState(),
|
||||
m_suiteFilter,
|
||||
selectedTests,
|
||||
GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TestImpactFramework/TestImpactFileUtils.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
#include <TestImpactFramework/TestImpactRuntimeException.h>
|
||||
|
||||
#include <TestImpactRuntimeUtils.h>
|
||||
|
||||
@@ -38,34 +38,44 @@ namespace TestImpact
|
||||
//! Extracts the name information from the specified test targets.
|
||||
AZStd::vector<AZStd::string> ExtractTestTargetNames(const AZStd::vector<const TestTarget*>& testTargets);
|
||||
|
||||
//! Generates a test run failure report from the specified test engine job information.
|
||||
//! Generates the test suites from the specified test engine job information.
|
||||
//! @tparam TestJob The test engine job type.
|
||||
template<typename TestJob>
|
||||
AZStd::vector<Client::TestCaseFailure> GenerateTestCaseFailures(const TestJob& testJob)
|
||||
AZStd::vector<Client::Test> GenerateClientTests(const TestJob& testJob)
|
||||
{
|
||||
AZStd::vector<Client::TestCaseFailure> testCaseFailures;
|
||||
AZStd::vector<Client::Test> tests;
|
||||
|
||||
if (testJob.GetTestRun().has_value())
|
||||
{
|
||||
for (const auto& testSuite : testJob.GetTestRun()->GetTestSuites())
|
||||
{
|
||||
AZStd::vector<Client::TestFailure> testFailures;
|
||||
for (const auto& testCase : testSuite.m_tests)
|
||||
{
|
||||
if (testCase.m_result.value_or(TestRunResult::Passed) == TestRunResult::Failed)
|
||||
auto result = Client::TestResult::NotRun;
|
||||
if (testCase.m_result.has_value())
|
||||
{
|
||||
testFailures.push_back(Client::TestFailure(testCase.m_name, "No error message retrieved"));
|
||||
if (testCase.m_result.value() == TestRunResult::Passed)
|
||||
{
|
||||
result = Client::TestResult::Passed;
|
||||
}
|
||||
else if (testCase.m_result.value() == TestRunResult::Failed)
|
||||
{
|
||||
result = Client::TestResult::Failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw RuntimeException(AZStd::string::format(
|
||||
"Unexpected test run result: %u", aznumeric_cast<AZ::u32>(testCase.m_result.value())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!testFailures.empty())
|
||||
{
|
||||
testCaseFailures.push_back(Client::TestCaseFailure(testSuite.m_name, AZStd::move(testFailures)));
|
||||
|
||||
const auto name = AZStd::string::format("%s.%s", testSuite.m_name.c_str(), testCase.m_name.c_str());
|
||||
tests.push_back(Client::Test(name, result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return testCaseFailures;
|
||||
return tests;
|
||||
}
|
||||
|
||||
template<typename TestJob>
|
||||
@@ -75,11 +85,11 @@ namespace TestImpact
|
||||
AZStd::chrono::milliseconds duration,
|
||||
const AZStd::vector<TestJob>& testJobs)
|
||||
{
|
||||
AZStd::vector<Client::TestRun> passingTests;
|
||||
AZStd::vector<Client::TestRunWithTestFailures> failingTests;
|
||||
AZStd::vector<Client::TestRun> executionFailureTests;
|
||||
AZStd::vector<Client::TestRun> timedOutTests;
|
||||
AZStd::vector<Client::TestRun> unexecutedTests;
|
||||
AZStd::vector<Client::PassingTestRun> passingTests;
|
||||
AZStd::vector<Client::FailingTestRun> failingTests;
|
||||
AZStd::vector<Client::TestRunWithExecutionFailure> executionFailureTests;
|
||||
AZStd::vector<Client::TimedOutTestRun> timedOutTests;
|
||||
AZStd::vector<Client::UnexecutedTestRun> unexecutedTests;
|
||||
|
||||
for (const auto& testJob : testJobs)
|
||||
{
|
||||
@@ -88,7 +98,7 @@ namespace TestImpact
|
||||
AZStd::chrono::high_resolution_clock::time_point() +
|
||||
AZStd::chrono::duration_cast<AZStd::chrono::milliseconds>(testJob.GetStartTime() - startTime);
|
||||
|
||||
Client::TestRun clientTestRun(
|
||||
Client::TestRunBase clientTestRun(
|
||||
testJob.GetTestTarget()->GetName(), testJob.GetCommandString(), relativeStartTime, testJob.GetDuration(),
|
||||
testJob.GetTestResult());
|
||||
|
||||
@@ -96,27 +106,27 @@ namespace TestImpact
|
||||
{
|
||||
case Client::TestRunResult::FailedToExecute:
|
||||
{
|
||||
executionFailureTests.push_back(clientTestRun);
|
||||
executionFailureTests.emplace_back(AZStd::move(clientTestRun));
|
||||
break;
|
||||
}
|
||||
case Client::TestRunResult::NotRun:
|
||||
{
|
||||
unexecutedTests.push_back(clientTestRun);
|
||||
unexecutedTests.emplace_back(AZStd::move(clientTestRun));
|
||||
break;
|
||||
}
|
||||
case Client::TestRunResult::Timeout:
|
||||
{
|
||||
timedOutTests.push_back(clientTestRun);
|
||||
timedOutTests.emplace_back(AZStd::move(clientTestRun));
|
||||
break;
|
||||
}
|
||||
case Client::TestRunResult::AllTestsPass:
|
||||
{
|
||||
passingTests.push_back(clientTestRun);
|
||||
passingTests.emplace_back(AZStd::move(clientTestRun), GenerateClientTests(testJob));
|
||||
break;
|
||||
}
|
||||
case Client::TestRunResult::TestFailures:
|
||||
{
|
||||
failingTests.emplace_back(AZStd::move(clientTestRun), GenerateTestCaseFailures(testJob));
|
||||
failingTests.emplace_back(AZStd::move(clientTestRun), GenerateClientTests(testJob));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 <TestImpactFramework/TestImpactException.h>
|
||||
#include <TestImpactFramework/TestImpactUtils.h>
|
||||
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace TestImpact
|
||||
{
|
||||
//! Delete the files that match the pattern from the specified directory.
|
||||
//! @param path The path to the directory to pattern match the files for deletion.
|
||||
//! @param pattern The pattern to match files for deletion.
|
||||
size_t DeleteFiles(const RepoPath& path, const AZStd::string& pattern)
|
||||
{
|
||||
size_t numFilesDeleted = 0;
|
||||
|
||||
AZ::IO::SystemFile::FindFiles(
|
||||
AZStd::string::format("%s/%s", path.c_str(), pattern.c_str()).c_str(),
|
||||
[&path, &numFilesDeleted](const char* file, bool isFile)
|
||||
{
|
||||
if (isFile)
|
||||
{
|
||||
AZ::IO::SystemFile::Delete(AZStd::string::format("%s/%s", path.c_str(), file).c_str());
|
||||
numFilesDeleted++;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return numFilesDeleted;
|
||||
}
|
||||
|
||||
//! Deletes the specified file.
|
||||
void DeleteFile(const RepoPath& file)
|
||||
{
|
||||
DeleteFiles(file.ParentPath(), file.Filename().Native());
|
||||
}
|
||||
|
||||
//! User-friendly names for the test suite types.
|
||||
AZStd::string SuiteTypeAsString(SuiteType suiteType)
|
||||
{
|
||||
switch (suiteType)
|
||||
{
|
||||
case SuiteType::Main:
|
||||
return "main";
|
||||
case SuiteType::Periodic:
|
||||
return "periodic";
|
||||
case SuiteType::Sandbox:
|
||||
return "sandbox";
|
||||
default:
|
||||
throw(Exception("Unexpected suite type"));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string SequenceReportTypeAsString(Client::SequenceReportType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Client::SequenceReportType::RegularSequence:
|
||||
return "regular";
|
||||
case Client::SequenceReportType::SeedSequence:
|
||||
return "seed";
|
||||
case Client::SequenceReportType::ImpactAnalysisSequence:
|
||||
return "impact_analysis";
|
||||
case Client::SequenceReportType::SafeImpactAnalysisSequence:
|
||||
return "safe_impact_analysis";
|
||||
default:
|
||||
throw(Exception(AZStd::string::format("Unexpected sequence report type: %u", aznumeric_cast<AZ::u32>(type))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TestSequenceResultAsString(TestSequenceResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case TestSequenceResult::Failure:
|
||||
return "failure";
|
||||
case TestSequenceResult::Success:
|
||||
return "success";
|
||||
case TestSequenceResult::Timeout:
|
||||
return "timeout";
|
||||
default:
|
||||
throw(Exception(AZStd::string::format("Unexpected test sequence result: %u", aznumeric_cast<AZ::u32>(result))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TestRunResultAsString(Client::TestRunResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case Client::TestRunResult::AllTestsPass:
|
||||
return "all_tests_pass";
|
||||
case Client::TestRunResult::FailedToExecute:
|
||||
return "failed_to_execute";
|
||||
case Client::TestRunResult::NotRun:
|
||||
return "not_run";
|
||||
case Client::TestRunResult::TestFailures:
|
||||
return "test_failures";
|
||||
case Client::TestRunResult::Timeout:
|
||||
return "timeout";
|
||||
default:
|
||||
throw(Exception(AZStd::string::format("Unexpected test run result: %u", aznumeric_cast<AZ::u32>(result))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string ExecutionFailurePolicyAsString(Policy::ExecutionFailure executionFailurePolicy)
|
||||
{
|
||||
switch (executionFailurePolicy)
|
||||
{
|
||||
case Policy::ExecutionFailure::Abort:
|
||||
return "abort";
|
||||
case Policy::ExecutionFailure::Continue:
|
||||
return "continue";
|
||||
case Policy::ExecutionFailure::Ignore:
|
||||
return "ignore";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected execution failure policy: %u", aznumeric_cast<AZ::u32>(executionFailurePolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage failedTestCoveragePolicy)
|
||||
{
|
||||
switch (failedTestCoveragePolicy)
|
||||
{
|
||||
case Policy::FailedTestCoverage::Discard:
|
||||
return "discard";
|
||||
case Policy::FailedTestCoverage::Keep:
|
||||
return "keep";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected failed test coverage policy: %u", aznumeric_cast<AZ::u32>(failedTestCoveragePolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TestPrioritizationPolicyAsString(Policy::TestPrioritization testPrioritizationPolicy)
|
||||
{
|
||||
switch (testPrioritizationPolicy)
|
||||
{
|
||||
case Policy::TestPrioritization::DependencyLocality:
|
||||
return "dependency_locality";
|
||||
case Policy::TestPrioritization::None:
|
||||
return "none";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected test prioritization policy: %u", aznumeric_cast<AZ::u32>(testPrioritizationPolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TestFailurePolicyAsString(Policy::TestFailure testFailurePolicy)
|
||||
{
|
||||
switch (testFailurePolicy)
|
||||
{
|
||||
case Policy::TestFailure::Abort:
|
||||
return "abort";
|
||||
case Policy::TestFailure::Continue:
|
||||
return "continue";
|
||||
default:
|
||||
throw(
|
||||
Exception(AZStd::string::format("Unexpected test failure policy: %u", aznumeric_cast<AZ::u32>(testFailurePolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string IntegrityFailurePolicyAsString(Policy::IntegrityFailure integrityFailurePolicy)
|
||||
{
|
||||
switch (integrityFailurePolicy)
|
||||
{
|
||||
case Policy::IntegrityFailure::Abort:
|
||||
return "abort";
|
||||
case Policy::IntegrityFailure::Continue:
|
||||
return "continue";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected integration failure policy: %u", aznumeric_cast<AZ::u32>(integrityFailurePolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap dynamicDependencyMapPolicy)
|
||||
{
|
||||
switch (dynamicDependencyMapPolicy)
|
||||
{
|
||||
case Policy::DynamicDependencyMap::Discard:
|
||||
return "discard";
|
||||
case Policy::DynamicDependencyMap::Update:
|
||||
return "update";
|
||||
default:
|
||||
throw(Exception(AZStd::string::format(
|
||||
"Unexpected dynamic dependency map policy: %u", aznumeric_cast<AZ::u32>(dynamicDependencyMapPolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TestShardingPolicyAsString(Policy::TestSharding testShardingPolicy)
|
||||
{
|
||||
switch (testShardingPolicy)
|
||||
{
|
||||
case Policy::TestSharding::Always:
|
||||
return "always";
|
||||
case Policy::TestSharding::Never:
|
||||
return "never";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected test sharding policy: %u", aznumeric_cast<AZ::u32>(testShardingPolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture targetOutputCapturePolicy)
|
||||
{
|
||||
switch (targetOutputCapturePolicy)
|
||||
{
|
||||
case Policy::TargetOutputCapture::File:
|
||||
return "file";
|
||||
case Policy::TargetOutputCapture::None:
|
||||
return "none";
|
||||
case Policy::TargetOutputCapture::StdOut:
|
||||
return "stdout";
|
||||
case Policy::TargetOutputCapture::StdOutAndFile:
|
||||
return "stdout_file";
|
||||
default:
|
||||
throw(Exception(
|
||||
AZStd::string::format("Unexpected target output capture policy: %u", aznumeric_cast<AZ::u32>(targetOutputCapturePolicy))));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string ClientTestResultAsString(Client::TestResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case Client::TestResult::Failed:
|
||||
return "failed";
|
||||
case Client::TestResult::NotRun:
|
||||
return "not_run";
|
||||
case Client::TestResult::Passed:
|
||||
return "passed";
|
||||
default:
|
||||
throw(Exception(AZStd::string::format("Unexpected client test case result: %u", aznumeric_cast<AZ::u32>(result))));
|
||||
}
|
||||
}
|
||||
} // namespace TestImpact
|
||||
@@ -16,11 +16,14 @@ set(FILES
|
||||
Include/TestImpactFramework/TestImpactChangelist.h
|
||||
Include/TestImpactFramework/TestImpactChangelistSerializer.h
|
||||
Include/TestImpactFramework/TestImpactChangelistException.h
|
||||
Include/TestImpactFramework/TestImpactPolicy.h
|
||||
Include/TestImpactFramework/TestImpactTestSequence.h
|
||||
Include/TestImpactFramework/TestImpactClientTestSelection.h
|
||||
Include/TestImpactFramework/TestImpactClientTestRun.h
|
||||
Include/TestImpactFramework/TestImpactClientSequenceReport.h
|
||||
Include/TestImpactFramework/TestImpactFileUtils.h
|
||||
Include/TestImpactFramework/TestImpactUtils.h
|
||||
Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h
|
||||
Include/TestImpactFramework/TestImpactSequenceReportException.h
|
||||
Source/Artifact/TestImpactArtifactException.h
|
||||
Source/Artifact/Factory/TestImpactBuildTargetDescriptorFactory.cpp
|
||||
Source/Artifact/Factory/TestImpactBuildTargetDescriptorFactory.h
|
||||
@@ -125,5 +128,7 @@ set(FILES
|
||||
Source/TestImpactClientTestRun.cpp
|
||||
Source/TestImpactClientSequenceReport.cpp
|
||||
Source/TestImpactChangeListSerializer.cpp
|
||||
Source/TestImpactClientSequenceReportSerializer.cpp
|
||||
Source/TestImpactRepoPath.cpp
|
||||
Source/TestImpactUtils.cpp
|
||||
)
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace AWSCore
|
||||
// assigned to a specific CPU starting with the specified CPU.
|
||||
AZ::JobManagerDesc jobManagerDesc{};
|
||||
AZ::JobManagerThreadDesc threadDesc(m_firstThreadCPU, m_threadPriority, m_threadStackSize);
|
||||
for (unsigned int i = 0; i < m_threadCount; ++i)
|
||||
for (int i = 0; i < m_threadCount; ++i)
|
||||
{
|
||||
jobManagerDesc.m_workerThreads.push_back(threadDesc);
|
||||
if (threadDesc.m_cpuId > -1)
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace AWSCore
|
||||
AZStd::chrono::seconds lastSendTimeStamp = AZStd::chrono::seconds(lastSendTimeStampSeconds);
|
||||
AZStd::chrono::seconds secondsSinceLastSend =
|
||||
AZStd::chrono::duration_cast<AZStd::chrono::seconds>(AZStd::chrono::system_clock::now().time_since_epoch()) - lastSendTimeStamp;
|
||||
if (secondsSinceLastSend.count() >= delayInSeconds)
|
||||
if (static_cast<AZ::u64>(secondsSinceLastSend.count()) >= delayInSeconds)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace AWSMetrics
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_metricsMutex);
|
||||
m_metricsQueue.AddMetrics(metricsEvent);
|
||||
|
||||
if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes())
|
||||
if (m_metricsQueue.GetSizeInBytes() >= static_cast<size_t>(m_clientConfiguration->GetMaxQueueSizeInBytes()))
|
||||
{
|
||||
// Flush the metrics queue when the accumulated metrics size hits the limit
|
||||
m_waitEvent.release();
|
||||
@@ -431,7 +431,7 @@ namespace AWSMetrics
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_metricsMutex);
|
||||
m_metricsQueue.AddMetrics(offlineRecords[index]);
|
||||
|
||||
if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes())
|
||||
if (m_metricsQueue.GetSizeInBytes() >= static_cast<size_t>(m_clientConfiguration->GetMaxQueueSizeInBytes()))
|
||||
{
|
||||
// Flush the metrics queue when the accumulated metrics size hits the limit
|
||||
m_waitEvent.release();
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace AWSMetrics
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int metricsIndex = 0; metricsIndex < doc.Size(); metricsIndex++)
|
||||
for (rapidjson::SizeType metricsIndex = 0; metricsIndex < doc.Size(); metricsIndex++)
|
||||
{
|
||||
MetricsEvent metrics;
|
||||
if (!metrics.ReadFromJson(doc[metricsIndex]))
|
||||
|
||||
@@ -28,9 +28,15 @@ namespace AZ
|
||||
//! Dump the PipelineStatistics from passes to a json file.
|
||||
virtual bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) = 0;
|
||||
|
||||
//! Dump the Cpu Profiling Statistics to a json file.
|
||||
//! Dump a single frame of Cpu profiling data
|
||||
virtual bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) = 0;
|
||||
|
||||
//! Start a multiframe capture of CPU profiling data.
|
||||
virtual bool BeginContinuousCpuProfilingCapture() = 0;
|
||||
|
||||
//! End and dump an in-progress continuous capture.
|
||||
virtual bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) = 0;
|
||||
|
||||
//! Dump the benchmark metadata to a json file.
|
||||
virtual bool CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) = 0;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationSettings.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -157,14 +158,15 @@ namespace AZ
|
||||
Name m_groupName;
|
||||
Name m_regionName;
|
||||
uint16_t m_stackDepth;
|
||||
AZStd::sys_time_t m_elapsedInNanoseconds;
|
||||
AZStd::sys_time_t m_startTick;
|
||||
AZStd::sys_time_t m_endTick;
|
||||
};
|
||||
|
||||
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
CpuProfilingStatisticsSerializer() = default;
|
||||
CpuProfilingStatisticsSerializer(const RHI::CpuProfiler::TimeRegionMap& timeRegionMap);
|
||||
CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData);
|
||||
|
||||
AZStd::vector<CpuProfilingStatisticsSerializerEntry> m_cpuProfilingStatisticsSerializerEntries;
|
||||
};
|
||||
@@ -327,17 +329,20 @@ namespace AZ
|
||||
|
||||
// --- CpuProfilingStatisticsSerializer ---
|
||||
|
||||
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const RHI::CpuProfiler::TimeRegionMap& timeRegionMap)
|
||||
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData)
|
||||
{
|
||||
// Create serializable entries
|
||||
for (auto& threadEntry : timeRegionMap)
|
||||
for (const auto& timeRegionMap : continuousData)
|
||||
{
|
||||
for (auto& cachedRegionEntry : threadEntry.second)
|
||||
for (const auto& threadEntry : timeRegionMap)
|
||||
{
|
||||
m_cpuProfilingStatisticsSerializerEntries.insert(
|
||||
m_cpuProfilingStatisticsSerializerEntries.end(),
|
||||
cachedRegionEntry.second.begin(),
|
||||
cachedRegionEntry.second.end());
|
||||
for (const auto& cachedRegionEntry : threadEntry.second)
|
||||
{
|
||||
m_cpuProfilingStatisticsSerializerEntries.insert(
|
||||
m_cpuProfilingStatisticsSerializerEntries.end(),
|
||||
cachedRegionEntry.second.begin(),
|
||||
cachedRegionEntry.second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,19 +364,11 @@ namespace AZ
|
||||
|
||||
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion)
|
||||
{
|
||||
// Converts ticks to Nanoseconds
|
||||
static const auto ticksToNanoSeconds = [](AZStd::sys_time_t elapsedInTicks) -> AZStd::sys_time_t
|
||||
{
|
||||
const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond();
|
||||
|
||||
const AZStd::sys_time_t timeInNanoseconds = (elapsedInTicks * 1000000) / (ticksPerSecond / 1000);
|
||||
return timeInNanoseconds;
|
||||
};
|
||||
|
||||
m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName;
|
||||
m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName;
|
||||
m_stackDepth = cachedTimeRegion.m_stackDepth;
|
||||
m_elapsedInNanoseconds = ticksToNanoSeconds(cachedTimeRegion.m_endTick - cachedTimeRegion.m_startTick);
|
||||
m_startTick = cachedTimeRegion.m_startTick;
|
||||
m_endTick = cachedTimeRegion.m_endTick;
|
||||
}
|
||||
|
||||
void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context)
|
||||
@@ -383,7 +380,8 @@ namespace AZ
|
||||
->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName)
|
||||
->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName)
|
||||
->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth)
|
||||
->Field("elapsedInNanoseconds", &CpuProfilingStatisticsSerializerEntry::m_elapsedInNanoseconds)
|
||||
->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick)
|
||||
->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -474,6 +472,12 @@ namespace AZ
|
||||
TickBus::Handler::BusDisconnect();
|
||||
|
||||
ProfilingCaptureRequestBus::Handler::BusDisconnect();
|
||||
|
||||
// Block deactivation until the IO thread has finished serializing the CPU data
|
||||
if (m_cpuDataSerializationThread.joinable())
|
||||
{
|
||||
m_cpuDataSerializationThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool ProfilingCaptureSystemComponent::CapturePassTimestamp(const AZStd::string& outputFilePath)
|
||||
@@ -641,6 +645,43 @@ namespace AZ
|
||||
return captureStarted;
|
||||
}
|
||||
|
||||
bool SerializeCpuProfilingData(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& data, AZStd::string outputFilePath, bool wasEnabled)
|
||||
{
|
||||
AZ_TracePrintf("ProfilingCaptureSystemComponent", "Beginning serialization of %zu frames of profiling data\n", data.size());
|
||||
JsonSerializerSettings serializationSettings;
|
||||
serializationSettings.m_keepDefaults = true;
|
||||
|
||||
CpuProfilingStatisticsSerializer serializer(data);
|
||||
|
||||
const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer,
|
||||
outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings);
|
||||
|
||||
AZStd::string captureInfo = outputFilePath;
|
||||
if (!saveResult.IsSuccess())
|
||||
{
|
||||
captureInfo = AZStd::string::format("Failed to save Cpu Profiling Statistics data to file '%s'. Error: %s",
|
||||
outputFilePath.c_str(),
|
||||
saveResult.GetError().c_str());
|
||||
AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str());
|
||||
}
|
||||
|
||||
// Disable the profiler again
|
||||
if (!wasEnabled)
|
||||
{
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
|
||||
}
|
||||
|
||||
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
|
||||
ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
|
||||
saveResult.IsSuccess(),
|
||||
captureInfo);
|
||||
return saveResult.IsSuccess();
|
||||
}
|
||||
|
||||
bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath)
|
||||
{
|
||||
// Start the cpu profiling
|
||||
@@ -652,40 +693,10 @@ namespace AZ
|
||||
|
||||
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]()
|
||||
{
|
||||
JsonSerializerSettings serializationSettings;
|
||||
serializationSettings.m_keepDefaults = true;
|
||||
|
||||
// Get time Cpu profiled time regions
|
||||
const RHI::CpuProfiler::TimeRegionMap& timeRegionMap = RHI::CpuProfiler::Get()->GetTimeRegionMap();
|
||||
|
||||
CpuProfilingStatisticsSerializer serializer(timeRegionMap);
|
||||
const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer,
|
||||
outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings);
|
||||
|
||||
AZStd::string captureInfo = outputFilePath;
|
||||
if (!saveResult.IsSuccess())
|
||||
{
|
||||
captureInfo = AZStd::string::format("Failed to save Cpu Profiling Statistics data to file '%s'. Error: %s",
|
||||
outputFilePath.c_str(),
|
||||
saveResult.GetError().c_str());
|
||||
AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str());
|
||||
}
|
||||
|
||||
// Disable the profiler again
|
||||
if (!wasEnabled)
|
||||
{
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
|
||||
}
|
||||
|
||||
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
|
||||
ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
|
||||
saveResult.IsSuccess(),
|
||||
captureInfo);
|
||||
|
||||
// Blocking call for a single frame of data, avoid thread overhead
|
||||
AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap> singleFrameData;
|
||||
singleFrameData.push_back(RHI::CpuProfiler::Get()->GetTimeRegionMap());
|
||||
SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled);
|
||||
});
|
||||
|
||||
// Start the TickBus.
|
||||
@@ -697,6 +708,53 @@ namespace AZ
|
||||
return captureStarted;
|
||||
}
|
||||
|
||||
bool ProfilingCaptureSystemComponent::BeginContinuousCpuProfilingCapture()
|
||||
{
|
||||
return AZ::RHI::CpuProfiler::Get()->BeginContinuousCapture();
|
||||
}
|
||||
|
||||
bool ProfilingCaptureSystemComponent::EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath)
|
||||
{
|
||||
bool expected = false;
|
||||
if (m_cpuDataSerializationInProgress.compare_exchange_strong(expected, true))
|
||||
{
|
||||
AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap> captureResult;
|
||||
const bool captureEnded = AZ::RHI::CpuProfiler::Get()->EndContinuousCapture(captureResult);
|
||||
if (!captureEnded)
|
||||
{
|
||||
AZ_TracePrintf("ProfilingCaptureSystemComponent", "Could not end the continuous capture, is one in progress?\n");
|
||||
m_cpuDataSerializationInProgress.store(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// cpuProfilingData could be 1GB+ once saved, so use an IO thread to write it to disk.
|
||||
auto threadIoFunction =
|
||||
[data = AZStd::move(captureResult), filePath = AZStd::string(outputFilePath), &flag = m_cpuDataSerializationInProgress]()
|
||||
{
|
||||
SerializeCpuProfilingData(data, filePath, true);
|
||||
flag.store(false);
|
||||
};
|
||||
|
||||
// If the thread object already exists (ex. we have already serialized data), join. This will not block since
|
||||
// m_cpuDataSerializationInProgress was false, meaning the IO thread has already completed execution.
|
||||
// TODO Use a reusable thread implementation over repeated creation + destruction of threads [ATOM-16214]
|
||||
if (m_cpuDataSerializationThread.joinable())
|
||||
{
|
||||
m_cpuDataSerializationThread.join();
|
||||
}
|
||||
|
||||
auto thread = AZStd::thread(threadIoFunction);
|
||||
m_cpuDataSerializationThread = AZStd::move(thread);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ_TracePrintf(
|
||||
"ProfilingSystemCaptureComponent",
|
||||
"Cannot end a continuous capture - another serialization is currently in progress\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProfilingCaptureSystemComponent::CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath)
|
||||
{
|
||||
const bool captureStarted = m_benchmarkMetadataCapture.StartCapture([this, benchmarkName, outputFilePath]()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
|
||||
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -71,6 +72,8 @@ namespace AZ
|
||||
bool CaptureCpuFrameTime(const AZStd::string& outputFilePath) override;
|
||||
bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) override;
|
||||
bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) override;
|
||||
bool BeginContinuousCpuProfilingCapture() override;
|
||||
bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) override;
|
||||
bool CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) override;
|
||||
|
||||
private:
|
||||
@@ -86,6 +89,11 @@ namespace AZ
|
||||
DelayedQueryCaptureHelper m_pipelineStatisticsCapture;
|
||||
DelayedQueryCaptureHelper m_cpuProfilingStatisticsCapture;
|
||||
DelayedQueryCaptureHelper m_benchmarkMetadataCapture;
|
||||
|
||||
// Flag passed by reference to the CPU profiling data serialization job, blocks new continuous capture requests when set.
|
||||
AZStd::atomic_bool m_cpuDataSerializationInProgress = false;
|
||||
|
||||
AZStd::thread m_cpuDataSerializationThread;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/ring_buffer.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
@@ -82,6 +83,14 @@ namespace AZ
|
||||
//! Get the last frame's TimeRegionMap
|
||||
virtual const TimeRegionMap& GetTimeRegionMap() const = 0;
|
||||
|
||||
//! Begin a continuous capture. Blocks the profiler from being toggled off until EndContinuousCapture is called.
|
||||
[[nodiscard]] virtual bool BeginContinuousCapture() = 0;
|
||||
|
||||
//! Flush the CPU Profiler's saved data into the passed ring buffer .
|
||||
[[nodiscard]] virtual bool EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget) = 0;
|
||||
|
||||
virtual bool IsContinuousCaptureInProgress() const = 0;
|
||||
|
||||
//! Enable/Disable the CpuProfiler
|
||||
virtual void SetProfilerEnabled(bool enabled) = 0;
|
||||
|
||||
|
||||
@@ -106,13 +106,18 @@ namespace AZ
|
||||
void OnSystemTick() final override;
|
||||
|
||||
//! CpuProfiler overrides...
|
||||
void BeginTimeRegion(TimeRegion& timeRegion) final;
|
||||
void EndTimeRegion() final;
|
||||
const TimeRegionMap& GetTimeRegionMap() const final;
|
||||
void SetProfilerEnabled(bool enabled) final;
|
||||
bool IsProfilerEnabled() const final;
|
||||
void BeginTimeRegion(TimeRegion& timeRegion) final override;
|
||||
void EndTimeRegion() final override;
|
||||
const TimeRegionMap& GetTimeRegionMap() const final override;
|
||||
bool BeginContinuousCapture() final override;
|
||||
bool EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget) final override;
|
||||
bool IsContinuousCaptureInProgress() const final override;
|
||||
void SetProfilerEnabled(bool enabled) final override;
|
||||
bool IsProfilerEnabled() const final override;
|
||||
|
||||
private:
|
||||
static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps
|
||||
|
||||
// Lazily create and register the local thread data
|
||||
void RegisterThreadStorage();
|
||||
|
||||
@@ -134,6 +139,14 @@ namespace AZ
|
||||
AZStd::shared_mutex m_shutdownMutex;
|
||||
|
||||
bool m_initialized = false;
|
||||
|
||||
AZStd::mutex m_continuousCaptureEndingMutex;
|
||||
|
||||
AZStd::atomic_bool m_continuousCaptureInProgress;
|
||||
|
||||
// Stores multiple frames of profiling data, size is controlled by MaxFramesToSave. Flushed when EndContinuousCapture is called.
|
||||
// Ring buffer so that we can have fast append of new data + removal of old profiling data with good cache locality.
|
||||
AZStd::ring_buffer<TimeRegionMap> m_continuousCaptureData;
|
||||
};
|
||||
|
||||
}; // namespace RPI
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace AZ
|
||||
Interface<CpuProfiler>::Register(this);
|
||||
m_initialized = true;
|
||||
SystemTickBus::Handler::BusConnect();
|
||||
m_continuousCaptureData.set_capacity(10);
|
||||
}
|
||||
|
||||
void CpuProfilerImpl::Shutdown()
|
||||
@@ -101,6 +102,8 @@ namespace AZ
|
||||
m_registeredThreads.clear();
|
||||
m_timeRegionMap.clear();
|
||||
m_initialized = false;
|
||||
m_continuousCaptureInProgress.store(false);
|
||||
m_continuousCaptureData.clear();
|
||||
SystemTickBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
@@ -141,12 +144,54 @@ namespace AZ
|
||||
return m_timeRegionMap;
|
||||
}
|
||||
|
||||
bool CpuProfilerImpl::BeginContinuousCapture()
|
||||
{
|
||||
bool expected = false;
|
||||
if (m_continuousCaptureInProgress.compare_exchange_strong(expected, true))
|
||||
{
|
||||
m_enabled = true;
|
||||
AZ_TracePrintf("Profiler", "Continuous capture started\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ_TracePrintf("Profiler", "Attempting to start a continuous capture while one already in progress");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CpuProfilerImpl::EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget)
|
||||
{
|
||||
if (!m_continuousCaptureInProgress.load())
|
||||
{
|
||||
AZ_TracePrintf("Profiler", "Attempting to end a continuous capture while one not in progress");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_continuousCaptureEndingMutex.try_lock())
|
||||
{
|
||||
m_enabled = false;
|
||||
flushTarget = AZStd::move(m_continuousCaptureData);
|
||||
m_continuousCaptureData.clear();
|
||||
AZ_TracePrintf("Profiler", "Continuous capture ended\n");
|
||||
m_continuousCaptureInProgress.store(false);
|
||||
|
||||
m_continuousCaptureEndingMutex.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CpuProfilerImpl::IsContinuousCaptureInProgress() const
|
||||
{
|
||||
return m_continuousCaptureInProgress.load();
|
||||
}
|
||||
|
||||
void CpuProfilerImpl::SetProfilerEnabled(bool enabled)
|
||||
{
|
||||
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
|
||||
|
||||
// Early out if the state is already the same
|
||||
if (m_enabled == enabled)
|
||||
// Early out if the state is already the same or a continuous capture is in progress
|
||||
if (m_enabled == enabled || m_continuousCaptureInProgress.load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -179,6 +224,20 @@ namespace AZ
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_continuousCaptureInProgress.load() && m_continuousCaptureEndingMutex.try_lock())
|
||||
{
|
||||
if (m_continuousCaptureData.full() && m_continuousCaptureData.size() != MaxFramesToSave)
|
||||
{
|
||||
const AZStd::size_t size = m_continuousCaptureData.size();
|
||||
m_continuousCaptureData.set_capacity(AZStd::min(MaxFramesToSave, size + size / 2));
|
||||
}
|
||||
|
||||
m_continuousCaptureData.push_back(AZStd::move(m_timeRegionMap));
|
||||
m_timeRegionMap.clear();
|
||||
m_continuousCaptureEndingMutex.unlock();
|
||||
}
|
||||
|
||||
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
|
||||
|
||||
// Iterate through all the threads, and collect the thread's cached time regions
|
||||
|
||||
@@ -110,9 +110,6 @@ namespace AZ
|
||||
//! Value returned is 1.0f when an area equal to the viewport height squared is covered. Useful for accurate LOD decisions.
|
||||
float CalculateSphereAreaInClipSpace(const AZ::Vector3& sphereWorldPosition, float sphereRadius) const;
|
||||
|
||||
//! Invalidate the view srg to rebuild the srg.
|
||||
void InvalidateSrg();
|
||||
|
||||
const AZ::Name& GetName() const { return m_name; }
|
||||
const UsageFlags GetUsageFlags() { return m_usageFlags; }
|
||||
|
||||
@@ -192,9 +189,6 @@ namespace AZ
|
||||
// Clip space offset for camera jitter with taa
|
||||
Vector2 m_clipSpaceOffset = Vector2(0.0f, 0.0f);
|
||||
|
||||
// Flags whether view matrices are dirty which requires rebuild srg
|
||||
bool m_needBuildSrg = true;
|
||||
|
||||
MatrixChangedEvent m_onWorldToClipMatrixChange;
|
||||
MatrixChangedEvent m_onWorldToViewMatrixChange;
|
||||
|
||||
|
||||
@@ -126,8 +126,6 @@ namespace AZ
|
||||
|
||||
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
|
||||
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
|
||||
|
||||
InvalidateSrg();
|
||||
}
|
||||
|
||||
AZ::Transform View::GetCameraTransform() const
|
||||
@@ -170,8 +168,6 @@ namespace AZ
|
||||
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
|
||||
}
|
||||
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
|
||||
|
||||
InvalidateSrg();
|
||||
}
|
||||
|
||||
void View::SetViewToClipMatrix(const AZ::Matrix4x4& viewToClip)
|
||||
@@ -202,14 +198,11 @@ namespace AZ
|
||||
m_unprojectionConstants.SetW(float(tanHalfFovY));
|
||||
|
||||
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
|
||||
|
||||
InvalidateSrg();
|
||||
}
|
||||
|
||||
void View::SetClipSpaceOffset(float xOffset, float yOffset)
|
||||
{
|
||||
m_clipSpaceOffset.Set(xOffset, yOffset);
|
||||
InvalidateSrg();
|
||||
}
|
||||
|
||||
const AZ::Matrix4x4& View::GetWorldToViewMatrix() const
|
||||
@@ -362,58 +355,49 @@ namespace AZ
|
||||
return -0.25f * cotHalfFovYSq * AZ::Constants::Pi * radiusSq * sqrt(fabsf((distanceSq - radiusSq)/radiusSqSubDepthSq))/radiusSqSubDepthSq;
|
||||
}
|
||||
|
||||
void View::InvalidateSrg()
|
||||
{
|
||||
m_needBuildSrg = true;
|
||||
}
|
||||
|
||||
void View::UpdateSrg()
|
||||
{
|
||||
if (m_needBuildSrg)
|
||||
if (m_clipSpaceOffset.IsZero())
|
||||
{
|
||||
if (m_clipSpaceOffset.IsZero())
|
||||
{
|
||||
Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix;
|
||||
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Offset the current and previous frame clip matricies
|
||||
Matrix4x4 offsetViewToClipMatrix = m_viewToClipMatrix;
|
||||
offsetViewToClipMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
|
||||
offsetViewToClipMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
|
||||
|
||||
Matrix4x4 offsetViewToClipPrevMatrix = m_viewToClipPrevMatrix;
|
||||
offsetViewToClipPrevMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
|
||||
offsetViewToClipPrevMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
|
||||
|
||||
// Build other matricies dependent on the view to clip matricies
|
||||
Matrix4x4 offsetWorldToClipMatrix = offsetViewToClipMatrix * m_worldToViewMatrix;
|
||||
Matrix4x4 offsetWorldToClipPrevMatrix = offsetViewToClipPrevMatrix * m_worldToViewPrevMatrix;
|
||||
|
||||
Matrix4x4 offsetClipToViewMatrix = offsetViewToClipMatrix.GetInverseFull();
|
||||
Matrix4x4 offsetClipToWorldMatrix = m_viewToWorldMatrix * offsetClipToViewMatrix;
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull());
|
||||
}
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position);
|
||||
m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull());
|
||||
m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ);
|
||||
m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants);
|
||||
|
||||
m_shaderResourceGroup->Compile();
|
||||
m_needBuildSrg = false;
|
||||
Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix;
|
||||
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Offset the current and previous frame clip matricies
|
||||
Matrix4x4 offsetViewToClipMatrix = m_viewToClipMatrix;
|
||||
offsetViewToClipMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
|
||||
offsetViewToClipMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
|
||||
|
||||
Matrix4x4 offsetViewToClipPrevMatrix = m_viewToClipPrevMatrix;
|
||||
offsetViewToClipPrevMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
|
||||
offsetViewToClipPrevMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
|
||||
|
||||
// Build other matricies dependent on the view to clip matricies
|
||||
Matrix4x4 offsetWorldToClipMatrix = offsetViewToClipMatrix * m_worldToViewMatrix;
|
||||
Matrix4x4 offsetWorldToClipPrevMatrix = offsetViewToClipPrevMatrix * m_worldToViewPrevMatrix;
|
||||
|
||||
Matrix4x4 offsetClipToViewMatrix = offsetViewToClipMatrix.GetInverseFull();
|
||||
Matrix4x4 offsetClipToWorldMatrix = m_viewToWorldMatrix * offsetClipToViewMatrix;
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull());
|
||||
}
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position);
|
||||
m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix);
|
||||
m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull());
|
||||
m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ);
|
||||
m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants);
|
||||
|
||||
m_shaderResourceGroup->Compile();
|
||||
|
||||
m_viewToClipPrevMatrix = m_viewToClipMatrix;
|
||||
m_worldToViewPrevMatrix = m_worldToViewMatrix;
|
||||
|
||||
@@ -129,6 +129,34 @@ namespace AZ
|
||||
m_captureToFile = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
bool isInProgress = RHI::CpuProfiler::Get()->IsContinuousCaptureInProgress();
|
||||
if (ImGui::Button(isInProgress ? "End" : "Begin"))
|
||||
{
|
||||
if (isInProgress)
|
||||
{
|
||||
AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond();
|
||||
AZStd::string timeString;
|
||||
AZStd::to_string(timeString, timeNow);
|
||||
u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick();
|
||||
const AZStd::string frameDataFilePath = AZStd::string::format(
|
||||
"@user@/CpuProfiler/%s_%llu.json",
|
||||
timeString.c_str(),
|
||||
currentTick);
|
||||
char resolvedPath[AZ::IO::MaxPathLength];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength);
|
||||
m_lastCapturedFilePath = resolvedPath;
|
||||
AZ::Render::ProfilingCaptureRequestBus::Broadcast(
|
||||
&AZ::Render::ProfilingCaptureRequestBus::Events::EndContinuousCpuProfilingCapture, frameDataFilePath);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
AZ::Render::ProfilingCaptureRequestBus::Broadcast(
|
||||
&AZ::Render::ProfilingCaptureRequestBus::Events::BeginContinuousCpuProfilingCapture);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_lastCapturedFilePath.empty())
|
||||
{
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -254,8 +254,8 @@ int AZ::FontRenderer::GetGlyph(GlyphBitmap* glyphBitmap, int* horizontalAdvance,
|
||||
const int textureSlotBufferHeight = glyphBitmap->GetHeight();
|
||||
|
||||
// might happen if font characters are too big or cache dimenstions in font.xml is too small "<font path="VeraMono.ttf" w="320" h="368"/>"
|
||||
const bool charWidthFits = iX + m_glyph->bitmap.width <= textureSlotBufferWidth;
|
||||
const bool charHeightFits = iY + m_glyph->bitmap.rows <= textureSlotBufferHeight;
|
||||
const bool charWidthFits = static_cast<int>(iX + m_glyph->bitmap.width) <= textureSlotBufferWidth;
|
||||
const bool charHeightFits = static_cast<int>(iY + m_glyph->bitmap.rows) <= textureSlotBufferHeight;
|
||||
const bool charFitsInSlot = charWidthFits && charHeightFits;
|
||||
AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", characterCode);
|
||||
|
||||
|
||||
@@ -450,7 +450,7 @@ namespace Blast
|
||||
const auto buffer = m_asset.GetAccelerator()->fillDebugRender(-1, mode == DebugRenderAabbTreeSegments);
|
||||
if (buffer.lineCount)
|
||||
{
|
||||
for (int i = 0; i < buffer.lineCount; ++i)
|
||||
for (uint32_t i = 0; i < buffer.lineCount; ++i)
|
||||
{
|
||||
auto& line = buffer.lines[i];
|
||||
AZ::Color color;
|
||||
|
||||
@@ -562,7 +562,7 @@ namespace Blast
|
||||
public:
|
||||
FakeEntityProvider(uint32_t entityCount)
|
||||
{
|
||||
for (int i = 0; i < entityCount; ++i)
|
||||
for (uint32 i = 0; i < entityCount; ++i)
|
||||
{
|
||||
m_entities.push_back(AZStd::make_shared<AZ::Entity>());
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ namespace CommandSystem
|
||||
void MetaData::GenerateNodeGroupMetaData(EMotionFX::Actor* actor, AZStd::string& outMetaDataString)
|
||||
{
|
||||
AZStd::string nodeNameList;
|
||||
const AZ::u32 numNodeGroups = actor->GetNumNodeGroups();
|
||||
for (uint32 i = 0; i < numNodeGroups; ++i)
|
||||
const size_t numNodeGroups = actor->GetNumNodeGroups();
|
||||
for (size_t i = 0; i < numNodeGroups; ++i)
|
||||
{
|
||||
EMotionFX::NodeGroup* nodeGroup = actor->GetNodeGroup(i);
|
||||
outMetaDataString += AZStd::string::format("AddNodeGroup -actorID $(ACTORID) -name \"%s\"\n", nodeGroup->GetName());
|
||||
|
||||
nodeNameList.clear();
|
||||
const AZ::u16 numNodes = nodeGroup->GetNumNodes();
|
||||
for (AZ::u16 n = 0; n < numNodes; ++n)
|
||||
const size_t numNodes = nodeGroup->GetNumNodes();
|
||||
for (size_t n = 0; n < numNodes; ++n)
|
||||
{
|
||||
const AZ::u16 nodeIndex = nodeGroup->GetNode(n);
|
||||
EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeIndex);
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace CommandSystem
|
||||
{
|
||||
if (*m_nodeAction == NodeAction::Replace)
|
||||
{
|
||||
nodeGroup->GetNodeArray().Clear();
|
||||
nodeGroup->GetNodeArray().clear();
|
||||
}
|
||||
for (const AZStd::string& nodeName : *m_nodeNames)
|
||||
{
|
||||
@@ -146,12 +146,12 @@ namespace CommandSystem
|
||||
if (m_nodeNames.has_value())
|
||||
{
|
||||
// clear previous nodes
|
||||
nodeGroup->GetNodeArray().Clear();
|
||||
const uint16 numNodes = m_oldNodeGroup->GetNumNodes();
|
||||
nodeGroup->GetNodeArray().clear();
|
||||
const size_t numNodes = m_oldNodeGroup->GetNumNodes();
|
||||
nodeGroup->SetNumNodes(numNodes);
|
||||
|
||||
// add all nodes to the group
|
||||
for (uint16 i = 0; i < numNodes; ++i)
|
||||
for (size_t i = 0; i < numNodes; ++i)
|
||||
{
|
||||
nodeGroup->SetNode(i, m_oldNodeGroup->GetNode(i));
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace ExporterLib
|
||||
{
|
||||
chunkHeader.m_sizeInBytes += sizeof(EMotionFX::FileFormat::Actor_NodeGroup);
|
||||
chunkHeader.m_sizeInBytes += GetStringChunkSize(nodeGroup->GetNameString());
|
||||
chunkHeader.m_sizeInBytes += sizeof(uint16) * nodeGroup->GetNumNodes();
|
||||
chunkHeader.m_sizeInBytes += sizeof(uint16) * aznumeric_cast<uint32>(nodeGroup->GetNumNodes());
|
||||
}
|
||||
|
||||
// endian conversion
|
||||
@@ -277,14 +277,14 @@ namespace ExporterLib
|
||||
MCORE_ASSERT(actor);
|
||||
|
||||
// get the number of node groups
|
||||
const uint32 numGroups = actor->GetNumNodeGroups();
|
||||
const size_t numGroups = actor->GetNumNodeGroups();
|
||||
|
||||
// create the node group array and reserve some elements
|
||||
AZStd::vector<EMotionFX::NodeGroup*> nodeGroups;
|
||||
nodeGroups.reserve(numGroups);
|
||||
|
||||
// iterate through the node groups and add them to the array
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
for (size_t i = 0; i < numGroups; ++i)
|
||||
{
|
||||
nodeGroups.emplace_back(actor->GetNodeGroup(i));
|
||||
}
|
||||
|
||||
@@ -142,9 +142,9 @@ namespace EMotionFX
|
||||
result->RecursiveAddDependencies(this);
|
||||
|
||||
// clone all nodes groups
|
||||
for (uint32 i = 0; i < m_nodeGroups.GetLength(); ++i)
|
||||
for (const NodeGroup* nodeGroup : m_nodeGroups)
|
||||
{
|
||||
result->AddNodeGroup(aznew NodeGroup(*m_nodeGroups[i]));
|
||||
result->AddNodeGroup(aznew NodeGroup(*nodeGroup));
|
||||
}
|
||||
|
||||
// clone the materials
|
||||
@@ -948,12 +948,11 @@ namespace EMotionFX
|
||||
// remove all node groups
|
||||
void Actor::RemoveAllNodeGroups()
|
||||
{
|
||||
const uint32 numGroups = m_nodeGroups.GetLength();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
for (NodeGroup*& nodeGroup : m_nodeGroups)
|
||||
{
|
||||
delete m_nodeGroups[i];
|
||||
delete nodeGroup;
|
||||
}
|
||||
m_nodeGroups.Clear();
|
||||
m_nodeGroups.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1965,13 +1964,13 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
|
||||
uint32 Actor::GetNumNodeGroups() const
|
||||
size_t Actor::GetNumNodeGroups() const
|
||||
{
|
||||
return m_nodeGroups.GetLength();
|
||||
return m_nodeGroups.size();
|
||||
}
|
||||
|
||||
|
||||
NodeGroup* Actor::GetNodeGroup(uint32 index) const
|
||||
NodeGroup* Actor::GetNodeGroup(size_t index) const
|
||||
{
|
||||
return m_nodeGroups[index];
|
||||
}
|
||||
@@ -1979,90 +1978,76 @@ namespace EMotionFX
|
||||
|
||||
void Actor::AddNodeGroup(NodeGroup* newGroup)
|
||||
{
|
||||
m_nodeGroups.Add(newGroup);
|
||||
m_nodeGroups.emplace_back(newGroup);
|
||||
}
|
||||
|
||||
|
||||
void Actor::RemoveNodeGroup(uint32 index, bool delFromMem)
|
||||
void Actor::RemoveNodeGroup(size_t index, bool delFromMem)
|
||||
{
|
||||
if (delFromMem)
|
||||
{
|
||||
delete m_nodeGroups[index];
|
||||
}
|
||||
|
||||
m_nodeGroups.Remove(index);
|
||||
m_nodeGroups.erase(AZStd::next(begin(m_nodeGroups), index));
|
||||
}
|
||||
|
||||
|
||||
void Actor::RemoveNodeGroup(NodeGroup* group, bool delFromMem)
|
||||
{
|
||||
m_nodeGroups.RemoveByValue(group);
|
||||
if (delFromMem)
|
||||
const auto found = AZStd::find(begin(m_nodeGroups), end(m_nodeGroups), group);
|
||||
if (found != end(m_nodeGroups))
|
||||
{
|
||||
delete group;
|
||||
m_nodeGroups.erase(found);
|
||||
if (delFromMem)
|
||||
{
|
||||
delete group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find a group index by its name
|
||||
uint32 Actor::FindNodeGroupIndexByName(const char* groupName) const
|
||||
size_t Actor::FindNodeGroupIndexByName(const char* groupName) const
|
||||
{
|
||||
const uint32 numGroups = m_nodeGroups.GetLength();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup)
|
||||
{
|
||||
if (m_nodeGroups[i]->GetNameString() == groupName)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return MCORE_INVALIDINDEX32;
|
||||
return nodeGroup->GetNameString() == groupName;
|
||||
});
|
||||
return found != end(m_nodeGroups) ? AZStd::distance(begin(m_nodeGroups), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
|
||||
// find a group index by its name, but not case sensitive
|
||||
uint32 Actor::FindNodeGroupIndexByNameNoCase(const char* groupName) const
|
||||
size_t Actor::FindNodeGroupIndexByNameNoCase(const char* groupName) const
|
||||
{
|
||||
const uint32 numGroups = m_nodeGroups.GetLength();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup)
|
||||
{
|
||||
if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return MCORE_INVALIDINDEX32;
|
||||
return AzFramework::StringFunc::Equal(nodeGroup->GetNameString(), groupName, false /* no case */);
|
||||
});
|
||||
return found != end(m_nodeGroups) ? AZStd::distance(begin(m_nodeGroups), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
|
||||
// find a group by its name
|
||||
NodeGroup* Actor::FindNodeGroupByName(const char* groupName) const
|
||||
{
|
||||
const uint32 numGroups = m_nodeGroups.GetLength();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup)
|
||||
{
|
||||
if (m_nodeGroups[i]->GetNameString() == groupName)
|
||||
{
|
||||
return m_nodeGroups[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nodeGroup->GetNameString() == groupName;
|
||||
});
|
||||
return found != end(m_nodeGroups) ? *found : nullptr;
|
||||
}
|
||||
|
||||
|
||||
// find a group by its name, but without case sensitivity
|
||||
NodeGroup* Actor::FindNodeGroupByNameNoCase(const char* groupName) const
|
||||
{
|
||||
const uint32 numGroups = m_nodeGroups.GetLength();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup)
|
||||
{
|
||||
if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */))
|
||||
{
|
||||
return m_nodeGroups[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return AzFramework::StringFunc::Equal(nodeGroup->GetNameString(), groupName, false /* no case */);
|
||||
});
|
||||
return found != end(m_nodeGroups) ? *found : nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
// include MCore related files
|
||||
#include <MCore/Source/Vector.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <MCore/Source/SmallArray.h>
|
||||
#include <MCore/Source/Distance.h>
|
||||
|
||||
// include required headers
|
||||
@@ -567,13 +566,13 @@ namespace EMotionFX
|
||||
* Get the number of node groups inside this actor object.
|
||||
* @result The number of node groups.
|
||||
*/
|
||||
uint32 GetNumNodeGroups() const;
|
||||
size_t GetNumNodeGroups() const;
|
||||
|
||||
/**
|
||||
* Get a pointer to a given node group.
|
||||
* @param index The node group index, which must be in range of [0..GetNumNodeGroups()-1].
|
||||
*/
|
||||
NodeGroup* GetNodeGroup(uint32 index) const;
|
||||
NodeGroup* GetNodeGroup(size_t index) const;
|
||||
|
||||
/**
|
||||
* Add a node group.
|
||||
@@ -586,7 +585,7 @@ namespace EMotionFX
|
||||
* @param index The node group number to remove. This value must be in range of [0..GetNumNodeGroups()-1].
|
||||
* @param delFromMem Set to true (default) when you wish to also delete the specified group from memory.
|
||||
*/
|
||||
void RemoveNodeGroup(uint32 index, bool delFromMem = true);
|
||||
void RemoveNodeGroup(size_t index, bool delFromMem = true);
|
||||
|
||||
/**
|
||||
* Remove a given node group by its pointer.
|
||||
@@ -601,14 +600,14 @@ namespace EMotionFX
|
||||
* @param groupName The name of the group to search for. This is case sensitive.
|
||||
* @result The group number, or MCORE_INVALIDINDEX32 when it cannot be found.
|
||||
*/
|
||||
uint32 FindNodeGroupIndexByName(const char* groupName) const;
|
||||
size_t FindNodeGroupIndexByName(const char* groupName) const;
|
||||
|
||||
/**
|
||||
* Find a group index by its name, on a non-case sensitive way.
|
||||
* @param groupName The name of the group to search for. This is NOT case sensitive.
|
||||
* @result The group number, or MCORE_INVALIDINDEX32 when it cannot be found.
|
||||
*/
|
||||
uint32 FindNodeGroupIndexByNameNoCase(const char* groupName) const;
|
||||
size_t FindNodeGroupIndexByNameNoCase(const char* groupName) const;
|
||||
|
||||
/**
|
||||
* Find a node group by its name.
|
||||
@@ -925,7 +924,7 @@ namespace EMotionFX
|
||||
AZStd::vector<NodeMirrorInfo> m_nodeMirrorInfos; /**< The array of node mirror info. */
|
||||
AZStd::vector< AZStd::vector< Material* > > m_materials; /**< A collection of materials (for each lod). */
|
||||
AZStd::vector< MorphSetup* > m_morphSetups; /**< A morph setup for each geometry LOD. */
|
||||
MCore::SmallArray<NodeGroup*> m_nodeGroups; /**< The set of node groups. */
|
||||
AZStd::vector<NodeGroup*> m_nodeGroups; /**< The set of node groups. */
|
||||
AZStd::shared_ptr<PhysicsSetup> m_physicsSetup; /**< Hit detection, ragdoll and cloth colliders, joint limits and rigid bodies. */
|
||||
AZStd::shared_ptr<SimulatedObjectSetup> m_simulatedObjectSetup; /**< Setup for simulated objects */
|
||||
MCore::Distance::EUnitType m_unitType; /**< The unit type used on export. */
|
||||
|
||||
@@ -84,8 +84,8 @@ namespace EMotionFX
|
||||
EnableAllNodes();
|
||||
|
||||
// apply actor node group default states (disable groups of nodes that are disabled on default)
|
||||
const uint32 numGroups = m_actor->GetNumNodeGroups();
|
||||
for (uint32 i = 0; i < numGroups; ++i)
|
||||
const size_t numGroups = m_actor->GetNumNodeGroups();
|
||||
for (size_t i = 0; i < numGroups; ++i)
|
||||
{
|
||||
if (m_actor->GetNodeGroup(i)->GetIsEnabledOnDefault() == false) // if this group is disabled on default
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace EMotionFX
|
||||
AZ_CLASS_ALLOCATOR_IMPL(NodeGroup, NodeAllocator, 0)
|
||||
|
||||
|
||||
NodeGroup::NodeGroup(const AZStd::string& groupName, uint16 numNodes, bool enabledOnDefault)
|
||||
NodeGroup::NodeGroup(const AZStd::string& groupName, size_t numNodes, bool enabledOnDefault)
|
||||
: m_name(groupName)
|
||||
, m_nodes(numNodes)
|
||||
, m_enabledOnDefault(enabledOnDefault)
|
||||
@@ -47,28 +47,28 @@ namespace EMotionFX
|
||||
|
||||
|
||||
// set the number of nodes
|
||||
void NodeGroup::SetNumNodes(const uint16 numNodes)
|
||||
void NodeGroup::SetNumNodes(const size_t numNodes)
|
||||
{
|
||||
m_nodes.Resize(numNodes);
|
||||
m_nodes.resize(numNodes);
|
||||
}
|
||||
|
||||
|
||||
// get the number of nodes
|
||||
uint16 NodeGroup::GetNumNodes() const
|
||||
size_t NodeGroup::GetNumNodes() const
|
||||
{
|
||||
return static_cast<uint16>(m_nodes.GetLength());
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
|
||||
// set a given node to a given node number
|
||||
void NodeGroup::SetNode(uint16 index, uint16 nodeIndex)
|
||||
void NodeGroup::SetNode(size_t index, uint16 nodeIndex)
|
||||
{
|
||||
m_nodes[index] = nodeIndex;
|
||||
}
|
||||
|
||||
|
||||
// get the node number of a given index
|
||||
uint16 NodeGroup::GetNode(uint16 index) const
|
||||
uint16 NodeGroup::GetNode(size_t index) const
|
||||
{
|
||||
return m_nodes[index];
|
||||
}
|
||||
@@ -77,10 +77,9 @@ namespace EMotionFX
|
||||
// enable all nodes in the group inside a given actor instance
|
||||
void NodeGroup::EnableNodes(ActorInstance* targetActorInstance)
|
||||
{
|
||||
const uint16 numNodes = static_cast<uint16>(m_nodes.GetLength());
|
||||
for (uint16 i = 0; i < numNodes; ++i)
|
||||
for (uint16 node : m_nodes)
|
||||
{
|
||||
targetActorInstance->EnableNode(m_nodes[i]);
|
||||
targetActorInstance->EnableNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +87,9 @@ namespace EMotionFX
|
||||
// disable all nodes in the group inside a given actor instance
|
||||
void NodeGroup::DisableNodes(ActorInstance* targetActorInstance)
|
||||
{
|
||||
const uint16 numNodes = static_cast<uint16>(m_nodes.GetLength());
|
||||
for (uint16 i = 0; i < numNodes; ++i)
|
||||
for (uint16 node : m_nodes)
|
||||
{
|
||||
targetActorInstance->DisableNode(m_nodes[i]);
|
||||
targetActorInstance->DisableNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,26 +97,29 @@ namespace EMotionFX
|
||||
// add a given node to the group (performs a realloc internally)
|
||||
void NodeGroup::AddNode(uint16 nodeIndex)
|
||||
{
|
||||
m_nodes.Add(nodeIndex);
|
||||
m_nodes.emplace_back(nodeIndex);
|
||||
}
|
||||
|
||||
|
||||
// remove a given node by its node number
|
||||
void NodeGroup::RemoveNodeByNodeIndex(uint16 nodeIndex)
|
||||
{
|
||||
m_nodes.RemoveByValue(nodeIndex);
|
||||
if (const auto found = AZStd::find(begin(m_nodes), end(m_nodes), nodeIndex); found)
|
||||
{
|
||||
m_nodes.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// remove a given array element from the list of nodes
|
||||
void NodeGroup::RemoveNodeByGroupIndex(uint16 index)
|
||||
void NodeGroup::RemoveNodeByGroupIndex(size_t index)
|
||||
{
|
||||
m_nodes.Remove(index);
|
||||
m_nodes.erase(AZStd::next(begin(m_nodes), index));
|
||||
}
|
||||
|
||||
|
||||
// get the node array directly
|
||||
MCore::SmallArray<uint16>& NodeGroup::GetNodeArray()
|
||||
AZStd::vector<uint16>& NodeGroup::GetNodeArray()
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user