Merge pull request #35 from aws-lumberyard-dev/TIF/Jenkins_Refactor

Tif/jenkins refactor
This commit is contained in:
jonawals
2021-05-21 20:08:05 +01:00
committed by GitHub
25 changed files with 384 additions and 214 deletions
@@ -12,6 +12,8 @@
#pragma once
#include <TestImpactFramework/TestImpactRepoPath.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
@@ -27,14 +29,14 @@ namespace TestImpact
//! Coverage information about a particular source file.
struct SourceCoverage
{
AZStd::string m_path; //!< Source file path.
RepoPath m_path; //!< Source file path.
AZStd::vector<LineCoverage> m_coverage; //!< Source file line coverage (empty if source level coverage only).
};
//! Coverage information about a particular module (executable, shared library).
struct ModuleCoverage
{
AZStd::string m_path; //!< Module path.
RepoPath m_path; //!< Module path.
AZStd::vector<SourceCoverage> m_sources; //!< Sources of this module that are covered.
};
} // namespace TestImpact
@@ -1,38 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <TestImpactFramework/TestImpactException.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#pragma once
namespace TestImpact
{
template<typename ExceptionType>
AZStd::string ReadFileContents(const AZ::IO::Path& file)
{
static_assert(AZStd::is_base_of<Exception, ExceptionType>::value, "Exception must be a TestImpact exception or derived type");
const auto fileSize = AZ::IO::SystemFile::Length(file.c_str());
AZ_TestImpact_Eval(fileSize > 0, ExceptionType, AZStd::string::format("File %s does not exist", file.c_str()));
AZStd::vector<char> buffer(fileSize + 1);
buffer[fileSize] = '\0';
AZ_TestImpact_Eval(AZ::IO::SystemFile::Read(file.c_str(), buffer.data()), ExceptionType, "Could not read file contents");
return AZStd::string(buffer.begin(), buffer.end());
}
} // namespace TestImpact
@@ -1,26 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <TestImpactFramework/TestImpactException.h>
namespace TestImpact
{
//! Exception for test job related operations.
class TestJobException
: public Exception
{
public:
using Exception::Exception;
};
} // namespace TestImpact
@@ -1,70 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "TestImpactTestRun.h"
namespace TestImpact
{
TestRun::TestRun(AZStd::vector<TestRunSuite>&& testSuites, AZStd::chrono::milliseconds duration)
: TestSuiteContainer(AZStd::move(testSuites))
, m_duration(duration)
{
for (const auto& suite : m_testSuites)
{
for (const auto& test : suite.m_tests)
{
if (test.m_status == TestRunStatus::Run)
{
m_numRuns++;
if (test.m_result.value() == TestRunResult::Passed)
{
m_numPasses++;
}
else
{
m_numFailures++;
}
}
else
{
m_numNotRuns++;
}
}
}
}
size_t TestRun::GetNumRuns() const
{
return m_numRuns;
}
size_t TestRun::GetNumNotRuns() const
{
return m_numNotRuns;
}
size_t TestRun::GetNumPasses() const
{
return m_numPasses;
}
size_t TestRun::GetNumFailures() const
{
return m_numFailures;
}
AZStd::chrono::milliseconds TestRun::GetDuration() const
{
return m_duration;
}
} // namespace TestImpact
@@ -13,7 +13,7 @@
#pragma once
#include <Artifact/Dynamic/TestImpactTestEnumerationSuite.h>
#include <Test/TestImpactTestSuiteContainer.h>
#include <TestEngine/TestImpactTestSuiteContainer.h>
namespace TestImpact
{
@@ -10,8 +10,8 @@
*
*/
#include <Test/Enumeration/TestImpactTestEnumerationException.h>
#include <Test/Enumeration/TestImpactTestEnumerationSerializer.h>
#include <TestEngine/Enumeration/TestImpactTestEnumerationException.h>
#include <TestEngine/Enumeration/TestImpactTestEnumerationSerializer.h>
#include <AzCore/JSON/document.h>
#include <AzCore/JSON/prettywriter.h>
@@ -12,7 +12,7 @@
#pragma once
#include <Test/Enumeration/TestImpactTestEnumeration.h>
#include <TestEngine/Enumeration/TestImpactTestEnumeration.h>
#include <AzCore/std/string/string.h>
@@ -10,11 +10,13 @@
*
*/
#include <TestImpactFramework/TestImpactUtils.h>
#include <Artifact/Factory/TestImpactTestEnumerationSuiteFactory.h>
#include <Test/Enumeration/TestImpactTestEnumerationException.h>
#include <Test/Enumeration/TestImpactTestEnumerationSerializer.h>
#include <Test/Enumeration/TestImpactTestEnumerator.h>
#include <Test/Job/TestImpactTestJobCommon.h>
#include <TestEngine/Enumeration/TestImpactTestEnumerationException.h>
#include <TestEngine/Enumeration/TestImpactTestEnumerationSerializer.h>
#include <TestEngine/Enumeration/TestImpactTestEnumerator.h>
#include <TestEngine/Enumeration/TestImpactTestEnumeration.h>
#include <AzCore/IO/SystemFile.h>
@@ -23,7 +25,7 @@ namespace TestImpact
namespace
{
void WriteCacheFile(
const TestEnumeration& enumeration, const AZ::IO::Path& path, Bitwise::CacheExceptionPolicy cacheExceptionPolicy)
const TestEnumeration& enumeration, const RepoPath& path, Bitwise::CacheExceptionPolicy cacheExceptionPolicy)
{
const AZStd::string cacheJSON = SerializeTestEnumeration(enumeration);
const AZStd::vector<char> cacheBytes(cacheJSON.begin(), cacheJSON.end());
@@ -48,7 +50,7 @@ namespace TestImpact
}
}
AZStd::optional<TestEnumeration> ReadCacheFile(const AZ::IO::Path& path, Bitwise::CacheExceptionPolicy cacheExceptionPolicy)
AZStd::optional<TestEnumeration> ReadCacheFile(const RepoPath& path, Bitwise::CacheExceptionPolicy cacheExceptionPolicy)
{
AZ::IO::SystemFile cacheFile;
AZStd::string cacheJSON;
@@ -83,18 +85,18 @@ namespace TestImpact
}
} // namespace
TestEnumeration ParseTestEnumerationFile(const AZ::IO::Path& enumerationFile)
TestEnumeration ParseTestEnumerationFile(const RepoPath& enumerationFile)
{
return TestEnumeration(GTest::TestEnumerationSuitesFactory(ReadFileContents<TestEnumerationException>(enumerationFile)));
}
TestEnumerationJobData::TestEnumerationJobData(const AZ::IO::Path& enumerationArtifact, AZStd::optional<Cache>&& cache)
TestEnumerationJobData::TestEnumerationJobData(const RepoPath& enumerationArtifact, AZStd::optional<Cache>&& cache)
: m_enumerationArtifact(enumerationArtifact)
, m_cache(AZStd::move(cache))
{
}
const AZ::IO::Path& TestEnumerationJobData::GetEnumerationArtifactPath() const
const RepoPath& TestEnumerationJobData::GetEnumerationArtifactPath() const
{
return m_enumerationArtifact;
}
@@ -163,7 +165,7 @@ namespace TestImpact
const auto& [meta, jobInfo] = jobData;
if (meta.m_result == JobResult::ExecutedWithSuccess)
{
const auto& enumeration = enumerations[jobId] = ParseTestEnumerationFile(jobInfo->GetEnumerationArtifactPath());
const auto& enumeration = (enumerations[jobId] = ParseTestEnumerationFile(jobInfo->GetEnumerationArtifactPath()));
// Write out the enumeration to a cache file if we have a cache write policy for this job
if (jobInfo->GetCache().has_value() && jobInfo->GetCache()->m_policy == JobData::CachePolicy::Write)
@@ -12,11 +12,11 @@
#pragma once
#include <Artifact/TestImpactArtifactException.h>
#include <Test/Enumeration/TestImpactTestEnumeration.h>
#include <Test/Job/TestImpactTestJobRunner.h>
#include <TestImpactFramework/TestImpactRuntime.h>
#include <AzCore/IO/Path/Path.h>
#include <Artifact/TestImpactArtifactException.h>
#include <TestEngine/Enumeration/TestImpactTestEnumeration.h>
#include <TestEngine/JobRunner/TestImpactTestJobRunner.h>
namespace TestImpact
{
@@ -35,19 +35,19 @@ namespace TestImpact
struct Cache
{
CachePolicy m_policy;
AZ::IO::Path m_file;
RepoPath m_file;
};
TestEnumerationJobData(const AZ::IO::Path& enumerationArtifact, AZStd::optional<Cache>&& cache);
TestEnumerationJobData(const RepoPath& enumerationArtifact, AZStd::optional<Cache>&& cache);
//! Returns the path to the enumeration artifact produced by the test target.
const AZ::IO::Path& GetEnumerationArtifactPath() const;
const RepoPath& GetEnumerationArtifactPath() const;
//! Returns the cache details for this job.
const AZStd::optional<Cache>& GetCache() const;
private:
AZ::IO::Path m_enumerationArtifact; //!< Path to enumeration artifact to be processed.
RepoPath m_enumerationArtifact; //!< Path to enumeration artifact to be processed.
AZStd::optional<Cache> m_cache = AZStd::nullopt; //!< No caching takes place if cache is empty.
};
@@ -12,11 +12,10 @@
#pragma once
#include <TestImpactFramework/TestImpactBitwise.h>
#include <TestImpactBitwise.h>
#include <Process/JobRunner/TestImpactProcessJob.h>
#include <Process/JobRunner/TestImpactProcessJobRunner.h>
#include <Test/Job/TestImpactTestJobException.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/optional.h>
@@ -45,6 +44,7 @@ namespace TestImpact
public:
using JobData = AdditionalInfo;
using JobInfo = JobInfo<AdditionalInfo>;
using Command = typename JobInfo::Command;
using JobPayload = Payload;
using Job = Job<JobInfo, Payload>;
using ClientJobCallback = AZStd::function<void(const JobInfo& jobInfo, const JobMeta& meta)>;
@@ -111,20 +111,22 @@ namespace TestImpact
// Callback to handle job exception policies and client/derived callbacks
const auto jobCallback = [this, &jobExceptionPolicy](const JobInfo& jobInfo, const JobMeta& meta, StdContent&& std)
{
auto callbackResult = ProcessCallbackResult::Continue;
if (meta.m_result == JobResult::FailedToExecute && IsFlagSet(jobExceptionPolicy, JobExceptionPolicy::OnFailedToExecute))
{
throw TestJobException("Job failed to execute");
callbackResult = ProcessCallbackResult::Abort;
}
else if (meta.m_result == JobResult::ExecutedWithFailure && IsFlagSet(jobExceptionPolicy, JobExceptionPolicy::OnExecutedWithFailure))
{
throw TestJobException("Job executed with failure");
callbackResult = ProcessCallbackResult::Abort;
}
if (m_derivedJobCallback.has_value())
{
if (const auto result = (*m_derivedJobCallback)(jobInfo, meta, AZStd::move(std)); result != CallbackResult::Continue)
if (const auto result = (*m_derivedJobCallback)(jobInfo, meta, AZStd::move(std));
result == ProcessCallbackResult::Abort)
{
return result;
callbackResult = ProcessCallbackResult::Abort;
}
}
@@ -133,7 +135,7 @@ namespace TestImpact
(*m_clientJobCallback)(jobInfo, meta);
}
return CallbackResult::Continue;
return callbackResult;
};
return m_jobRunner.Execute(jobInfos, jobCallback, payloadMapProducer);
@@ -10,31 +10,32 @@
*
*/
#include <TestImpactFramework/TestImpactUtils.h>
#include <Artifact/Factory/TestImpactModuleCoverageFactory.h>
#include <Artifact/Factory/TestImpactTestRunSuiteFactory.h>
#include <Test/Job/TestImpactTestJobCommon.h>
#include <Test/Run/TestImpactInstrumentedTestRunner.h>
#include <Test/Run/TestImpactTestRunException.h>
#include <Test/Run/TestImpactTestRunSerializer.h>
#include <TestEngine/Run/TestImpactInstrumentedTestRunner.h>
#include <TestEngine/Run/TestImpactTestRunException.h>
#include <TestEngine/Run/TestImpactTestRunSerializer.h>
#include <AzCore/IO/SystemFile.h>
namespace TestImpact
{
InstrumentedTestRunJobData::InstrumentedTestRunJobData(const AZ::IO::Path& resultsArtifact, const AZ::IO::Path& coverageArtifact)
InstrumentedTestRunJobData::InstrumentedTestRunJobData(const RepoPath& resultsArtifact, const RepoPath& coverageArtifact)
: TestRunJobData(resultsArtifact)
, m_coverageArtifact(coverageArtifact)
{
}
const AZ::IO::Path& InstrumentedTestRunJobData::GetCoverageArtifactPath() const
const RepoPath& InstrumentedTestRunJobData::GetCoverageArtifactPath() const
{
return m_coverageArtifact;
}
InstrumentedTestRunner::JobPayload ParseTestRunAndCoverageFiles(
const AZ::IO::Path& runFile,
const AZ::IO::Path& coverageFile,
const RepoPath& runFile,
const RepoPath& coverageFile,
AZStd::chrono::milliseconds duration,
InstrumentedTestRunner::CoverageExceptionPolicy coverageExceptionPolicy)
{
@@ -44,7 +45,7 @@ namespace TestImpact
{
AZ_TestImpact_Eval(
!IsFlagSet(coverageExceptionPolicy, Bitwise::CoverageExceptionPolicy::OnEmptyCoverage), TestRunException,
"No coverage data generated");
AZStd::string::format("No coverage data generated for '%s'", coverageFile.c_str()));
}
TestCoverage coverage(AZStd::move(moduleCoverages));
@@ -73,11 +74,24 @@ namespace TestImpact
const auto& [meta, jobInfo] = jobData;
if (meta.m_result == JobResult::ExecutedWithSuccess || meta.m_result == JobResult::ExecutedWithFailure)
{
runs[jobId] = ParseTestRunAndCoverageFiles(
jobInfo->GetRunArtifactPath(),
jobInfo->GetCoverageArtifactPath(),
meta.m_duration.value(),
coverageExceptionPolicy);
try
{
runs[jobId] = ParseTestRunAndCoverageFiles(
jobInfo->GetRunArtifactPath(),
jobInfo->GetCoverageArtifactPath(),
meta.m_duration.value(),
coverageExceptionPolicy);
}
catch (const Exception& e)
{
AZ_Warning("RunInstrumentedTests", false, e.what());
runs[jobId] = AZStd::nullopt;
if (coverageExceptionPolicy == CoverageExceptionPolicy::OnEmptyCoverage)
{
break;
}
}
}
}
@@ -12,24 +12,25 @@
#pragma once
#include <Test/Job/TestImpactTestJobRunner.h>
#include <Test/Run/TestImpactTestCoverage.h>
#include <Test/Run/TestImpactTestRun.h>
#include <Test/Run/TestImpactTestRunJobData.h>
#include <TestEngine/JobRunner/TestImpactTestJobRunner.h>
#include <TestEngine/Run/TestImpactTestCoverage.h>
#include <TestEngine/Run/TestImpactTestRun.h>
#include <TestEngine/Run/TestImpactTestRunJobData.h>
namespace TestImpact
{
//! Per-job data for instrumented test runs.
class InstrumentedTestRunJobData : public TestRunJobData
class InstrumentedTestRunJobData
: public TestRunJobData
{
public:
InstrumentedTestRunJobData(const AZ::IO::Path& resultsArtifact, const AZ::IO::Path& coverageArtifact);
InstrumentedTestRunJobData(const RepoPath& resultsArtifact, const RepoPath& coverageArtifact);
//! Returns the path to the coverage artifact produced by the test target.
const AZ::IO::Path& GetCoverageArtifactPath() const;
const RepoPath& GetCoverageArtifactPath() const;
private:
AZ::IO::Path m_coverageArtifact; //!< Path to coverage data.
RepoPath m_coverageArtifact; //!< Path to coverage data.
};
namespace Bitwise
@@ -43,7 +44,8 @@ namespace TestImpact
} // namespace Bitwise
//! Runs a batch of test targets to determine the test coverage and passes/failures.
class InstrumentedTestRunner : public TestJobRunner<InstrumentedTestRunJobData, AZStd::pair<TestRun, TestCoverage>>
class InstrumentedTestRunner
: public TestJobRunner<InstrumentedTestRunJobData, AZStd::pair<TestRun, TestCoverage>>
{
using JobRunner = TestJobRunner<InstrumentedTestRunJobData, AZStd::pair<TestRun, TestCoverage>>;
@@ -10,16 +10,68 @@
*
*/
#include <Test/Run/TestImpactTestCoverage.h>
#include <TestEngine/Run/TestImpactTestCoverage.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/sort.h>
namespace TestImpact
{
TestCoverage::TestCoverage(AZStd::vector<ModuleCoverage>&& moduleCoverages)
TestCoverage::TestCoverage(const TestCoverage& other)
: m_modules(other.m_modules)
, m_sourcesCovered(other.m_sourcesCovered)
, m_coverageLevel(other.m_coverageLevel)
{
}
TestCoverage::TestCoverage(TestCoverage&& other) noexcept
: m_modules(AZStd::move(other.m_modules))
, m_sourcesCovered(AZStd::move(other.m_sourcesCovered))
{
AZStd::swap(m_coverageLevel, other.m_coverageLevel);
}
TestCoverage::TestCoverage(const AZStd::vector<ModuleCoverage>& moduleCoverages)
: m_modules(moduleCoverages)
{
CalculateTestMetrics();
}
TestCoverage::TestCoverage(AZStd::vector<ModuleCoverage>&& moduleCoverages) noexcept
: m_modules(AZStd::move(moduleCoverages))
{
CalculateTestMetrics();
}
TestCoverage& TestCoverage::operator=(const TestCoverage& other)
{
if (this != &other)
{
m_modules = other.m_modules;
m_sourcesCovered = other.m_sourcesCovered;
m_coverageLevel = other.m_coverageLevel;
}
return *this;
}
TestCoverage& TestCoverage::operator=(TestCoverage&& other) noexcept
{
if (this != &other)
{
m_modules = AZStd::move(other.m_modules);
m_sourcesCovered = other.m_sourcesCovered;
m_coverageLevel = other.m_coverageLevel;
}
return *this;
}
void TestCoverage::CalculateTestMetrics()
{
m_coverageLevel.reset();
m_sourcesCovered.clear();
for (const auto& moduleCovered : m_modules)
{
for (const auto& sourceCovered : moduleCovered.m_sources)
@@ -29,7 +29,13 @@ namespace TestImpact
class TestCoverage
{
public:
TestCoverage(AZStd::vector<ModuleCoverage>&& moduleCoverages);
TestCoverage(const TestCoverage&);
TestCoverage(TestCoverage&&) noexcept;
TestCoverage(AZStd::vector<ModuleCoverage>&& moduleCoverages) noexcept;
TestCoverage(const AZStd::vector<ModuleCoverage>& moduleCoverages);
TestCoverage& operator=(const TestCoverage&);
TestCoverage& operator=(TestCoverage&&) noexcept;
//! Returns the number of unique sources covered.
size_t GetNumSourcesCovered() const;
@@ -47,6 +53,8 @@ namespace TestImpact
AZStd::optional<CoverageLevel> GetCoverageLevel() const;
private:
void CalculateTestMetrics();
AZStd::vector<ModuleCoverage> m_modules;
AZStd::vector<AZStd::string> m_sourcesCovered;
AZStd::optional<CoverageLevel> m_coverageLevel;
@@ -0,0 +1,138 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "TestImpactTestRun.h"
namespace TestImpact
{
TestRun::TestRun(const TestRun& other)
: TestSuiteContainer(other)
, m_numRuns(other.m_numRuns)
, m_numNotRuns(other.m_numNotRuns)
, m_numPasses(other.m_numPasses)
, m_numFailures(other.m_numFailures)
, m_duration(other.m_duration)
{
CalculateTestMetrics();
}
TestRun::TestRun(TestRun&& other) noexcept
: TestSuiteContainer(AZStd::move(other))
, m_numRuns(other.m_numRuns)
, m_numNotRuns(other.m_numNotRuns)
, m_numPasses(other.m_numPasses)
, m_numFailures(other.m_numFailures)
, m_duration(other.m_duration)
{
}
TestRun::TestRun(AZStd::vector<TestRunSuite>&& testSuites, AZStd::chrono::milliseconds duration) noexcept
: TestSuiteContainer(AZStd::move(testSuites))
, m_duration(duration)
{
CalculateTestMetrics();
}
TestRun::TestRun(const AZStd::vector<TestRunSuite>& testSuites, AZStd::chrono::milliseconds duration)
: TestSuiteContainer(testSuites)
, m_duration(duration)
{
CalculateTestMetrics();
}
TestRun& TestRun::operator=(TestRun&& other) noexcept
{
if (this != &other)
{
TestSuiteContainer::operator=(AZStd::move(other));
m_numRuns = other.m_numRuns;
m_numNotRuns = other.m_numNotRuns;
m_numPasses = other.m_numPasses;
m_numFailures = other.m_numFailures;
m_duration = other.m_duration;
}
return *this;
}
TestRun& TestRun::operator=(const TestRun& other)
{
if (this != &other)
{
TestSuiteContainer::operator=(other);
m_numRuns = other.m_numRuns;
m_numNotRuns = other.m_numNotRuns;
m_numPasses = other.m_numPasses;
m_numFailures = other.m_numFailures;
m_duration = other.m_duration;
}
return *this;
}
void TestRun::CalculateTestMetrics()
{
m_numRuns = 0;
m_numNotRuns = 0;
m_numPasses = 0;
m_numFailures = 0;
for (const auto& suite : m_testSuites)
{
for (const auto& test : suite.m_tests)
{
if (test.m_status == TestRunStatus::Run)
{
m_numRuns++;
if (test.m_result.value() == TestRunResult::Passed)
{
m_numPasses++;
}
else
{
m_numFailures++;
}
}
else
{
m_numNotRuns++;
}
}
}
}
size_t TestRun::GetNumRuns() const
{
return m_numRuns;
}
size_t TestRun::GetNumNotRuns() const
{
return m_numNotRuns;
}
size_t TestRun::GetNumPasses() const
{
return m_numPasses;
}
size_t TestRun::GetNumFailures() const
{
return m_numFailures;
}
AZStd::chrono::milliseconds TestRun::GetDuration() const
{
return m_duration;
}
} // namespace TestImpact
@@ -13,7 +13,7 @@
#pragma once
#include <Artifact/Dynamic/TestImpactTestRunSuite.h>
#include <Test/TestImpactTestSuiteContainer.h>
#include <TestEngine/TestImpactTestSuiteContainer.h>
namespace TestImpact
{
@@ -24,7 +24,13 @@ namespace TestImpact
using TestSuiteContainer = TestSuiteContainer<TestRunSuite>;
public:
TestRun(AZStd::vector<TestRunSuite>&& testSuites, AZStd::chrono::milliseconds duration);
TestRun(const TestRun&);
TestRun(TestRun&&) noexcept;
TestRun(const AZStd::vector<TestRunSuite>& testSuites, AZStd::chrono::milliseconds duration);
TestRun(AZStd::vector<TestRunSuite>&& testSuites, AZStd::chrono::milliseconds duration) noexcept;
TestRun& operator=(const TestRun&);
TestRun& operator=(TestRun&&) noexcept;
//! Returns the total number of tests that were run.
size_t GetNumRuns() const;
@@ -42,6 +48,8 @@ namespace TestImpact
AZStd::chrono::milliseconds GetDuration() const;
private:
void CalculateTestMetrics();
size_t m_numRuns = 0;
size_t m_numNotRuns = 0;
size_t m_numPasses = 0;
@@ -10,16 +10,16 @@
*
*/
#include <Test/Run/TestImpactTestRunJobData.h>
#include <TestEngine/Run/TestImpactTestRunJobData.h>
namespace TestImpact
{
TestRunJobData::TestRunJobData(const AZ::IO::Path& resultsArtifact)
TestRunJobData::TestRunJobData(const RepoPath& resultsArtifact)
: m_runArtifact(resultsArtifact)
{
}
const AZ::IO::Path& TestRunJobData::GetRunArtifactPath() const
const RepoPath& TestRunJobData::GetRunArtifactPath() const
{
return m_runArtifact;
}
@@ -12,7 +12,7 @@
#pragma once
#include <Test/Job/TestImpactTestJobRunner.h>
#include <TestEngine/JobRunner/TestImpactTestJobRunner.h>
namespace TestImpact
{
@@ -20,12 +20,12 @@ namespace TestImpact
class TestRunJobData
{
public:
TestRunJobData(const AZ::IO::Path& resultsArtifact);
TestRunJobData(const RepoPath& resultsArtifact);
//! Returns the path to the test run artifact produced by the test target.
const AZ::IO::Path& GetRunArtifactPath() const;
const RepoPath& GetRunArtifactPath() const;
private:
AZ::IO::Path m_runArtifact; //!< Path to results data.
RepoPath m_runArtifact; //!< Path to results data.
};
} // namespace TestImpact
@@ -10,8 +10,8 @@
*
*/
#include <Test/Run/TestImpactTestRunException.h>
#include <Test/Run/TestImpactTestRunSerializer.h>
#include <TestEngine/Run/TestImpactTestRunException.h>
#include <TestEngine/Run/TestImpactTestRunSerializer.h>
#include <AzCore/JSON/document.h>
#include <AzCore/JSON/prettywriter.h>
@@ -12,7 +12,7 @@
#pragma once
#include <Test/Run/TestImpactTestRun.h>
#include <TestEngine/Run/TestImpactTestRun.h>
#include <AzCore/std/string/string.h>
@@ -10,17 +10,18 @@
*
*/
#include <TestImpactFramework/TestImpactUtils.h>
#include <Artifact/Factory/TestImpactTestRunSuiteFactory.h>
#include <Test/Job/TestImpactTestJobCommon.h>
#include <Test/Run/TestImpactTestRunException.h>
#include <Test/Run/TestImpactTestRunSerializer.h>
#include <Test/Run/TestImpactTestRunner.h>
#include <TestEngine/Run/TestImpactTestRunException.h>
#include <TestEngine/Run/TestImpactTestRunSerializer.h>
#include <TestEngine/Run/TestImpactTestRunner.h>
#include <AzCore/IO/SystemFile.h>
namespace TestImpact
{
TestRun ParseTestRunFile(const AZ::IO::Path& runFile, AZStd::chrono::milliseconds duration)
TestRun ParseTestRunFile(const RepoPath& runFile, AZStd::chrono::milliseconds duration)
{
return TestRun(GTest::TestRunSuitesFactory(ReadFileContents<TestRunException>(runFile)), duration);
}
@@ -46,7 +47,15 @@ namespace TestImpact
const auto& [meta, jobInfo] = jobData;
if (meta.m_result == JobResult::ExecutedWithSuccess || meta.m_result == JobResult::ExecutedWithFailure)
{
runs[jobId] = ParseTestRunFile(jobInfo->GetRunArtifactPath(), meta.m_duration.value());
try
{
runs[jobId] = ParseTestRunFile(jobInfo->GetRunArtifactPath(), meta.m_duration.value());
}
catch (const Exception& e)
{
AZ_Warning("RunTests", false, e.what());
runs[jobId] = AZStd::nullopt;
}
}
}
@@ -12,9 +12,9 @@
#pragma once
#include <Test/Job/TestImpactTestJobRunner.h>
#include <Test/Run/TestImpactTestRun.h>
#include <Test/Run/TestImpactTestRunJobData.h>
#include <TestEngine/JobRunner/TestImpactTestJobRunner.h>
#include <TestEngine/Run/TestImpactTestRun.h>
#include <TestEngine/Run/TestImpactTestRunJobData.h>
namespace TestImpact
{
@@ -22,7 +22,13 @@ namespace TestImpact
class TestSuiteContainer
{
public:
TestSuiteContainer(AZStd::vector<TestSuite>&& testSuites);
TestSuiteContainer(const TestSuiteContainer&);
TestSuiteContainer(TestSuiteContainer&&) noexcept;
TestSuiteContainer(const AZStd::vector<TestSuite>& testSuites);
TestSuiteContainer(AZStd::vector<TestSuite>&& testSuites) noexcept;
TestSuiteContainer& operator=(const TestSuiteContainer&);
TestSuiteContainer& operator=(TestSuiteContainer&&) noexcept;
//! Returns the test suites in this container.
const AZStd::vector<TestSuite>& GetTestSuites() const;
@@ -39,6 +45,9 @@ namespace TestImpact
//! Returns the total number of disabled tests across all test suites.
size_t GetNumDisabledTests() const;
private:
void CalculateTestMetrics();
protected:
AZStd::vector<TestSuite> m_testSuites;
size_t m_numDisabledTests = 0;
@@ -46,9 +55,67 @@ namespace TestImpact
};
template<typename TestSuite>
TestSuiteContainer<TestSuite>::TestSuiteContainer(AZStd::vector<TestSuite>&& testSuites)
TestSuiteContainer<TestSuite>::TestSuiteContainer(TestSuiteContainer&& other) noexcept
: m_testSuites(AZStd::move(other.m_testSuites))
, m_numDisabledTests(other.m_numDisabledTests)
, m_numEnabledTests(other.m_numEnabledTests)
{
}
template<typename TestSuite>
TestSuiteContainer<TestSuite>::TestSuiteContainer(const TestSuiteContainer& other)
: m_testSuites(other.m_testSuites.begin(), other.m_testSuites.end())
, m_numDisabledTests(other.m_numDisabledTests)
, m_numEnabledTests(other.m_numEnabledTests)
{
}
template<typename TestSuite>
TestSuiteContainer<TestSuite>::TestSuiteContainer(AZStd::vector<TestSuite>&& testSuites) noexcept
: m_testSuites(std::move(testSuites))
{
CalculateTestMetrics();
}
template<typename TestSuite>
TestSuiteContainer<TestSuite>::TestSuiteContainer(const AZStd::vector<TestSuite>& testSuites)
: m_testSuites(testSuites)
{
CalculateTestMetrics();
}
template<typename TestSuite>
TestSuiteContainer<TestSuite>& TestSuiteContainer<TestSuite>::operator=(TestSuiteContainer&& other) noexcept
{
if (this != &other)
{
m_testSuites = AZStd::move(other.m_testSuites);
m_numDisabledTests = other.m_numDisabledTests;
m_numEnabledTests = other.m_numEnabledTests;
}
return *this;
}
template<typename TestSuite>
TestSuiteContainer<TestSuite>& TestSuiteContainer<TestSuite>::operator=(const TestSuiteContainer& other)
{
if (this != &other)
{
m_testSuites = other.m_testSuites;
m_numDisabledTests = other.m_numDisabledTests;
m_numEnabledTests = other.m_numEnabledTests;
}
return *this;
}
template<typename TestSuite>
void TestSuiteContainer<TestSuite>::CalculateTestMetrics()
{
m_numDisabledTests = 0;
m_numEnabledTests = 0;
for (const auto& suite : m_testSuites)
{
if (suite.m_enabled)