You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceRep...

857 lines
39 KiB
C++

/*
* 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 SequenceReportBaseType>
void SerializeSequenceReportBaseMembers(
const SequenceReportBaseType& sequenceReport, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
// Type
writer.Key(SequenceReportFields::Keys[SequenceReportFields::Type]);
writer.String(SequenceReportTypeAsString(sequenceReport.ReportType).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 DraftingSequenceReportBaseType>
void SerializeDraftingSequenceReportMembers(
const DraftingSequenceReportBaseType& 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();
}
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