Address PR comments

This commit is contained in:
John
2021-06-10 14:54:46 +01:00
parent fdbc15b195
commit 169d4da288
32 changed files with 1631 additions and 164 deletions
@@ -0,0 +1,65 @@
#
# 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.
#
ly_add_target(
NAME TestImpact.Frontend.Console.Static STATIC
NAMESPACE AZ
FILES_CMAKE
testimpactframework_frontend_console_static_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
Include
PRIVATE
Source
BUILD_DEPENDENCIES
PUBLIC
AZ::TestImpact.Runtime.Static
)
ly_add_target(
NAME TestImpact.Frontend.Console EXECUTABLE
OUTPUT_NAME tiaf
NAMESPACE AZ
FILES_CMAKE
testimpactframework_frontend_console_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
BUILD_DEPENDENCIES
PRIVATE
AZ::TestImpact.Frontend.Console.Static
)
################################################################################
# Tests
################################################################################
# Disbled:SPEC-7246
#ly_add_target(
# NAME TestImpact.Frontend.Console.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
# NAMESPACE AZ
# FILES_CMAKE
# testimpactframework_frontend_console_static_tests_files.cmake
# INCLUDE_DIRECTORIES
# PRIVATE
# Include
# Source
# Tests
# BUILD_DEPENDENCIES
# PRIVATE
# AZ::AzTestShared
# AZ::AzTest
# AZ::TestImpact.Frontend.Console.Static
#)
#
#ly_add_googletest(
# NAME AZ::TestImpact.Frontend.Console.Static.Tests
#)
@@ -0,0 +1,35 @@
/*
* 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
namespace TestImpact
{
namespace Console
{
enum class ReturnCode : int
{
Success = 0, //!< The instigation operation(s) returned without error.
InvalidArgs, //!< The specified command line arguments were incorrect.
InvalidUnifiedDiff, //!< The specified unified diff could not be transformed into a valid change list.
InvalidConfiguration, //!< The runtime configuration is malformed.
RuntimeError, //!< The runtime encountered an error that it could not recover from.
UnhandledError, //!< The framework encountered an error that it anticipated but did not handle and could not recover from.
UnknownError, //!< An error of unknown origin was encountered that the console or runtime could not recover from.
TestFailure, //!< The test sequence had one or more test failures.
Timeout //!< The test sequence runtime exceeded the global timeout value.
};
//! Entry point for the console front end application.
[[nodiscard]] ReturnCode Main(int argc, char** argv);
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,455 @@
/*
* 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 <TestImpactCommandLineOptions.h>
#include <TestImpactCommandLineOptionsUtils.h>
#include <AzCore/Settings/CommandLine.h>
namespace TestImpact
{
namespace
{
enum
{
// Options
ConfigKey,
ChangeListKey,
OutputChangeListKey,
SequenceKey,
TestPrioritizationPolicyKey,
ExecutionFailurePolicyKey,
FailedTestCoveragePolicyKey,
TestFailurePolicyKey,
IntegrityFailurePolicyKey,
TestShardingPolicyKey,
TargetOutputCaptureKey,
MaxConcurrencyKey,
TestTargetTimeoutKey,
GlobalTimeoutKey,
SuiteFilterKey,
SafeModeKey,
// Values
None,
Seed,
Regular,
ImpactAnalysis,
ImpactAnalysisNoWrite,
ImpactAnalysisOrSeed,
Locality,
Abort,
Continue,
Ignore,
StdOut,
File,
Discard,
Keep
};
constexpr const char* OptionKeys[] =
{
// Options
"config",
"changelist",
"ochangelist",
"sequence",
"ppolicy",
"epolicy",
"cpolicy",
"fpolicy",
"ipolicy",
"shard",
"targetout",
"maxconcurrency",
"ttimeout",
"gtimeout",
"suite",
"safemode",
// Values
"none",
"seed",
"regular",
"tia",
"tianowrite",
"tiaorseed",
"locality",
"abort",
"continue",
"ignore",
"stdout",
"file",
"discard",
"keep"
};
RepoPath ParseConfigurationFile(const AZ::CommandLine& cmd)
{
return ParsePathOption(OptionKeys[ConfigKey], cmd).value_or(LY_TEST_IMPACT_DEFAULT_CONFIG_FILE);
}
AZStd::optional<RepoPath> ParseChangeListFile(const AZ::CommandLine& cmd)
{
return ParsePathOption(OptionKeys[ChangeListKey], cmd);
}
bool ParseOutputChangeList(const AZ::CommandLine& cmd)
{
return ParseOnOffOption(OptionKeys[OutputChangeListKey], BinaryStateValue<bool>{ false, true }, cmd).value_or(false);
}
TestSequenceType ParseTestSequenceType(const AZ::CommandLine& cmd)
{
const AZStd::vector<AZStd::pair<AZStd::string, TestSequenceType>> states =
{
{OptionKeys[None], TestSequenceType::None},
{OptionKeys[Seed], TestSequenceType::Seed},
{OptionKeys[Regular], TestSequenceType::Regular},
{OptionKeys[ImpactAnalysis], TestSequenceType::ImpactAnalysis},
{OptionKeys[ImpactAnalysisNoWrite], TestSequenceType::ImpactAnalysisNoWrite},
{OptionKeys[ImpactAnalysisOrSeed], TestSequenceType::ImpactAnalysisOrSeed}
};
return ParseMultiStateOption(OptionKeys[SequenceKey], states, cmd).value_or(TestSequenceType::None);
}
Policy::TestPrioritization ParseTestPrioritizationPolicy(const AZ::CommandLine& cmd)
{
const BinaryStateOption<Policy::TestPrioritization> states =
{
{OptionKeys[None], Policy::TestPrioritization::None},
{OptionKeys[Locality], Policy::TestPrioritization::DependencyLocality}
};
return ParseBinaryStateOption(OptionKeys[TestPrioritizationPolicyKey], states, cmd).value_or(Policy::TestPrioritization::None);
}
Policy::ExecutionFailure ParseExecutionFailurePolicy(const AZ::CommandLine& cmd)
{
const AZStd::vector<AZStd::pair<AZStd::string, Policy::ExecutionFailure>> states =
{
{OptionKeys[Abort], Policy::ExecutionFailure::Abort},
{OptionKeys[Continue], Policy::ExecutionFailure::Continue},
{OptionKeys[Ignore], Policy::ExecutionFailure::Ignore}
};
return ParseMultiStateOption(OptionKeys[ExecutionFailurePolicyKey], states, cmd).value_or(Policy::ExecutionFailure::Continue);
}
Policy::FailedTestCoverage ParseFailedTestCoveragePolicy(const AZ::CommandLine& cmd)
{
const AZStd::vector<AZStd::pair<AZStd::string, Policy::FailedTestCoverage>> states =
{
{OptionKeys[Discard], Policy::FailedTestCoverage::Discard},
{OptionKeys[Keep], Policy::FailedTestCoverage::Keep}
};
return ParseMultiStateOption(OptionKeys[FailedTestCoveragePolicyKey], states, cmd).value_or(Policy::FailedTestCoverage::Keep);
}
Policy::TestFailure ParseTestFailurePolicy(const AZ::CommandLine& cmd)
{
const BinaryStateValue<Policy::TestFailure> states =
{
Policy::TestFailure::Abort,
Policy::TestFailure::Continue
};
return ParseAbortContinueOption(OptionKeys[TestFailurePolicyKey], states, cmd).value_or(Policy::TestFailure::Abort);
}
Policy::IntegrityFailure ParseIntegrityFailurePolicy(const AZ::CommandLine& cmd)
{
const BinaryStateValue<Policy::IntegrityFailure> states =
{
Policy::IntegrityFailure::Abort,
Policy::IntegrityFailure::Continue
};
return ParseAbortContinueOption(OptionKeys[IntegrityFailurePolicyKey], states, cmd).value_or(Policy::IntegrityFailure::Abort);
}
Policy::TestSharding ParseTestShardingPolicy(const AZ::CommandLine& cmd)
{
const BinaryStateValue<Policy::TestSharding> states =
{
Policy::TestSharding::Never,
Policy::TestSharding::Always
};
return ParseOnOffOption(OptionKeys[TestShardingPolicyKey], states, cmd).value_or(Policy::TestSharding::Never);
}
Policy::TargetOutputCapture ParseTargetOutputCapture(const AZ::CommandLine& cmd)
{
if (const auto numSwitchValues = cmd.GetNumSwitchValues(OptionKeys[TargetOutputCaptureKey]);
numSwitchValues)
{
AZ_TestImpact_Eval(
numSwitchValues <= 2, CommandLineOptionsException, "Unexpected parameters for target output capture option");
Policy::TargetOutputCapture targetOutputCapture = Policy::TargetOutputCapture::None;
for (auto i = 0; i < numSwitchValues; i++)
{
const auto option = cmd.GetSwitchValue(OptionKeys[TargetOutputCaptureKey], i);
if (option == OptionKeys[StdOut])
{
if (targetOutputCapture == Policy::TargetOutputCapture::File)
{
targetOutputCapture = Policy::TargetOutputCapture::StdOutAndFile;
}
else
{
targetOutputCapture = Policy::TargetOutputCapture::StdOut;
}
}
else if (option == OptionKeys[File])
{
if (targetOutputCapture == Policy::TargetOutputCapture::StdOut)
{
targetOutputCapture = Policy::TargetOutputCapture::StdOutAndFile;
}
else
{
targetOutputCapture = Policy::TargetOutputCapture::File;
}
}
else
{
throw CommandLineOptionsException(
AZStd::string::format("Unexpected value for target output capture option: %s", option.c_str()));
}
}
return targetOutputCapture;
}
return Policy::TargetOutputCapture::None;
}
AZStd::optional<size_t> ParseMaxConcurrency(const AZ::CommandLine& cmd)
{
return ParseUnsignedIntegerOption(OptionKeys[MaxConcurrencyKey], cmd);
}
AZStd::optional<AZStd::chrono::milliseconds> ParseTestTargetTimeout(const AZ::CommandLine& cmd)
{
return ParseSecondsOption(OptionKeys[TestTargetTimeoutKey], cmd);
}
AZStd::optional<AZStd::chrono::milliseconds> ParseGlobalTimeout(const AZ::CommandLine& cmd)
{
return ParseSecondsOption(OptionKeys[GlobalTimeoutKey], cmd);
}
bool ParseSafeMode(const AZ::CommandLine& cmd)
{
const BinaryStateValue<bool> states = { false, true };
return ParseOnOffOption(OptionKeys[SafeModeKey], states, cmd).value_or(false);
}
SuiteType ParseSuiteFilter(const AZ::CommandLine& cmd)
{
const AZStd::vector<AZStd::pair<AZStd::string, SuiteType>> states =
{
{GetSuiteTypeName(SuiteType::Main), SuiteType::Main},
{GetSuiteTypeName(SuiteType::Periodic), SuiteType::Periodic},
{GetSuiteTypeName(SuiteType::Sandbox), SuiteType::Sandbox}
};
return ParseMultiStateOption(OptionKeys[SuiteFilterKey], states, cmd).value_or(SuiteType::Main);
}
}
CommandLineOptions::CommandLineOptions(int argc, char** argv)
{
AZ::CommandLine cmd;
cmd.Parse(argc, argv);
m_configurationFile = ParseConfigurationFile(cmd);
m_changeListFile = ParseChangeListFile(cmd);
m_outputChangeList = ParseOutputChangeList(cmd);
m_testSequenceType = ParseTestSequenceType(cmd);
m_testPrioritizationPolicy = ParseTestPrioritizationPolicy(cmd);
m_executionFailurePolicy = ParseExecutionFailurePolicy(cmd);
m_failedTestCoveragePolicy = ParseFailedTestCoveragePolicy(cmd);
m_testFailurePolicy = ParseTestFailurePolicy(cmd);
m_integrityFailurePolicy = ParseIntegrityFailurePolicy(cmd);
m_testShardingPolicy = ParseTestShardingPolicy(cmd);
m_targetOutputCapture = ParseTargetOutputCapture(cmd);
m_maxConcurrency = ParseMaxConcurrency(cmd);
m_testTargetTimeout = ParseTestTargetTimeout(cmd);
m_globalTimeout = ParseGlobalTimeout(cmd);
m_safeMode = ParseSafeMode(cmd);
m_suiteFilter = ParseSuiteFilter(cmd);
}
bool CommandLineOptions::HasChangeListFile() const
{
return m_changeListFile.has_value();
}
bool CommandLineOptions::HasSafeMode() const
{
return m_safeMode;
}
const AZStd::optional<RepoPath>& CommandLineOptions::GetChangeListFile() const
{
return m_changeListFile;
}
bool CommandLineOptions::HasOutputChangeList() const
{
return m_outputChangeList;
}
const RepoPath& CommandLineOptions::GetConfigurationFile() const
{
return m_configurationFile;
}
TestSequenceType CommandLineOptions::GetTestSequenceType() const
{
return m_testSequenceType;
}
Policy::TestPrioritization CommandLineOptions::GetTestPrioritizationPolicy() const
{
return m_testPrioritizationPolicy;
}
Policy::ExecutionFailure CommandLineOptions::GetExecutionFailurePolicy() const
{
return m_executionFailurePolicy;
}
Policy::FailedTestCoverage CommandLineOptions::GetFailedTestCoveragePolicy() const
{
return m_failedTestCoveragePolicy;
}
Policy::TestFailure CommandLineOptions::GetTestFailurePolicy() const
{
return m_testFailurePolicy;
}
Policy::IntegrityFailure CommandLineOptions::GetIntegrityFailurePolicy() const
{
return m_integrityFailurePolicy;
}
Policy::TestSharding CommandLineOptions::GetTestShardingPolicy() const
{
return m_testShardingPolicy;
}
Policy::TargetOutputCapture CommandLineOptions::GetTargetOutputCapture() const
{
return m_targetOutputCapture;
}
const AZStd::optional<size_t>& CommandLineOptions::GetMaxConcurrency() const
{
return m_maxConcurrency;
}
const AZStd::optional<AZStd::chrono::milliseconds>& CommandLineOptions::GetTestTargetTimeout() const
{
return m_testTargetTimeout;
}
const AZStd::optional<AZStd::chrono::milliseconds>& CommandLineOptions::GetGlobalTimeout() const
{
return m_globalTimeout;
}
SuiteType CommandLineOptions::GetSuiteFilter() const
{
return m_suiteFilter;
}
AZStd::string CommandLineOptions::GetCommandLineUsageString()
{
AZStd::string help =
"usage: tiaf [options]\n"
" options:\n"
" -config=<filename> Path to the configuration file for the TIAF runtime (default: \n"
" <tiaf binay build dir>.<tiaf binary build type>.json).\n"
" -changelist=<filename> Path to the JSON of source file changes to perform test impact \n"
" analysis on.\n"
" -gtimeout=<seconds> Global timeout value to terminate the entire test sequence should it \n"
" be exceeded.\n"
" -ttimeout=<seconds> Timeout value to terminate individual test targets should it be \n"
" exceeded.\n"
" -sequence=<none, seed, regular, tia, tianowrite, tiaorseed> The type of test sequence to perform, where 'none' runs no tests and\n"
" will report a all tests successful, 'seed' removes any prior coverage \n"
" data and runs all test targets with instrumentation to reseed the \n"
" data from scratch, 'regular' runs all of the test targets without any \n"
" instrumentation to generate coverage data(any prior coverage data is \n"
" left intact), 'tia' uses any prior coverage data to run the instrumented \n"
" subset of selected tests(if no prior coverage data a regular run is \n"
" performed instead), 'tianowrite' uses any prior coverage data to run the \n"
" uninstrumented subset of selected tests (if no prior coverage data a \n"
" regular run is performed instead). The coverage data is not updated with \n"
" the subset of selected tests and 'tiaorseed' uses any prior coverage data \n"
" to run the instrumented subset of selected tests (if no prior coverage \n"
" data a seed run is performed instead).\n"
" -safemode=<on,off> Flag to specify a safe mode sequence where the set of unselected \n"
" tests is run without instrumentation after the set of selected \n"
" instrumented tests is run (this has the effect of ensuring all \n"
" tests are run regardless).\n"
" -shard=<on,off> Break any test targets with a sharding policy into the number of \n"
" shards according to the maximum concurrency value.\n"
" -cpolicy=<remove, keep> Policy for handling the coverage data of failing tests, where 'discard' \n"
" will discard the coverage data produced by the failing tests, causing \n"
" them to be drafted into future test runs and 'keep' will keep any existing \n"
" coverage data and update the coverage data for failed tests that produce \n"
" coverage.\n"
" -targetout=<sdtout, file> Capture of individual test run stdout, where 'stdout' will capture \n"
" each individual test target's stdout and output each one to stdout \n"
" and 'file' will capture each individual test target's stdout and output \n"
" each one individually to a file (multiple values are accepted).\n"
" -epolicy=<abort, continue, ignore> Policy for handling test execution failure (test targets could not be \n"
" launched due to the binary not being built, incorrect paths, etc.), \n"
" where 'abort' will abort the entire test sequence upon the first test\n"
" target execution failure and report a failure(along with the return \n"
" code of the test target that failed to launch), 'continue' will continue \n"
" with the test sequence in the event of test target execution failures\n"
" and treat the test targets that failed to launch as test failures\n"
" (along with the return codes of the test targets that failed to \n"
" launch), 'ignore' will continue with the test sequence in the event of \n"
" test target execution failures and treat the test targets that failed\n"
" to launch as test passes(along with the return codes of the test \n"
" targets that failed to launch).\n"
" -fpolicy <abort, continue> Policy for handling test failures (test targets report failing tests), \n"
" where 'abort' will abort the entire test sequence upon the first test \n"
" failure and report a failure and 'continue' will continue with the test\n"
" sequence in the event of test failures and report the test failures.\n"
" -ipolicy=<abort, seed, rerun> Policy for handling coverage data integrity failures, where 'abort' will \n"
" abort the test sequence and report a failure, 'seed' will attempt another \n"
" sequence using the seed sequence type, otherwise will abort and report \n"
" a failure (this option has no effect for regular and seed sequence \n"
" types) and 'rerun' will attempt another sequence using the regular \n"
" sequence type, otherwise will abort and report a failure(this option has \n"
" no effect for regular sequence type).\n"
" -ppolicy=<none, locality> Policy for prioritizing selected test targets, where 'none' will not \n"
" attempt any test target prioritization and 'locality' will attempt to \n"
" prioritize test targets according to the locality of their covering \n"
" production targets in the dependency graph(if no dependency graph data \n"
" available, no prioritization will occur).\n"
" -maxconcurrency=<number> The maximum number of concurrent test targets/shards to be in flight at \n"
" any given moment.\n"
" -ochangelist=<on,off> Outputs the change list used for test selection.\n"
" -suite=<main, periodic, sandbox> The test suite to select from for this test sequence.";
return help;
}
} // namespace TestImpact
@@ -0,0 +1,112 @@
/*
* 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/TestImpactTestSequence.h>
#include <TestImpactFramework/TestImpactRepoPath.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/containers/vector.h>
namespace TestImpact
{
//! The type of test sequence to run.
enum class TestSequenceType
{
None, //!< Runs no tests and will report all tests successful.
Seed, //!< Removes any prior coverage data and runs all test targets with instrumentation to reseed the data from scratch.
Regular, //!< Runs all of the test targets without any instrumentation to generate coverage data (any prior coverage data is left intact).
ImpactAnalysis, //!< Uses any prior coverage data to run the instrumented subset of selected tests (if no prior coverage data a regular run is performed instead).
ImpactAnalysisNoWrite, //!< Uses any prior coverage data to run the uninstrumented subset of selected tests (if no prior coverage data a regular run is performed instead).
//!< The coverage data is not updated with the subset of selected tests.
ImpactAnalysisOrSeed //!< Uses any prior coverage data to run the instrumented subset of selected tests (if no prior coverage data a seed run is performed instead).
};
//! Representation of the command line options supplied to the console frontend application.
class CommandLineOptions
{
public:
CommandLineOptions(int argc, char** argv);
static AZStd::string GetCommandLineUsageString();
//! Returns true if a change list file path has been supplied, otherwise false.
bool HasChangeListFile() const;
//! Returns true if the safe mode option has been enabled, otherwise false.
bool HasSafeMode() const;
//! Returns true if the output change list option has been enabled, otherwise false.
bool HasOutputChangeList() const;
//! Returns the path to the runtime configuration file.
const RepoPath& GetConfigurationFile() const;
//! Returns the path to the change list file (if any).
const AZStd::optional<RepoPath>& GetChangeListFile() const;
//! Returns the test sequence type to run.
TestSequenceType GetTestSequenceType() const;
//! Returns the test prioritization policy to use.
Policy::TestPrioritization GetTestPrioritizationPolicy() const;
//! Returns the test execution failure policy to use.
Policy::ExecutionFailure GetExecutionFailurePolicy() const;
//! Returns failed test coverage drafting policy to use.
Policy::FailedTestCoverage GetFailedTestCoveragePolicy() const;
//! Returns the test failure policy to use.
Policy::TestFailure GetTestFailurePolicy() const;
//! Returns the integration failure policy to use.
Policy::IntegrityFailure GetIntegrityFailurePolicy() const;
//! Returns the test sharding policy to use.
Policy::TestSharding GetTestShardingPolicy() const;
//! Returns the test target standard output capture policy to use.
Policy::TargetOutputCapture GetTargetOutputCapture() const;
//! Returns the maximum number of test targets to be in flight at any given time.
const AZStd::optional<size_t>& GetMaxConcurrency() const;
//! Returns the individual test target timeout to use (if any).
const AZStd::optional<AZStd::chrono::milliseconds>& GetTestTargetTimeout() const;
//! Returns the global test sequence timeout to use (if any).
const AZStd::optional<AZStd::chrono::milliseconds>& GetGlobalTimeout() const;
//! Returns the filter for test suite that will be allowed to be run.
SuiteType GetSuiteFilter() const;
private:
RepoPath m_configurationFile;
AZStd::optional<RepoPath> m_changeListFile;
bool m_outputChangeList = false;
TestSequenceType m_testSequenceType;
Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None;
Policy::ExecutionFailure m_executionFailurePolicy = Policy::ExecutionFailure::Continue;
Policy::FailedTestCoverage m_failedTestCoveragePolicy = Policy::FailedTestCoverage::Keep;
Policy::TestFailure m_testFailurePolicy = Policy::TestFailure::Abort;
Policy::IntegrityFailure m_integrityFailurePolicy = Policy::IntegrityFailure::Abort;
Policy::TestSharding m_testShardingPolicy = Policy::TestSharding::Never;
Policy::TargetOutputCapture m_targetOutputCapture = Policy::TargetOutputCapture::None;
AZStd::optional<size_t> m_maxConcurrency;
AZStd::optional<AZStd::chrono::milliseconds> m_testTargetTimeout;
AZStd::optional<AZStd::chrono::milliseconds> m_globalTimeout;
SuiteType m_suiteFilter;
bool m_safeMode = false;
};
} // namespace TestImpact
@@ -0,0 +1,26 @@
/*
* 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 command line options.
class CommandLineOptionsException
: public Exception
{
public:
using Exception::Exception;
};
} // namespace TestImpact
@@ -0,0 +1,79 @@
/*
* 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 <TestImpactCommandLineOptionsUtils.h>
#include <AzCore/std/string/conversions.h>
namespace TestImpact
{
//! Attempts to parse a path option value.
AZStd::optional<RepoPath> ParsePathOption(const AZStd::string& optionName, const AZ::CommandLine& cmd)
{
if (const auto numSwitchValues = cmd.GetNumSwitchValues(optionName);
numSwitchValues)
{
AZ_TestImpact_Eval(
numSwitchValues == 1,
CommandLineOptionsException,
AZStd::string::format("Unexpected number of parameters for %s option", optionName.c_str()));
const auto value = cmd.GetSwitchValue(optionName, 0);
AZ_TestImpact_Eval(
!value.empty(),
CommandLineOptionsException,
AZStd::string::format("%s file option value is empty", optionName.c_str()));
return value;
}
return AZStd::nullopt;
}
//! Attempts to pass an unsigned integer option value.
AZStd::optional<size_t> ParseUnsignedIntegerOption(const AZStd::string& optionName, const AZ::CommandLine& cmd)
{
if (const auto numSwitchValues = cmd.GetNumSwitchValues(optionName);
numSwitchValues)
{
AZ_TestImpact_Eval(
numSwitchValues == 1,
CommandLineOptionsException,
AZStd::string::format("Unexpected number of parameters for %s option", optionName.c_str()));
const auto strValue = cmd.GetSwitchValue(optionName, 0);
size_t successfulParse = 0; // Will be non-zero if the parse was successful
auto value = AZStd::stoul(strValue, &successfulParse, 0);
AZ_TestImpact_Eval(
successfulParse,
CommandLineOptionsException,
AZStd::string::format("Couldn't parse unsigned integer option value: %s", strValue.c_str()));
return aznumeric_caster(value);
}
return AZStd::nullopt;
}
//! Attempts to parse an option value in seconds.
AZStd::optional<AZStd::chrono::milliseconds> ParseSecondsOption(const AZStd::string& optionName, const AZ::CommandLine& cmd)
{
if (const auto option = ParseUnsignedIntegerOption(optionName, cmd);
option.has_value())
{
return AZStd::chrono::seconds(option.value());
}
return AZStd::nullopt;
}
} // namespace TestImpact
@@ -0,0 +1,122 @@
/*
* 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 <TestImpactCommandLineOptions.h>
#include <TestImpactCommandLineOptionsException.h>
#include <AzCore/Settings/CommandLine.h>
namespace TestImpact
{
//! Representation of a command line option value name and its typed value.
template<typename T>
using OptionValue = AZStd::pair<AZStd::string, T>;
//! Representation of a binary state command line option with its two values.
template<typename T>
using BinaryStateOption = AZStd::pair<OptionValue<T>, OptionValue<T>>;
//! Representation of the values for a binary state option.
template<typename T>
using BinaryStateValue = AZStd::pair<T, T>;
//! Attempts to parse the specified binary state option.
template<typename T>
AZStd::optional<T> ParseBinaryStateOption(
const AZStd::string& optionName,
const AZStd::pair<OptionValue<T>,
OptionValue<T>>& state, const AZ::CommandLine& cmd)
{
if (const auto numSwitchValues = cmd.GetNumSwitchValues(optionName);
numSwitchValues)
{
AZ_TestImpact_Eval(
numSwitchValues == 1,
CommandLineOptionsException,
AZStd::string::format("Unexpected number of parameters for %s option", optionName.c_str()));
const auto option = cmd.GetSwitchValue(optionName, 0);
if (const auto& [optionValueText, optionValue] = state.first;
option == optionValueText)
{
return optionValue;
}
if (const auto& [optionValueText, optionValue] = state.second;
option == optionValueText)
{
return optionValue;
}
throw CommandLineOptionsException(
AZStd::string::format("Unexpected value for %s option: %s", optionName.c_str(), option.c_str()));
}
return AZStd::nullopt;
}
//! Attempts to pass an arbitrarily sized state option.
template<typename T>
AZStd::optional<T> ParseMultiStateOption(
const AZStd::string& optionName,
const AZStd::vector<AZStd::pair<AZStd::string, T>>& states,
const AZ::CommandLine& cmd)
{
if (const auto numSwitchValues = cmd.GetNumSwitchValues(optionName);
numSwitchValues)
{
AZ_TestImpact_Eval(
numSwitchValues == 1,
CommandLineOptionsException,
AZStd::string::format("Unexpected number of parameters for %s option", optionName.c_str()));
const auto option = cmd.GetSwitchValue(optionName, 0);
for (const auto& state : states)
{
if (const auto& [optionValueText, optionValue] = state;
option == optionValueText)
{
return optionValue;
}
}
throw CommandLineOptionsException(
AZStd::string::format("Unexpected value for %s option: %s", optionName.c_str(), option.c_str()));
}
return AZStd::nullopt;
}
//! Attempts to pass a specialization of the binary state option where the command line values are "on" and "off".
template<typename T>
AZStd::optional<T> ParseOnOffOption(const AZStd::string& optionName, const AZStd::pair<T, T>& states, const AZ::CommandLine& cmd)
{
return ParseBinaryStateOption(optionName, BinaryStateOption<T>{ {"off", states.first}, { "on", states.second } }, cmd);
}
//! Attempts to pass a specialization of the binary state option where the command line values are "abort" and "continue".
template<typename T>
AZStd::optional<T> ParseAbortContinueOption(const AZStd::string& optionName, const AZStd::pair<T, T>& states, const AZ::CommandLine& cmd)
{
return ParseBinaryStateOption(optionName, BinaryStateOption<T>{ {"abort", states.first}, { "continue", states.second } }, cmd);
}
//! Attempts to parse a path option value.
AZStd::optional<RepoPath> ParsePathOption(const AZStd::string& optionName, const AZ::CommandLine& cmd);
//! Attempts to pass an unsigned integer option value.
AZStd::optional<size_t> ParseUnsignedIntegerOption(const AZStd::string& optionName, const AZ::CommandLine& cmd);
//! Attempts to parse an option value in seconds.
AZStd::optional<AZStd::chrono::milliseconds> ParseSecondsOption(const AZStd::string& optionName, const AZ::CommandLine& cmd);
} // namespace TestImpact
@@ -0,0 +1,29 @@
/*
* 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/TestImpactConsoleMain.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Memory/SystemAllocator.h>
int main(int argc, char** argv)
{
AZ::AllocatorInstance<AZ::OSAllocator>::Create();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
TestImpact::Console::ReturnCode returnCode = TestImpact::Console::Main(argc, argv);
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
return static_cast<int>(returnCode);
}
@@ -0,0 +1,316 @@
/*
* 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 <TestImpactFramework/TestImpactChangeListException.h>
#include <TestImpactFramework/TestImpactConfigurationException.h>
#include <TestImpactFramework/TestImpactRuntimeException.h>
#include <TestImpactFramework/TestImpactConsoleMain.h>
#include <TestImpactFramework/TestImpactChangeListSerializer.h>
#include <TestImpactFramework/TestImpactChangeList.h>
#include <TestImpactFramework/TestImpactRuntime.h>
#include <TestImpactFramework/TestImpactFileUtils.h>
#include <TestImpactFramework/TestImpactClientTestSelection.h>
#include <TestImpactFramework/TestImpactRuntime.h>
#include <TestImpactConsoleTestSequenceEventHandler.h>
#include <TestImpactCommandLineOptions.h>
#include <TestImpactRuntimeConfigurationFactory.h>
#include <TestImpactCommandLineOptionsException.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <iostream>
namespace TestImpact
{
namespace Console
{
//! Generates a string to be used for printing to the console for the specified change list.
AZStd::string GenerateChangeListString(const ChangeList& changeList)
{
AZStd::string output;
const auto& outputFiles = [&output](const AZStd::vector<RepoPath>& files)
{
for (const auto& file : files)
{
output += AZStd::string::format("\t%s\n", file.c_str());
}
};
output += AZStd::string::format("Created files (%u):\n", changeList.m_createdFiles.size());
outputFiles(changeList.m_createdFiles);
output += AZStd::string::format("Updated files (%u):\n", changeList.m_updatedFiles.size());
outputFiles(changeList.m_updatedFiles);
output += AZStd::string::format("Deleted files (%u):\n", changeList.m_deletedFiles.size());
outputFiles(changeList.m_deletedFiles);
return output;
}
//! Gets the appropriate console return code for the specified test sequence result.
ReturnCode GetReturnCodeForTestSequenceResult(TestSequenceResult result)
{
switch (result)
{
case TestSequenceResult::Success:
return ReturnCode::Success;
case TestSequenceResult::Failure:
return ReturnCode::TestFailure;
case TestSequenceResult::Timeout:
return ReturnCode::Timeout;
default:
std::cout << "Unexpected TestSequenceResult value: " << aznumeric_cast<size_t>(result) << std::endl;
return ReturnCode::UnknownError;
}
}
//! Wrapper around impact analysis sequences to handle the case where the safe mode option is active.
ReturnCode WrappedImpactAnalysisTestSequence(
TestSequenceEventHandler& sequenceEventHandler,
const CommandLineOptions& options,
Runtime& runtime,
const AZStd::optional<ChangeList>& changeList)
{
// Even though it is possible for a regular run to be selected (see below) which does not actually require a change list,
// consider any impact analysis sequence type without a change list to be an error
AZ_TestImpact_Eval(
changeList.has_value(),
CommandLineOptionsException,
"Expected a change list for impact analysis but none was provided");
TestSequenceResult result = TestSequenceResult::Failure;
if (options.HasSafeMode())
{
if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysis)
{
auto [selectedResult, discardedResult] = runtime.SafeImpactAnalysisTestSequence(
changeList.value(),
options.GetTestPrioritizationPolicy(),
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
// Handling the possible timeout and failure permutations of the selected and discarded test results is splitting hairs
// so apply the following, admittedly arbitrary, rules to determine what the composite test sequence result should be
if (selectedResult == TestSequenceResult::Success && discardedResult == TestSequenceResult::Success)
{
// Trivial case: both sequences succeeded
result = TestSequenceResult::Success;
}
else if (selectedResult == TestSequenceResult::Failure || discardedResult == TestSequenceResult::Failure)
{
// One sequence failed whilst the other sequence either succeeded or timed out
result = TestSequenceResult::Failure;
}
else
{
// One or both sequences timed out or failed
result = TestSequenceResult::Timeout;
}
}
else if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysisNoWrite)
{
// A no-write impact analysis sequence with safe mode enabled is functionally identical to a regular sequence type
// due to a) the selected tests being run without instrumentation and b) the discarded tests also being run without
// instrumentation
result = runtime.RegularTestSequence(
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
}
else
{
throw(Exception("Unexpected sequence type"));
}
}
else
{
Policy::DynamicDependencyMap dynamicDependencyMapPolicy;
if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysis)
{
dynamicDependencyMapPolicy = Policy::DynamicDependencyMap::Update;
}
else if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysisNoWrite)
{
dynamicDependencyMapPolicy = Policy::DynamicDependencyMap::Discard;
}
else
{
throw(Exception("Unexpected sequence type"));
}
result = runtime.ImpactAnalysisTestSequence(
changeList.value(),
options.GetTestPrioritizationPolicy(),
dynamicDependencyMapPolicy,
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
}
return GetReturnCodeForTestSequenceResult(result);
};
//! Entry point for the test impact analysis framework console front end application.
ReturnCode Main(int argc, char** argv)
{
try
{
CommandLineOptions options(argc, argv);
AZStd::optional<ChangeList> changeList;
// If we have a change list, check to see whether or not the client has requested the printing of said change list
if (options.HasChangeListFile())
{
changeList = DeserializeChangeList(ReadFileContents<CommandLineOptionsException>(*options.GetChangeListFile()));
if (options.HasOutputChangeList())
{
std::cout << "Change List:\n";
std::cout << GenerateChangeListString(*changeList).c_str();
if (options.GetTestSequenceType() == TestSequenceType::None)
{
return ReturnCode::Success;
}
}
}
// As of now, there are no other non-test operations other than printing a change list so getting this far is considered an error
AZ_TestImpact_Eval(options.GetTestSequenceType() != TestSequenceType::None, CommandLineOptionsException, "No action specified");
std::cout << "Constructing in-memory model of source tree and test coverage for test suite ";
std::cout << GetSuiteTypeName(options.GetSuiteFilter()).c_str() << ", this may take a moment...\n";
Runtime runtime(
RuntimeConfigurationFactory(ReadFileContents<CommandLineOptionsException>(options.GetConfigurationFile())),
options.GetSuiteFilter(),
options.GetExecutionFailurePolicy(),
options.GetFailedTestCoveragePolicy(),
options.GetTestFailurePolicy(),
options.GetIntegrityFailurePolicy(),
options.GetTestShardingPolicy(),
options.GetTargetOutputCapture(),
options.GetMaxConcurrency());
if (runtime.HasImpactAnalysisData())
{
std::cout << "Test impact analysis data for this repository was found.\n";
}
else
{
std::cout << "Test impact analysis data for this repository was not found, seed or regular sequence fallbacks will be used.\n";
}
TestSequenceEventHandler sequenceEventHandler(options.GetSuiteFilter());
switch (const auto type = options.GetTestSequenceType())
{
case TestSequenceType::Regular:
{
const auto result = runtime.RegularTestSequence(
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
return GetReturnCodeForTestSequenceResult(result);
}
case TestSequenceType::Seed:
{
const auto result = runtime.SeededTestSequence(
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
return GetReturnCodeForTestSequenceResult(result);
}
case TestSequenceType::ImpactAnalysisNoWrite:
case TestSequenceType::ImpactAnalysis:
{
return WrappedImpactAnalysisTestSequence(sequenceEventHandler, options, runtime, changeList);
}
case TestSequenceType::ImpactAnalysisOrSeed:
{
if (runtime.HasImpactAnalysisData())
{
return WrappedImpactAnalysisTestSequence(sequenceEventHandler, options, runtime, changeList);
}
else
{
const auto result = runtime.SeededTestSequence(
options.GetTestTargetTimeout(),
options.GetGlobalTimeout(),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler),
AZStd::ref(sequenceEventHandler));
return GetReturnCodeForTestSequenceResult(result);
}
}
default:
std::cout << "Unexpected TestSequenceType value: " << static_cast<size_t>(type) << std::endl;
return ReturnCode::UnknownError;
}
}
catch (const CommandLineOptionsException& e)
{
std::cout << e.what() << std::endl;
std::cout << CommandLineOptions::GetCommandLineUsageString().c_str() << std::endl;
return ReturnCode::InvalidArgs;
}
catch (const ChangeListException& e)
{
std::cout << e.what() << std::endl;
return ReturnCode::InvalidUnifiedDiff;
}
catch (const ConfigurationException& e)
{
std::cout << e.what() << std::endl;
return ReturnCode::InvalidConfiguration;
}
catch (const RuntimeException& e)
{
std::cout << e.what() << std::endl;
return ReturnCode::RuntimeError;
}
catch (const Exception& e)
{
std::cout << e.what() << std::endl;
return ReturnCode::UnhandledError;
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
return ReturnCode::UnknownError;
}
catch (...)
{
std::cout << "An unknown error occurred" << std::endl;
return ReturnCode::UnknownError;
}
}
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,234 @@
/*
* 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 <TestImpactConsoleTestSequenceEventHandler.h>
#include <TestImpactConsoleUtils.h>
#include <iostream>
namespace TestImpact
{
namespace Console
{
namespace Output
{
void TestSuiteFilter(SuiteType filter)
{
std::cout << "Test suite filter: " << GetSuiteTypeName(filter).c_str() << "\n";
}
void ImpactAnalysisTestSelection(size_t numSelectedTests, size_t numDiscardedTests, size_t numExcludedTests, size_t numDraftedTests)
{
const float totalTests = numSelectedTests + numDiscardedTests;
const float saving = (1.0 - (numSelectedTests / totalTests)) * 100.0f;
std::cout << numSelectedTests << " tests selected, " << numDiscardedTests << " tests discarded (" << saving << "% test saving)\n";
std::cout << "Of which " << numExcludedTests << " tests have been excluded and " << numDraftedTests << " tests have been drafted.\n";
}
void FailureReport(const Client::SequenceFailure& failureReport, AZStd::chrono::milliseconds duration)
{
std::cout << "Sequence completed in " << (duration.count() / 1000.f) << "s with";
if (!failureReport.GetExecutionFailures().empty() ||
!failureReport.GetTestRunFailures().empty() ||
!failureReport.GetTimedOutTests().empty() ||
!failureReport.GetUnexecutedTests().empty())
{
std::cout << ":\n";
std::cout << SetColor(Foreground::White, Background::Red).c_str()
<< failureReport.GetTestRunFailures().size()
<< ResetColor().c_str() << " test failures\n";
std::cout << SetColor(Foreground::White, Background::Red).c_str()
<< failureReport.GetExecutionFailures().size()
<< ResetColor().c_str() << " execution failures\n";
std::cout << SetColor(Foreground::White, Background::Red).c_str()
<< failureReport.GetTimedOutTests().size()
<< ResetColor().c_str() << " test timeouts\n";
std::cout << SetColor(Foreground::White, Background::Red).c_str()
<< failureReport.GetUnexecutedTests().size()
<< ResetColor().c_str() << " unexecuted tests\n";
if (!failureReport.GetTestRunFailures().empty())
{
std::cout << "\nTest failures:\n";
for (const auto& testRunFailure : failureReport.GetTestRunFailures())
{
std::cout << " " << testRunFailure.GetTargetName().c_str();
for (const auto& testCaseFailure : testRunFailure.GetTestCaseFailures())
{
std::cout << "." << testCaseFailure.GetName().c_str();
for (const auto& testFailure : testCaseFailure.GetTestFailures())
{
std::cout << "." << testFailure.GetName().c_str() << "\n";
}
}
}
}
if (!failureReport.GetExecutionFailures().empty())
{
std::cout << "\nExecution failures:\n";
for (const auto& executionFailure : failureReport.GetExecutionFailures())
{
std::cout << " " << executionFailure.GetTargetName().c_str() << "\n";
std::cout << executionFailure.GetCommandString().c_str() << "\n";
}
}
if (!failureReport.GetTimedOutTests().empty())
{
std::cout << "\nTimed out tests:\n";
for (const auto& testTimeout : failureReport.GetTimedOutTests())
{
std::cout << " " << testTimeout.GetTargetName().c_str() << "\n";
}
}
if (!failureReport.GetUnexecutedTests().empty())
{
std::cout << "\nUnexecuted tests:\n";
for (const auto& unexecutedTest : failureReport.GetUnexecutedTests())
{
std::cout << " " << unexecutedTest.GetTargetName().c_str() << "\n";
}
}
}
else
{
std::cout << SetColor(Foreground::White, Background::Green).c_str() << " \100% passes!\n" << ResetColor().c_str();
}
}
}
TestSequenceEventHandler::TestSequenceEventHandler(SuiteType suiteFilter)
: m_suiteFilter(suiteFilter)
{
}
// TestSequenceStartCallback
void TestSequenceEventHandler::operator()(Client::TestRunSelection&& selectedTests)
{
ClearState();
m_numTests = selectedTests.GetNumIncludedTestRuns();
Output::TestSuiteFilter(m_suiteFilter);
std::cout << selectedTests.GetNumIncludedTestRuns() << " tests selected, " << selectedTests.GetNumExcludedTestRuns() << " excluded.\n";
}
// ImpactAnalysisTestSequenceStartCallback
void TestSequenceEventHandler::operator()(
Client::TestRunSelection&& selectedTests,
AZStd::vector<AZStd::string>&& discardedTests,
AZStd::vector<AZStd::string>&& draftedTests)
{
ClearState();
m_numTests = selectedTests.GetNumIncludedTestRuns() + draftedTests.size();
Output::TestSuiteFilter(m_suiteFilter);
Output::ImpactAnalysisTestSelection(
selectedTests.GetTotalNumTests(), discardedTests.size(), selectedTests.GetNumExcludedTestRuns(), draftedTests.size());
}
// SafeImpactAnalysisTestSequenceStartCallback
void TestSequenceEventHandler::operator()(
Client::TestRunSelection&& selectedTests,
Client::TestRunSelection&& discardedTests,
AZStd::vector<AZStd::string>&& draftedTests)
{
ClearState();
m_numTests = selectedTests.GetNumIncludedTestRuns() + draftedTests.size();
Output::TestSuiteFilter(m_suiteFilter);
Output::ImpactAnalysisTestSelection(
selectedTests.GetTotalNumTests(),
discardedTests.GetTotalNumTests(),
selectedTests.GetNumExcludedTestRuns() + discardedTests.GetNumExcludedTestRuns(),
draftedTests.size());
}
// TestSequenceCompleteCallback
void TestSequenceEventHandler::operator()(
Client::SequenceFailure&& failureReport,
AZStd::chrono::milliseconds duration)
{
Output::FailureReport(failureReport, duration);
std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n";
}
// SafeTestSequenceCompleteCallback
void TestSequenceEventHandler::operator()(
Client::SequenceFailure&& selectedFailureReport,
Client::SequenceFailure&& discardedFailureReport,
AZStd::chrono::milliseconds selectedDuration,
AZStd::chrono::milliseconds discaredDuration)
{
std::cout << "Selected test run:\n";
Output::FailureReport(selectedFailureReport, selectedDuration);
std::cout << "Discarded test run:\n";
Output::FailureReport(discardedFailureReport, discaredDuration);
std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n";
}
// TestRunCompleteCallback
void TestSequenceEventHandler::operator()([[maybe_unused]] Client::TestRun&& test)
{
m_numTestsComplete++;
const auto progress = AZStd::string::format("(%03u/%03u)", m_numTestsComplete, m_numTests, test.GetTargetName().c_str());
AZStd::string result;
switch (test.GetResult())
{
case Client::TestRunResult::AllTestsPass:
{
result = SetColorForString(Foreground::White, Background::Green, "PASS");
break;
}
case Client::TestRunResult::FailedToExecute:
{
result = SetColorForString(Foreground::White, Background::Red, "EXEC");
break;
}
case Client::TestRunResult::NotRun:
{
result = SetColorForString(Foreground::White, Background::Yellow, "SKIP");
break;
}
case Client::TestRunResult::TestFailures:
{
result = SetColorForString(Foreground::White, Background::Red, "FAIL");
break;
}
case Client::TestRunResult::Timeout:
{
result = SetColorForString(Foreground::White, Background::Magenta, "TIME");
break;
}
}
std::cout << progress.c_str() << " " << result.c_str() << " " << test.GetTargetName().c_str() << " (" << (test.GetDuration().count() / 1000.f) << "s)\n";
}
void TestSequenceEventHandler::ClearState()
{
m_numTests = 0;
m_numTestsComplete = 0;
}
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,72 @@
/*
* 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/TestImpactTestSequence.h>
#include <TestImpactFramework/TestImpactClientTestSelection.h>
#include <TestImpactFramework/TestImpactClientFailureReport.h>
#include <TestImpactFramework/TestImpactClientTestRun.h>
#include <AzCore/std/chrono/chrono.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/unordered_set.h>
#pragma once
namespace TestImpact
{
namespace Console
{
//! Event handler for all test sequence types.
class TestSequenceEventHandler
{
public:
explicit TestSequenceEventHandler(SuiteType suiteFilter);
//! TestSequenceStartCallback.
void operator()(Client::TestRunSelection&& selectedTests);
//! ImpactAnalysisTestSequenceStartCallback.
void operator()(
Client::TestRunSelection&& selectedTests,
AZStd::vector<AZStd::string>&& discardedTests,
AZStd::vector<AZStd::string>&& draftedTests);
//! SafeImpactAnalysisTestSequenceStartCallback.
void operator()(
Client::TestRunSelection&& selectedTests,
Client::TestRunSelection&& discardedTests,
AZStd::vector<AZStd::string>&& draftedTests);
//! TestSequenceCompleteCallback.
void operator()(
Client::SequenceFailure&& failureReport,
AZStd::chrono::milliseconds duration);
//! SafeTestSequenceCompleteCallback.
void operator()(
Client::SequenceFailure&& selectedFailureReport,
Client::SequenceFailure&& discardedFailureReport,
AZStd::chrono::milliseconds selectedDuration,
AZStd::chrono::milliseconds discaredDuration);
//! TestRunCompleteCallback.
void operator()(Client::TestRun&& test);
private:
void ClearState();
SuiteType m_suiteFilter;
size_t m_numTests = 0;
size_t m_numTestsComplete = 0;
};
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,34 @@
/*
* 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 <TestImpactConsoleUtils.h>
namespace TestImpact
{
namespace Console
{
AZStd::string SetColor(Foreground foreground, Background background)
{
return AZStd::string::format("\033[%u;%um", aznumeric_cast<uint32_t>(foreground), aznumeric_cast<uint32_t>(background));
}
AZStd::string SetColorForString(Foreground foreground, Background background, const AZStd::string& str)
{
return AZStd::string::format("%s%s%s", SetColor(foreground, background).c_str(), str.c_str(), ResetColor().c_str());
}
AZStd::string ResetColor()
{
return "\033[0m";
}
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,56 @@
/*
* 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 <AzCore/std/string/string.h>
namespace TestImpact
{
namespace Console
{
//! The set of available foreground colors.
enum class Foreground
{
Black = 30,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White
};
//! The set of available background colors.
enum class Background
{
Black = 40,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White
};
//! Returns a string to be used to set the specified foreground and background color.
AZStd::string SetColor(Foreground foreground, Background background);
//! Returns a string with the specified string set to the specified foreground and background color followed by a color reset.
AZStd::string SetColorForString(Foreground foreground, Background background, const AZStd::string& str);
//! Returns a string to be used to reset the color back to white foreground on black background.
AZStd::string ResetColor();
} // namespace Console
} // namespace TestImpact
@@ -0,0 +1,306 @@
/*
* 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/TestImpactConfigurationException.h>
#include <TestImpactRuntimeConfigurationFactory.h>
#include <AzCore/JSON/document.h>
#include <AzCore/std/functional.h>
#include <AzCore/std/optional.h>
namespace TestImpact
{
namespace Config
{
// Keys for pertinent JSON elements
constexpr const char* Keys[] =
{
"root",
"platform",
"relative_paths",
"artifact_dir",
"enumeration_cache_dir",
"test_impact_data_files",
"temp",
"active",
"target_sources",
"static",
"autogen",
"static",
"include_filters",
"input_output_pairer",
"input",
"dir",
"matchers",
"target_dependency_file",
"target_vertex",
"file",
"test_runner",
"instrumentation",
"bin",
"exclude",
"shard",
"fixture_contiguous",
"fixture_interleaved",
"test_contiguous",
"test_interleaved",
"never",
"target",
"policy",
"artifacts",
"meta",
"repo",
"workspace",
"build_target_descriptor",
"dependency_graph_data",
"test_target_meta",
"test_engine",
"target"
};
enum
{
Root = 0,
PlatformName,
RelativePaths,
ArtifactDir,
EnumerationCacheDir,
TestImpactDataFiles,
TempWorkspace,
ActiveWorkspace,
TargetSources,
StaticSources,
AutogenSources,
StaticArtifacts,
SourceIncludeFilters,
AutogenInputOutputPairer,
AutogenInputSources,
Directory,
DependencyGraphMatchers,
TargetDependencyFileMatcher,
TargetVertexMatcher,
TestTargetMetaFile,
TestRunner,
TestInstrumentation,
BinaryFile,
TargetExcludeFilter,
TestSharding,
ContinuousFixtureSharding,
InterleavedFixtureSharding,
ContinuousTestSharding,
InterleavedTestSharding,
NeverShard,
TargetName,
TestShardingPolicy,
Artifacts,
Meta,
Repository,
Workspace,
BuildTargetDescriptor,
DependencyGraphData,
TestTargetMeta,
TestEngine,
TargetConfig
};
}
//! Returns an absolute path for a path relative to the specified root.
RepoPath GetAbsPathFromRelPath(const RepoPath& root, const RepoPath& rel)
{
return root / rel;
}
ConfigMeta ParseConfigMeta(const rapidjson::Value& meta)
{
ConfigMeta configMeta;
configMeta.m_platform = meta[Config::Keys[Config::PlatformName]].GetString();
return configMeta;
}
RepoConfig ParseRepoConfig(const rapidjson::Value& repo)
{
RepoConfig repoConfig;
repoConfig.m_root = repo[Config::Keys[Config::Root]].GetString();
return repoConfig;
}
WorkspaceConfig::Temp ParseTempWorkspaceConfig(const rapidjson::Value& tempWorkspace)
{
WorkspaceConfig::Temp tempWorkspaceConfig;
tempWorkspaceConfig.m_root = tempWorkspace[Config::Keys[Config::Root]].GetString();
tempWorkspaceConfig.m_artifactDirectory =
GetAbsPathFromRelPath(
tempWorkspaceConfig.m_root, tempWorkspace[Config::Keys[Config::RelativePaths]][Config::Keys[Config::ArtifactDir]].GetString());
return tempWorkspaceConfig;
}
AZStd::array<RepoPath, 3> ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTIAFile)
{
AZStd::array<RepoPath, 3> sparTIAFiles;
sparTIAFiles[static_cast<size_t>(SuiteType::Main)] =
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Main).c_str()].GetString());
sparTIAFiles[static_cast<size_t>(SuiteType::Periodic)] =
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Periodic).c_str()].GetString());
sparTIAFiles[static_cast<size_t>(SuiteType::Sandbox)] =
GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Sandbox).c_str()].GetString());
return sparTIAFiles;
}
WorkspaceConfig::Active ParseActiveWorkspaceConfig(const rapidjson::Value& activeWorkspace)
{
WorkspaceConfig::Active activeWorkspaceConfig;
const auto& relativePaths = activeWorkspace[Config::Keys[Config::RelativePaths]];
activeWorkspaceConfig.m_root = activeWorkspace[Config::Keys[Config::Root]].GetString();
activeWorkspaceConfig.m_enumerationCacheDirectory
= GetAbsPathFromRelPath(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::EnumerationCacheDir]].GetString());
activeWorkspaceConfig.m_sparTIAFiles =
ParseTestImpactAnalysisDataFiles(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::TestImpactDataFiles]]);
return activeWorkspaceConfig;
}
WorkspaceConfig ParseWorkspaceConfig(const rapidjson::Value& workspace)
{
WorkspaceConfig workspaceConfig;
workspaceConfig.m_temp = ParseTempWorkspaceConfig(workspace[Config::Keys[Config::TempWorkspace]]);
workspaceConfig.m_active = ParseActiveWorkspaceConfig(workspace[Config::Keys[Config::ActiveWorkspace]]);
return workspaceConfig;
}
BuildTargetDescriptorConfig ParseBuildTargetDescriptorConfig(const rapidjson::Value& buildTargetDescriptor)
{
BuildTargetDescriptorConfig buildTargetDescriptorConfig;
const auto& targetSources = buildTargetDescriptor[Config::Keys[Config::TargetSources]];
const auto& staticTargetSources = targetSources[Config::Keys[Config::StaticSources]];
const auto& autogenTargetSources = targetSources[Config::Keys[Config::AutogenSources]];
buildTargetDescriptorConfig.m_mappingDirectory = buildTargetDescriptor[Config::Keys[Config::Directory]].GetString();
const auto& staticInclusionFilters = staticTargetSources[Config::Keys[Config::SourceIncludeFilters]].GetArray();
buildTargetDescriptorConfig.m_staticInclusionFilters.reserve(staticInclusionFilters.Size());
for (const auto& staticInclusionFilter : staticInclusionFilters)
{
buildTargetDescriptorConfig.m_staticInclusionFilters.push_back(staticInclusionFilter.GetString());
}
buildTargetDescriptorConfig.m_inputOutputPairer = autogenTargetSources[Config::Keys[Config::AutogenInputOutputPairer]].GetString();
const auto& inputInclusionFilters =
autogenTargetSources[Config::Keys[Config::AutogenInputSources]][Config::Keys[Config::SourceIncludeFilters]].GetArray();
buildTargetDescriptorConfig.m_inputInclusionFilters.reserve(inputInclusionFilters.Size());
for (const auto& inputInclusionFilter : inputInclusionFilters)
{
buildTargetDescriptorConfig.m_inputInclusionFilters.push_back(inputInclusionFilter.GetString());
}
return buildTargetDescriptorConfig;
}
DependencyGraphDataConfig ParseDependencyGraphDataConfig(const rapidjson::Value& dependencyGraphData)
{
DependencyGraphDataConfig dependencyGraphDataConfig;
const auto& matchers = dependencyGraphData[Config::Keys[Config::DependencyGraphMatchers]];
dependencyGraphDataConfig.m_graphDirectory = dependencyGraphData[Config::Keys[Config::Directory]].GetString();
dependencyGraphDataConfig.m_targetDependencyFileMatcher = matchers[Config::Keys[Config::TargetDependencyFileMatcher]].GetString();
dependencyGraphDataConfig.m_targetVertexMatcher = matchers[Config::Keys[Config::TargetVertexMatcher]].GetString();
return dependencyGraphDataConfig;
}
TestTargetMetaConfig ParseTestTargetMetaConfig(const rapidjson::Value& testTargetMeta)
{
TestTargetMetaConfig testTargetMetaConfig;
testTargetMetaConfig.m_metaFile = testTargetMeta[Config::Keys[Config::TestTargetMetaFile]].GetString();
return testTargetMetaConfig;
}
TestEngineConfig ParseTestEngineConfig(const rapidjson::Value& testEngine)
{
TestEngineConfig testEngineConfig;
testEngineConfig.m_testRunner.m_binary = testEngine[Config::Keys[Config::TestRunner]][Config::Keys[Config::BinaryFile]].GetString();
testEngineConfig.m_instrumentation.m_binary = testEngine[Config::Keys[Config::TestInstrumentation]][Config::Keys[Config::BinaryFile]].GetString();
return testEngineConfig;
}
TargetConfig ParseTargetConfig(const rapidjson::Value& target)
{
TargetConfig targetConfig;
targetConfig.m_outputDirectory = target[Config::Keys[Config::Directory]].GetString();
const auto& testExcludes = target[Config::Keys[Config::TargetExcludeFilter]].GetArray();
targetConfig.m_excludedTestTargets.reserve(testExcludes.Size());
for (const auto& testExclude : testExcludes)
{
targetConfig.m_excludedTestTargets.push_back(testExclude.GetString());
}
const auto& testShards = target[Config::Keys[Config::TestSharding]].GetArray();
targetConfig.m_shardedTestTargets.reserve(testShards.Size());
for (const auto& testShard : testShards)
{
const auto getShardingConfiguration = [](const AZStd::string& config)
{
if (config == Config::Keys[Config::ContinuousFixtureSharding])
{
return ShardConfiguration::FixtureContiguous;
}
else if (config == Config::Keys[Config::InterleavedFixtureSharding])
{
return ShardConfiguration::FixtureInterleaved;
}
else if (config == Config::Keys[Config::ContinuousTestSharding])
{
return ShardConfiguration::TestContiguous;
}
else if (config == Config::Keys[Config::InterleavedTestSharding])
{
return ShardConfiguration::TestInterleaved;
}
else if (config == Config::Keys[Config::NeverShard])
{
return ShardConfiguration::Never;
}
else
{
throw ConfigurationException(AZStd::string::format("Unexpected sharding configuration: %s", config.c_str()));
}
};
TargetConfig::ShardedTarget shard;
shard.m_name = testShard[Config::Keys[Config::TargetName]].GetString();
shard.m_configuration = getShardingConfiguration(testShard[Config::Keys[Config::TestShardingPolicy]].GetString());
targetConfig.m_shardedTestTargets.push_back(AZStd::move(shard));
}
return targetConfig;
}
RuntimeConfig RuntimeConfigurationFactory(const AZStd::string& configurationData)
{
rapidjson::Document configurationFile;
if (configurationFile.Parse(configurationData.c_str()).HasParseError())
{
throw TestImpact::ConfigurationException("Could not parse runtimeConfig data, JSON has errors");
}
RuntimeConfig runtimeConfig;
const auto& staticArtifacts = configurationFile[Config::Keys[Config::Artifacts]][Config::Keys[Config::StaticArtifacts]];
runtimeConfig.m_meta = ParseConfigMeta(configurationFile[Config::Keys[Config::Meta]]);
runtimeConfig.m_repo = ParseRepoConfig(configurationFile[Config::Keys[Config::Repository]]);
runtimeConfig.m_workspace = ParseWorkspaceConfig(configurationFile[Config::Keys[Config::Workspace]]);
runtimeConfig.m_buildTargetDescriptor = ParseBuildTargetDescriptorConfig(staticArtifacts[Config::Keys[Config::BuildTargetDescriptor]]);
runtimeConfig.m_dependencyGraphData = ParseDependencyGraphDataConfig(staticArtifacts[Config::Keys[Config::DependencyGraphData]]);
runtimeConfig.m_testTargetMeta = ParseTestTargetMetaConfig(staticArtifacts[Config::Keys[Config::TestTargetMeta]]);
runtimeConfig.m_testEngine = ParseTestEngineConfig(configurationFile[Config::Keys[Config::TestEngine]]);
runtimeConfig.m_target = ParseTargetConfig(configurationFile[Config::Keys[Config::TargetConfig]]);
return runtimeConfig;
}
} // namespace TestImpact
@@ -0,0 +1,19 @@
/*
* 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/TestImpactConfiguration.h>
namespace TestImpact
{
//! Parses the configuration data (in JSON format) and returns the constructed runtime configuration.
RuntimeConfig RuntimeConfigurationFactory(const AZStd::string& configurationData);
} // namespace TestImpact
@@ -0,0 +1,42 @@
///*
// * 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/TestImpactClientTestSelection.h>
//#include <TestImpactFramework/TestImpactClientTestRun.h>
//
//#include <TestImpactConsoleTestSequenceEventHandler.h>
//
//#include <AzCore/std/containers/vector.h>
//#include <AzCore/std/smart_ptr/unique_ptr.h>
//#include <AzCore/UnitTest/TestTypes.h>
//#include <AzTest/AzTest.h>
//
//namespace UnitTest
//{
// class ConsoleTestSequenceTestFixture
// : public AllocatorsTestFixture
// {
// };
//
// TEST_F(ConsoleTestSequenceTestFixture, CheckEmptyArgs_ExpectDefaultValues)
// {
// AZStd::unordered_set<AZStd::string> suites = { "PERIODIC","MAIN" };
// TestImpact::Console::TestSequenceEventHandler seq(&suites);
// AZStd::vector<AZStd::string> selectedTests = { "Test1", "Test2", "Test3", "Test4", "Test5" };
// seq.operator()(TestImpact::Client::TestRunSelection(selectedTests, {"Test6"}));
//
// for (auto i = 0; i < selectedTests.size(); i++)
// {
// seq.operator()(TestImpact::Client::TestRun(selectedTests[i], (TestImpact::Client::TestRunResult)i, AZStd::chrono::milliseconds(i)));
// }
// }
//}
@@ -0,0 +1,34 @@
/*
* 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 <AzCore/Memory/OSAllocator.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzTest/AzTest.h>
class TestImpactTestEnvironment
: public AZ::Test::ITestEnvironment
{
protected:
void SetupEnvironment() override
{
AZ::AllocatorInstance<AZ::OSAllocator>::Create();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
}
void TeardownEnvironment() override
{
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
};
AZ_UNIT_TEST_HOOK(new TestImpactTestEnvironment);
@@ -0,0 +1,27 @@
/*
* 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 <TestImpactRuntimeConfigurationFactory.h>
#include <AzTest/AzTest.h>
#include <fstream>
namespace UnitTest
{
//TEST(FOO, BAR)
//{
// std::ifstream configFile("C:\\o3de_TIF_Feature\\windows_vs2019\\bin\\debug\\tiaf.debug.json");
// AZStd::string configData((std::istreambuf_iterator<char>(configFile)), std::istreambuf_iterator<char>());
// const auto configuration = TestImpact::ConfigurationFactory(configData);
//}
}
@@ -0,0 +1,14 @@
#
# 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.
#
set(FILES
Source/TestImpactConsole.cpp
)
@@ -0,0 +1,26 @@
#
# 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.
#
set(FILES
Include/TestImpactFramework/TestImpactConsoleMain.h
Source/TestImpactCommandLineOptions.h
Source/TestImpactCommandLineOptions.cpp
Source/TestImpactCommandLineOptionsUtils.cpp
Source/TestImpactCommandLineOptionsUtils.h
Source/TestImpactCommandLineOptionsException.h
Source/TestImpactRuntimeConfigurationFactory.h
Source/TestImpactRuntimeConfigurationFactory.cpp
Source/TestImpactConsoleMain.cpp
Source/TestImpactConsoleTestSequenceEventHandler.cpp
Source/TestImpactConsoleTestSequenceEventHandler.h
Source/TestImpactConsoleUtils.cpp
Source/TestImpactConsoleUtils.h
)
@@ -0,0 +1,18 @@
#
# 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.
#
set(FILES
Tests/TestImpactCommandLineOptionsTest.cpp
Tests/TestImpactRuntimeConfigurationFactoryTest.cpp
Tests/TestImpactFrontendConsoleStaticTestMain.cpp
Tests/TestImpactConsoleMainTest.cpp
Tests/TestImpactConsoleTestSequenceEventHandlerTest.cpp
)