Add deserialization to sequence reports. (#4018)

* Add deserialization to sequence reports.

Signed-off-by: John <jonawals@amazon.com>

* Address PR comments.

Signed-off-by: John <jonawals@amazon.com>

* Address PR comments.

Signed-off-by: John <jonawals@amazon.com>

* Address PR comments.

Signed-off-by: John <jonawals@amazon.com>

* Revert last change.

Signed-off-by: John <jonawals@amazon.com>
This commit is contained in:
jonawals
2021-09-17 12:41:19 +01:00
committed by GitHub
parent 9a71a902d0
commit c28bc7c6d8
6 changed files with 684 additions and 159 deletions
@@ -122,12 +122,14 @@ namespace TestImpact
};
//! Base class for all sequence report types.
template<typename PolicyStateType>
template<SequenceReportType Type, typename PolicyStateType>
class SequenceReportBase
{
public:
static constexpr SequenceReportType ReportType = Type;
using PolicyState = PolicyStateType;
//! 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).
@@ -136,33 +138,49 @@ namespace TestImpact
//! @param selectedTestRuns The target names of the selected test runs.
//! @param selectedTestRunReport The report for the set of selected test runs.
SequenceReportBase(
SequenceReportType type,
size_t maxConcurrency,
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
const PolicyStateType& policyState,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
PolicyStateType policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
TestRunReport&& selectedTestRunReport)
: m_type(type)
, m_maxConcurrency(maxConcurrency)
, m_testTargetTimeout(testTargetTimeout)
, m_globalTimeout(globalTimeout)
, m_policyState(policyState)
TestRunSelection selectedTestRuns,
TestRunReport selectedTestRunReport)
: m_maxConcurrency(maxConcurrency)
, m_testTargetTimeout(AZStd::move(testTargetTimeout))
, m_globalTimeout(AZStd::move(globalTimeout))
, m_policyState(AZStd::move(policyState))
, m_suite(suiteType)
, m_selectedTestRuns(selectedTestRuns)
, m_selectedTestRuns(AZStd::move(selectedTestRuns))
, m_selectedTestRunReport(AZStd::move(selectedTestRunReport))
{
}
virtual ~SequenceReportBase() = default;
//! Returns the identifying type for this sequence report.
SequenceReportType GetType() const
SequenceReportBase(SequenceReportBase&& report)
: SequenceReportBase(
AZStd::move(report.m_maxConcurrency),
AZStd::move(report.m_testTargetTimeout),
AZStd::move(report.m_globalTimeout),
AZStd::move(report.m_policyState),
AZStd::move(report.m_suite),
AZStd::move(report.m_selectedTestRuns),
AZStd::move(report.m_selectedTestRunReport))
{
return m_type;
}
SequenceReportBase(const SequenceReportBase& report)
: SequenceReportBase(
report.m_maxConcurrency,
report.m_testTargetTimeout,
report.m_globalTimeout,
report.m_policyState,
report.m_suite,
report.m_selectedTestRuns,
report.m_selectedTestRunReport)
{
}
virtual ~SequenceReportBase() = default;
//! Returns the maximum concurrency for this sequence.
size_t GetMaxConcurrency() const
{
@@ -284,7 +302,6 @@ namespace TestImpact
}
private:
SequenceReportType m_type;
size_t m_maxConcurrency = 0;
AZStd::optional<AZStd::chrono::milliseconds> m_testTargetTimeout;
AZStd::optional<AZStd::chrono::milliseconds> m_globalTimeout;
@@ -296,58 +313,27 @@ namespace TestImpact
//! Report type for regular test sequences.
class RegularSequenceReport
: public SequenceReportBase<SequencePolicyState>
: public SequenceReportBase<SequenceReportType::RegularSequence, SequencePolicyState>
{
public:
//! 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 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);
using SequenceReportBase::SequenceReportBase;
};
//! Report type for seed test sequences.
class SeedSequenceReport
: public SequenceReportBase<SequencePolicyState>
: public SequenceReportBase<SequenceReportType::SeedSequence, 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);
using SequenceReportBase::SequenceReportBase;
};
//! Report detailing a test run sequence of selected and drafted tests.
template<typename PolicyStateType>
template<SequenceReportType Type, typename PolicyStateType>
class DraftingSequenceReportBase
: public SequenceReportBase<PolicyStateType>
: public SequenceReportBase<Type, 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).
@@ -358,18 +344,16 @@ namespace TestImpact
//! @param selectedTestRunReport The report for the set of selected test runs.
//! @param draftedTestRunReport The report for the set of drafted test runs.
DraftingSequenceReportBase(
SequenceReportType type,
size_t maxConcurrency,
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
const PolicyStateType& policyState,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
PolicyStateType policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
const AZStd::vector<AZStd::string>& draftedTestRuns,
TestRunSelection selectedTestRuns,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& draftedTestRunReport)
: SequenceReportBase<PolicyStateType> (
type,
: SequenceReportBase<Type, PolicyStateType>(
maxConcurrency,
testTargetTimeout,
globalTimeout,
@@ -377,7 +361,17 @@ namespace TestImpact
suiteType,
selectedTestRuns,
AZStd::move(selectedTestRunReport))
, m_draftedTestRuns(draftedTestRuns)
, m_draftedTestRuns(AZStd::move(draftedTestRuns))
, m_draftedTestRunReport(AZStd::move(draftedTestRunReport))
{
}
DraftingSequenceReportBase(
SequenceReportBase<Type, PolicyStateType>&& report,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& draftedTestRunReport)
: SequenceReportBase<Type, PolicyStateType>(AZStd::move(report))
, m_draftedTestRuns(AZStd::move(draftedTestRuns))
, m_draftedTestRunReport(AZStd::move(draftedTestRunReport))
{
}
@@ -456,7 +450,7 @@ namespace TestImpact
//! Report detailing an impact analysis sequence of selected, discarded and drafted tests.
class ImpactAnalysisSequenceReport
: public DraftingSequenceReportBase<ImpactAnalysisSequencePolicyState>
: public DraftingSequenceReportBase<SequenceReportType::ImpactAnalysisSequence, ImpactAnalysisSequencePolicyState>
{
public:
//! Constructs the report for an impact analysis sequence.
@@ -471,16 +465,18 @@ namespace TestImpact
//! @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,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
ImpactAnalysisSequencePolicyState policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
const AZStd::vector<AZStd::string>& discardedTestRuns,
const AZStd::vector<AZStd::string>& draftedTestRuns,
TestRunSelection selectedTestRuns,
AZStd::vector<AZStd::string> discardedTestRuns,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& draftedTestRunReport);
ImpactAnalysisSequenceReport(DraftingSequenceReportBase&& report, AZStd::vector<AZStd::string> discardedTestRuns);
//! Returns the test runs discarded from running in the sequence.
const AZStd::vector<AZStd::string>& GetDiscardedTestRuns() const;
private:
@@ -489,7 +485,7 @@ namespace TestImpact
//! Report detailing an impact analysis sequence of selected, discarded and drafted test runs.
class SafeImpactAnalysisSequenceReport
: public DraftingSequenceReportBase<SafeImpactAnalysisSequencePolicyState>
: public DraftingSequenceReportBase<SequenceReportType::SafeImpactAnalysisSequence, SafeImpactAnalysisSequencePolicyState>
{
public:
//! Constructs the report for a sequence of selected, discarded and drafted test runs.
@@ -506,17 +502,20 @@ namespace TestImpact
//! @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,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
SafeImpactAnalysisSequencePolicyState policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
const TestRunSelection& discardedTestRuns,
const AZStd::vector<AZStd::string>& draftedTestRuns,
TestRunSelection selectedTestRuns,
TestRunSelection discardedTestRuns,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& discardedTestRunReport,
TestRunReport&& draftedTestRunReport);
SafeImpactAnalysisSequenceReport(
DraftingSequenceReportBase&& report, TestRunSelection discardedTestRuns, TestRunReport&& discardedTestRunReport);
// SequenceReport overrides ...
AZStd::chrono::milliseconds GetDuration() const override;
TestSequenceResult GetResult() const override;
@@ -14,15 +14,27 @@
namespace TestImpact
{
//! Serializes a regular sequence report to JSON format.
//! Serializes a regular sequence report to Json format.
AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport);
//! Serializes a seed sequence report to JSON format.
//! Serializes a seed sequence report to Json format.
AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport);
//! Serializes an impact analysis sequence report to JSON format.
//! 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.
//! Serializes a safe impact analysis sequence report to Json format.
AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport);
//! Deserialize a regular sequence report from Json format.
Client::RegularSequenceReport DeserializeRegularSequenceReport(const AZStd::string& sequenceReportJson);
//! Deserialize a seed sequence report from Json format.
Client::SeedSequenceReport DeserializeSeedSequenceReport(const AZStd::string& sequenceReportJson);
//! Deserialize an impact analysis sequence report from Json format.
Client::ImpactAnalysisSequenceReport DeserializeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson);
//! Deserialize a safe impact analysis sequence report from Json format.
Client::SafeImpactAnalysisSequenceReport DeserializeSafeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson);
} // namespace TestImpact
@@ -103,4 +103,43 @@ namespace TestImpact
//! User-friendly names for the client test result types.
AZStd::string ClientTestResultAsString(Client::TestResult result);
//! User-friendly names for the suite types.
SuiteType SuiteTypeFromString(const AZStd::string& suiteType);
//! Returns the sequence report type for the specified string.
Client::SequenceReportType SequenceReportTypeFromString(const AZStd::string& type);
//! Returns the test run result for the specified string.
Client::TestRunResult TestRunResultFromString(const AZStd::string& result);
//! Returns the test result for the specified string.
Client::TestResult TestResultFromString(const AZStd::string& result);
//! Returns the test sequence result for the specified string.
TestSequenceResult TestSequenceResultFromString(const AZStd::string& result);
//! Returns the execution failure policy for the specified string.
Policy::ExecutionFailure ExecutionFailurePolicyFromString(const AZStd::string& executionFailurePolicy);
//! Returns the failed test coverage policy for the specified string.
Policy::FailedTestCoverage FailedTestCoveragePolicyFromString(const AZStd::string& failedTestCoveragePolicy);
//! Returns the test prioritization policy for the specified string.
Policy::TestPrioritization TestPrioritizationPolicyFromString(const AZStd::string& testPrioritizationPolicy);
//! Returns the test failure policy for the specified string.
Policy::TestFailure TestFailurePolicyFromString(const AZStd::string& testFailurePolicy);
//! Returns the integrity failure policy for the specified string.
Policy::IntegrityFailure IntegrityFailurePolicyFromString(const AZStd::string& integrityFailurePolicy);
//! Returns the dynamic dependency map policy for the specified string.
Policy::DynamicDependencyMap DynamicDependencyMapPolicyFromString(const AZStd::string& dynamicDependencyMapPolicy);
//! Returns the test sharding policy for the specified string.
Policy::TestSharding TestShardingPolicyFromString(const AZStd::string& testShardingPolicy);
//! Returns the target output capture policy for the specified string.
Policy::TargetOutputCapture TargetOutputCapturePolicyFromString(const AZStd::string& targetOutputCapturePolicy);
} // namespace TestImpact
@@ -159,69 +159,35 @@ namespace TestImpact
return m_totalNumDisabledTests;
}
RegularSequenceReport::RegularSequenceReport(
ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport(
size_t maxConcurrency,
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
const SequencePolicyState& policyState,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
ImpactAnalysisSequencePolicyState policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
TestRunReport&& selectedTestRunReport)
: SequenceReportBase(
SequenceReportType::RegularSequence,
maxConcurrency,
testTargetTimeout,
globalTimeout,
policyState,
suiteType,
selectedTestRuns,
AZStd::move(selectedTestRunReport))
{
}
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))
TestRunSelection selectedTestRuns,
AZStd::vector<AZStd::string> discardedTestRuns,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& draftedTestRunReport)
: DraftingSequenceReportBase(
maxConcurrency,
AZStd::move(testTargetTimeout),
AZStd::move(globalTimeout),
AZStd::move(policyState),
suiteType,
AZStd::move(selectedTestRuns),
AZStd::move(draftedTestRuns),
AZStd::move(selectedTestRunReport),
AZStd::move(draftedTestRunReport))
, m_discardedTestRuns(discardedTestRuns)
{
}
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& selectedTestRuns,
const AZStd::vector<AZStd::string>& discardedTestRuns,
const AZStd::vector<AZStd::string>& draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& draftedTestRunReport)
: DraftingSequenceReportBase(
SequenceReportType::ImpactAnalysisSequence,
maxConcurrency,
testTargetTimeout,
globalTimeout,
policyState,
suiteType,
selectedTestRuns,
draftedTestRuns,
AZStd::move(selectedTestRunReport),
AZStd::move(draftedTestRunReport))
, m_discardedTestRuns(discardedTestRuns)
DraftingSequenceReportBase&& report, AZStd::vector<AZStd::string> discardedTestRuns)
: DraftingSequenceReportBase(AZStd::move(report))
, m_discardedTestRuns(AZStd::move(discardedTestRuns))
{
}
@@ -232,25 +198,24 @@ namespace TestImpact
SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport(
size_t maxConcurrency,
const AZStd::optional<AZStd::chrono::milliseconds>& testTargetTimeout,
const AZStd::optional<AZStd::chrono::milliseconds>& globalTimeout,
const SafeImpactAnalysisSequencePolicyState& policyState,
AZStd::optional<AZStd::chrono::milliseconds> testTargetTimeout,
AZStd::optional<AZStd::chrono::milliseconds> globalTimeout,
SafeImpactAnalysisSequencePolicyState policyState,
SuiteType suiteType,
const TestRunSelection& selectedTestRuns,
const TestRunSelection& discardedTestRuns,
const AZStd::vector<AZStd::string>& draftedTestRuns,
TestRunSelection selectedTestRuns,
TestRunSelection discardedTestRuns,
AZStd::vector<AZStd::string> draftedTestRuns,
TestRunReport&& selectedTestRunReport,
TestRunReport&& discardedTestRunReport,
TestRunReport&& draftedTestRunReport)
: DraftingSequenceReportBase(
SequenceReportType::SafeImpactAnalysisSequence,
maxConcurrency,
testTargetTimeout,
globalTimeout,
policyState,
AZStd::move(testTargetTimeout),
AZStd::move(globalTimeout),
AZStd::move(policyState),
suiteType,
selectedTestRuns,
draftedTestRuns,
AZStd::move(selectedTestRuns),
AZStd::move(draftedTestRuns),
AZStd::move(selectedTestRunReport),
AZStd::move(draftedTestRunReport))
, m_discardedTestRuns(discardedTestRuns)
@@ -258,6 +223,14 @@ namespace TestImpact
{
}
SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport(
DraftingSequenceReportBase&& report, TestRunSelection discardedTestRuns, TestRunReport&& discardedTestRunReport)
: DraftingSequenceReportBase(AZStd::move(report))
, m_discardedTestRuns(AZStd::move(discardedTestRuns))
, m_discardedTestRunReport(AZStd::move(discardedTestRunReport))
{
}
TestSequenceResult SafeImpactAnalysisSequenceReport::GetResult() const
{
return CalculateMultiTestSequenceResult({ DraftingSequenceReportBase::GetResult(), m_discardedTestRunReport.GetResult() });
@@ -21,7 +21,7 @@ namespace TestImpact
{
namespace SequenceReportFields
{
// Keys for pertinent JSON node and attribute names
// Keys for pertinent Json node and attribute names
constexpr const char* Keys[] =
{
"name",
@@ -417,13 +417,13 @@ namespace TestImpact
writer.String(DynamicDependencyMapPolicyAsString(policyState.m_dynamicDependencyMap).c_str());
}
template<typename PolicyStateType>
template<typename SequenceReportBaseType>
void SerializeSequenceReportBaseMembers(
const Client::SequenceReportBase<PolicyStateType>& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
const SequenceReportBaseType& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
// Type
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Type]);
writer.String(SequenceReportTypeAsString(sequenceReport.GetType()).c_str());
writer.String(SequenceReportTypeAsString(sequenceReport.ReportType).c_str());
// Test target timeout
writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]);
@@ -510,9 +510,9 @@ namespace TestImpact
writer.Uint64(sequenceReport.GetTotalNumDisabledTests());
}
template<typename PolicyStateType>
template<typename DraftingSequenceReportBaseType>
void SerializeDraftingSequenceReportMembers(
const Client::DraftingSequenceReportBase<PolicyStateType>& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
const DraftingSequenceReportBaseType& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
SerializeSequenceReportBaseMembers(sequenceReport, writer);
@@ -603,4 +603,254 @@ namespace TestImpact
return stringBuffer.GetString();
}
AZStd::chrono::high_resolution_clock::time_point TimePointFromMsInt64(AZ::s64 ms)
{
return AZStd::chrono::high_resolution_clock::time_point(AZStd::chrono::milliseconds(ms));
}
AZStd::vector<Client::Test> DeserializeTests(const rapidjson::Value& serialTests)
{
AZStd::vector<Client::Test> tests;
tests.reserve(serialTests[SequenceReportFields::Keys[SequenceReportFields::Tests]].GetArray().Size());
for (const auto& test : serialTests[SequenceReportFields::Keys[SequenceReportFields::Tests]].GetArray())
{
const AZStd::string name = test[SequenceReportFields::Keys[SequenceReportFields::Name]].GetString();
const auto result = TestResultFromString(test[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString());
tests.emplace_back(name, result);
}
return tests;
}
Client::TestRunBase DeserializeTestRunBase(const rapidjson::Value& serialTestRun)
{
return Client::TestRunBase(
serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Name]].GetString(),
serialTestRun[SequenceReportFields::Keys[SequenceReportFields::CommandArgs]].GetString(),
TimePointFromMsInt64(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::StartTime]].GetInt64()),
AZStd::chrono::milliseconds(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Duration]].GetInt64()),
TestRunResultFromString(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString()));
}
template<typename TestRunType>
AZStd::vector<TestRunType> DeserializeTestRuns(const rapidjson::Value& serialTestRuns)
{
AZStd::vector<TestRunType> testRuns;
testRuns.reserve(serialTestRuns.GetArray().Size());
for (const auto& testRun : serialTestRuns.GetArray())
{
testRuns.emplace_back(DeserializeTestRunBase(testRun));
}
return testRuns;
}
template<typename CompletedTestRunType>
AZStd::vector<CompletedTestRunType> DeserializeCompletedTestRuns(const rapidjson::Value& serialCompletedTestRuns)
{
AZStd::vector<CompletedTestRunType> testRuns;
testRuns.reserve(serialCompletedTestRuns.GetArray().Size());
for (const auto& testRun : serialCompletedTestRuns.GetArray())
{
testRuns.emplace_back(
DeserializeTestRunBase(testRun), DeserializeTests(testRun[SequenceReportFields::Keys[SequenceReportFields::Tests]]));
}
return testRuns;
}
Client::TestRunReport DeserializeTestRunReport(const rapidjson::Value& serialTestRunReport)
{
return Client::TestRunReport(
TestSequenceResultFromString(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString()),
TimePointFromMsInt64(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::StartTime]].GetInt64()),
AZStd::chrono::milliseconds(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::Duration]].GetInt64()),
DeserializeCompletedTestRuns<Client::PassingTestRun>(
serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::PassingTestRuns]]),
DeserializeCompletedTestRuns<Client::FailingTestRun>(
serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::FailingTestRuns]]),
DeserializeTestRuns<Client::TestRunWithExecutionFailure>(
serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::ExecutionFailureTestRuns]]),
DeserializeTestRuns<Client::TimedOutTestRun>(
serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::TimedOutTestRuns]]),
DeserializeTestRuns<Client::UnexecutedTestRun>(
serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::UnexecutedTestRuns]]));
}
Client::TestRunSelection DeserializeTestSelection(const rapidjson::Value& serialTestRunSelection)
{
const auto extractTestTargetNames = [](const rapidjson::Value& serialTestTargets)
{
AZStd::vector<AZStd::string> testTargets;
testTargets.reserve(serialTestTargets.GetArray().Size());
for (const auto& testTarget : serialTestTargets.GetArray())
{
testTargets.emplace_back(testTarget.GetString());
}
return testTargets;
};
return Client::TestRunSelection(
extractTestTargetNames(serialTestRunSelection[SequenceReportFields::Keys[SequenceReportFields::IncludedTestRuns]]),
extractTestTargetNames(serialTestRunSelection[SequenceReportFields::Keys[SequenceReportFields::ExcludedTestRuns]]));
}
PolicyStateBase DeserializePolicyStateBaseMembers(const rapidjson::Value& serialPolicyState)
{
return
{
ExecutionFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::ExecutionFailure]].GetString()),
FailedTestCoveragePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::CoverageFailure]].GetString()),
TestFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestFailure]].GetString()),
IntegrityFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::IntegrityFailure]].GetString()),
TestShardingPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestSharding]].GetString()),
TargetOutputCapturePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TargetOutputCapture]].GetString())
};
}
SequencePolicyState DeserializePolicyStateMembers(const rapidjson::Value& serialPolicyState)
{
return { DeserializePolicyStateBaseMembers(serialPolicyState) };
}
SafeImpactAnalysisSequencePolicyState DeserializeSafeImpactAnalysisPolicyStateMembers(const rapidjson::Value& serialPolicyState)
{
return
{
DeserializePolicyStateBaseMembers(serialPolicyState),
TestPrioritizationPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]].GetString())
};
}
ImpactAnalysisSequencePolicyState DeserializeImpactAnalysisSequencePolicyStateMembers(const rapidjson::Value& serialPolicyState)
{
return
{
DeserializePolicyStateBaseMembers(serialPolicyState),
TestPrioritizationPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]].GetString()),
DynamicDependencyMapPolicyFromString(
serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::DynamicDependencyMap]].GetString())
};
}
template<typename PolicyStateType>
PolicyStateType DeserializePolicyStateType(const rapidjson::Value& serialPolicyStateType)
{
if constexpr (AZStd::is_same_v<PolicyStateType, SequencePolicyState>)
{
return DeserializePolicyStateMembers(serialPolicyStateType);
}
else if constexpr (AZStd::is_same_v<PolicyStateType, SafeImpactAnalysisSequencePolicyState>)
{
return DeserializeSafeImpactAnalysisPolicyStateMembers(serialPolicyStateType);
}
else if constexpr (AZStd::is_same_v<PolicyStateType, ImpactAnalysisSequencePolicyState>)
{
return DeserializeImpactAnalysisSequencePolicyStateMembers(serialPolicyStateType);
}
else
{
static_assert(false, "Template paramater must be a valid policy state type");
}
}
template<typename SequenceReportBaseType>
SequenceReportBaseType DeserialiseSequenceReportBase(const rapidjson::Value& serialSequenceReportBase)
{
const auto type = SequenceReportTypeFromString(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Type]].GetString());
AZ_TestImpact_Eval(
type == SequenceReportBaseType::ReportType,
SequenceReportException, AZStd::string::format(
"The JSON sequence report type '%s' does not match the constructed report type",
serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Type]].GetString()));
const auto testTargetTimeout =
serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]].GetUint64();
const auto globalTimeout =
serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::GlobalTimeout]].GetUint64();
return SequenceReportBaseType(
serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::MaxConcurrency]].GetUint64(),
testTargetTimeout ? AZStd::optional<AZStd::chrono::milliseconds>{ testTargetTimeout } : AZStd::nullopt,
globalTimeout ? AZStd::optional<AZStd::chrono::milliseconds>{ globalTimeout } : AZStd::nullopt,
DeserializePolicyStateType<SequenceReportBaseType::PolicyState>(serialSequenceReportBase),
SuiteTypeFromString(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Suite]].GetString()),
DeserializeTestSelection(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::SelectedTestRuns]]),
DeserializeTestRunReport(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::SelectedTestRunReport]]));
}
template<typename DerivedDraftingSequenceReportType>
Client::DraftingSequenceReportBase<DerivedDraftingSequenceReportType::ReportType, typename DerivedDraftingSequenceReportType::PolicyState>
DeserializeDraftingSequenceReportBase(const rapidjson::Value& serialDraftingSequenceReportBase)
{
AZStd::vector<AZStd::string> draftingTestRuns;
draftingTestRuns.reserve(
serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]].GetArray().Size());
for (const auto& testRun :
serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]].GetArray())
{
draftingTestRuns.emplace_back(testRun.GetString());
}
using SequenceBase =
Client::SequenceReportBase<DerivedDraftingSequenceReportType::ReportType, typename DerivedDraftingSequenceReportType::PolicyState>;
using DraftingSequenceBase =
Client::DraftingSequenceReportBase<DerivedDraftingSequenceReportType::ReportType, typename DerivedDraftingSequenceReportType::PolicyState>;
return DraftingSequenceBase(
DeserialiseSequenceReportBase<SequenceBase>(serialDraftingSequenceReportBase),
AZStd::move(draftingTestRuns),
DeserializeTestRunReport(serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRunReport]]));
}
rapidjson::Document OpenSequenceReportJson(const AZStd::string& sequenceReportJson)
{
rapidjson::Document doc;
if (doc.Parse<0>(sequenceReportJson.c_str()).HasParseError())
{
throw SequenceReportException("Could not parse sequence report data");
}
return doc;
}
Client::RegularSequenceReport DeserializeRegularSequenceReport(const AZStd::string& sequenceReportJson)
{
const auto doc = OpenSequenceReportJson(sequenceReportJson);
return DeserialiseSequenceReportBase<Client::RegularSequenceReport>(doc);
}
Client::SeedSequenceReport DeserializeSeedSequenceReport(const AZStd::string& sequenceReportJson)
{
const auto doc = OpenSequenceReportJson(sequenceReportJson);
return DeserialiseSequenceReportBase<Client::SeedSequenceReport>(doc);
}
Client::ImpactAnalysisSequenceReport DeserializeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson)
{
const auto doc = OpenSequenceReportJson(sequenceReportJson);
AZStd::vector<AZStd::string> discardedTestRuns;
discardedTestRuns.reserve(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]].GetArray().Size());
for (const auto& testRun : doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]].GetArray())
{
discardedTestRuns.emplace_back(testRun.GetString());
}
return Client::ImpactAnalysisSequenceReport(
DeserializeDraftingSequenceReportBase<Client::ImpactAnalysisSequenceReport>(doc), AZStd::move(discardedTestRuns));
}
Client::SafeImpactAnalysisSequenceReport DeserializeSafeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson)
{
const auto doc = OpenSequenceReportJson(sequenceReportJson);
return Client::SafeImpactAnalysisSequenceReport(
DeserializeDraftingSequenceReportBase<Client::SafeImpactAnalysisSequenceReport>(doc),
DeserializeTestSelection(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]]),
DeserializeTestRunReport(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRunReport]]));
}
} // namespace TestImpact
@@ -243,4 +243,256 @@ namespace TestImpact
throw(Exception(AZStd::string::format("Unexpected client test case result: %u", aznumeric_cast<AZ::u32>(result))));
}
}
SuiteType SuiteTypeFromString(const AZStd::string& suiteType)
{
if (suiteType == SuiteTypeAsString(SuiteType::Main))
{
return SuiteType::Main;
}
else if (suiteType == SuiteTypeAsString(SuiteType::Periodic))
{
return SuiteType::Periodic;
}
else if (suiteType == SuiteTypeAsString(SuiteType::Sandbox))
{
return SuiteType::Sandbox;
}
else
{
throw Exception(AZStd::string::format("Unexpected suite type: '%s'", suiteType.c_str()));
}
}
Client::SequenceReportType SequenceReportTypeFromString(const AZStd::string& type)
{
if (type == SequenceReportTypeAsString(Client::SequenceReportType::ImpactAnalysisSequence))
{
return Client::SequenceReportType::ImpactAnalysisSequence;
}
else if (type == SequenceReportTypeAsString(Client::SequenceReportType::RegularSequence))
{
return Client::SequenceReportType::RegularSequence;
}
else if (type == SequenceReportTypeAsString(Client::SequenceReportType::SafeImpactAnalysisSequence))
{
return Client::SequenceReportType::SafeImpactAnalysisSequence;
}
else if (type == SequenceReportTypeAsString(Client::SequenceReportType::SeedSequence))
{
return Client::SequenceReportType::SeedSequence;
}
else
{
throw Exception(AZStd::string::format("Unexpected sequence report type: '%s'", type.c_str()));
}
}
Client::TestRunResult TestRunResultFromString(const AZStd::string& result)
{
if (result == TestRunResultAsString(Client::TestRunResult::AllTestsPass))
{
return Client::TestRunResult::AllTestsPass;
}
else if (result == TestRunResultAsString(Client::TestRunResult::FailedToExecute))
{
return Client::TestRunResult::FailedToExecute;
}
else if (result == TestRunResultAsString(Client::TestRunResult::NotRun))
{
return Client::TestRunResult::NotRun;
}
else if (result == TestRunResultAsString(Client::TestRunResult::TestFailures))
{
return Client::TestRunResult::TestFailures;
}
else if (result == TestRunResultAsString(Client::TestRunResult::Timeout))
{
return Client::TestRunResult::Timeout;
}
else
{
throw Exception(AZStd::string::format("Unexpected client test run result: '%s'", result.c_str()));
}
}
Client::TestResult TestResultFromString(const AZStd::string& result)
{
if (result == ClientTestResultAsString(Client::TestResult::Failed))
{
return Client::TestResult::Failed;
}
else if (result == ClientTestResultAsString(Client::TestResult::NotRun))
{
return Client::TestResult::NotRun;
}
else if (result == ClientTestResultAsString(Client::TestResult::Passed))
{
return Client::TestResult::Passed;
}
else
{
throw Exception(AZStd::string::format("Unexpected client test result: '%s'", result.c_str()));
}
}
TestSequenceResult TestSequenceResultFromString(const AZStd::string& result)
{
if (result == TestSequenceResultAsString(TestSequenceResult::Failure))
{
return TestSequenceResult::Failure;
}
else if (result == TestSequenceResultAsString(TestSequenceResult::Success))
{
return TestSequenceResult::Success;
}
else if (result == TestSequenceResultAsString(TestSequenceResult::Timeout))
{
return TestSequenceResult::Timeout;
}
else
{
throw Exception(AZStd::string::format("Unexpected test sequence result: '%s'", result.c_str()));
}
}
Policy::ExecutionFailure ExecutionFailurePolicyFromString(const AZStd::string& executionFailurePolicy)
{
if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Abort))
{
return Policy::ExecutionFailure::Abort;
}
else if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Continue))
{
return Policy::ExecutionFailure::Continue;
}
else if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Ignore))
{
return Policy::ExecutionFailure::Ignore;
}
else
{
throw Exception(AZStd::string::format("Unexpected execution failure policy: '%s'", executionFailurePolicy.c_str()));
}
}
Policy::FailedTestCoverage FailedTestCoveragePolicyFromString(const AZStd::string& failedTestCoveragePolicy)
{
if (failedTestCoveragePolicy == FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage::Discard))
{
return Policy::FailedTestCoverage::Discard;
}
else if (failedTestCoveragePolicy == FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage::Keep))
{
return Policy::FailedTestCoverage::Keep;
}
else
{
throw Exception(AZStd::string::format("Unexpected failed test coverage policy: '%s'", failedTestCoveragePolicy.c_str()));
}
}
Policy::TestPrioritization TestPrioritizationPolicyFromString(const AZStd::string& testPrioritizationPolicy)
{
if (testPrioritizationPolicy == TestPrioritizationPolicyAsString(Policy::TestPrioritization::DependencyLocality))
{
return Policy::TestPrioritization::DependencyLocality;
}
else if (testPrioritizationPolicy == TestPrioritizationPolicyAsString(Policy::TestPrioritization::None))
{
return Policy::TestPrioritization::None;
}
else
{
throw Exception(AZStd::string::format("Unexpected test prioritization policy: '%s'", testPrioritizationPolicy.c_str()));
}
}
Policy::TestFailure TestFailurePolicyFromString(const AZStd::string& testFailurePolicy)
{
if (testFailurePolicy == TestFailurePolicyAsString(Policy::TestFailure::Abort))
{
return Policy::TestFailure::Abort;
}
else if (testFailurePolicy == TestFailurePolicyAsString(Policy::TestFailure::Continue))
{
return Policy::TestFailure::Continue;
}
else
{
throw Exception(AZStd::string::format("Unexpected test failure policy: '%s'", testFailurePolicy.c_str()));
}
}
Policy::IntegrityFailure IntegrityFailurePolicyFromString(const AZStd::string& integrityFailurePolicy)
{
if (integrityFailurePolicy == IntegrityFailurePolicyAsString(Policy::IntegrityFailure::Abort))
{
return Policy::IntegrityFailure::Abort;
}
else if (integrityFailurePolicy == IntegrityFailurePolicyAsString(Policy::IntegrityFailure::Continue))
{
return Policy::IntegrityFailure::Continue;
}
else
{
throw Exception(AZStd::string::format("Unexpected integration failure policy: '%s'", integrityFailurePolicy.c_str()));
}
}
Policy::DynamicDependencyMap DynamicDependencyMapPolicyFromString(const AZStd::string& dynamicDependencyMapPolicy)
{
if (dynamicDependencyMapPolicy == DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap::Discard))
{
return Policy::DynamicDependencyMap::Discard;
}
else if (dynamicDependencyMapPolicy == DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap::Update))
{
return Policy::DynamicDependencyMap::Update;
}
else
{
throw Exception(AZStd::string::format("Unexpected dynamic dependency map policy: '%s'", dynamicDependencyMapPolicy.c_str()));
}
}
Policy::TestSharding TestShardingPolicyFromString(const AZStd::string& testShardingPolicy)
{
if (testShardingPolicy == TestShardingPolicyAsString(Policy::TestSharding::Always))
{
return Policy::TestSharding::Always;
}
else if (testShardingPolicy == TestShardingPolicyAsString(Policy::TestSharding::Never))
{
return Policy::TestSharding::Never;
}
else
{
throw Exception(AZStd::string::format("Unexpected test sharding policy: '%s'", testShardingPolicy.c_str()));
}
}
Policy::TargetOutputCapture TargetOutputCapturePolicyFromString(const AZStd::string& targetOutputCapturePolicy)
{
if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::File))
{
return Policy::TargetOutputCapture::File;
}
else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::None))
{
return Policy::TargetOutputCapture::None;
}
else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::StdOut))
{
return Policy::TargetOutputCapture::StdOut;
}
else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::StdOutAndFile))
{
return Policy::TargetOutputCapture::StdOutAndFile;
}
else
{
throw Exception(AZStd::string::format("Unexpected target output capture policy: '%s'", targetOutputCapturePolicy.c_str()));
}
}
} // namespace TestImpact