From 597f0905c5250f8417dfe19aa5c56c9b526ba06d Mon Sep 17 00:00:00 2001 From: jonawals Date: Fri, 21 May 2021 20:13:10 +0100 Subject: [PATCH 1/2] Refactor ProcessScheduler with Execute method --- .../JobRunner/TestImpactProcessJobRunner.h | 78 +++++------- .../Scheduler/TestImpactProcessScheduler.cpp | 118 +++++++++++++----- .../Scheduler/TestImpactProcessScheduler.h | 56 ++++----- .../Enumeration/TestImpactTestEnumerator.cpp | 32 +++-- .../Enumeration/TestImpactTestEnumerator.h | 23 ++-- .../JobRunner/TestImpactTestJobRunner.h | 70 +++++------ .../Run/TestImpactInstrumentedTestRunner.cpp | 26 ++-- .../Run/TestImpactInstrumentedTestRunner.h | 25 ++-- .../TestEngine/Run/TestImpactTestCoverage.cpp | 2 +- .../TestEngine/Run/TestImpactTestCoverage.h | 4 +- .../TestEngine/Run/TestImpactTestRunner.cpp | 26 ++-- .../TestEngine/Run/TestImpactTestRunner.h | 21 ++-- 12 files changed, 272 insertions(+), 209 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h index 0c30accc84..384111b823 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h @@ -50,32 +50,29 @@ namespace TestImpact { public: //! Constructs the job runner with the specified parameters to constrain job runs. + //! @param maxConcurrentProcesses he maximum number of concurrent jobs in-flight. + JobRunner(size_t maxConcurrentProcesses); + + //! Executes the specified jobs and returns the products of their labor. + //! @param jobs The arguments (and other pertinent information) required for each job to be run. //! @param stdOutRouting The standard output routing to be specified for all jobs. //! @param stdErrRouting The standard error routing to be specified for all jobs. - //! @param maxConcurrentProcesses he maximum number of concurrent jobs in-flight. - //! @param processTimeout The maximum duration a job may be in-flight before being forcefully terminated (nullopt if no timeout). - //! @param scheduleTimeout The maximum duration the scheduler may run before forcefully terminating all in-flight jobs (nullopt if - //! no timeout). - JobRunner( + //! @param jobTimeout The maximum duration a job may be in-flight before being forcefully terminated (nullopt if no timeout). + //! @param runnerTimeout The maximum duration the scheduler may run before forcefully terminating all in-flight jobs (nullopt if no timeout). + //! @param payloadMapProducer The client callback to be called when all jobs have finished to transform the work produced by each job into the desired output. + //! @param jobCallback The client callback to be called when each job changes state. + //! @return The result of the run sequence and the jobs with their associated payloads. + AZStd::pair> Execute( + const AZStd::vector& jobs, + PayloadMapProducer payloadMapProducer, StdOutputRouting stdOutRouting, StdErrorRouting stdErrRouting, - size_t maxConcurrentProcesses, - AZStd::optional processTimeout, - AZStd::optional scheduleTimeout); - - //! Executes the specified jobs and returns the products of their labor. - //! @note: the job and payload callbacks are specified here rather than in the constructor to allow clients to use capturing lambdas - //! should they desire to. - //! @param jobs The arguments (and other pertinent information) required for each job to be run. - //! @param jobCallback The client callback to be called when each job changes state. - //! @param payloadMapProducer The client callback to be called when all jobs have finished to transform the work produced by each - //! job into the desired output. - AZStd::vector Execute( - const AZStd::vector& jobs, JobCallback jobCallback, - PayloadMapProducer payloadMapProducer); + AZStd::optional jobTimeout, + AZStd::optional runnerTimeout, + JobCallback jobCallback); private: - size_t m_maxConcurrentProcesses = 0; //!< Maximum number of concurrent jobs being executed at a given time. + ProcessScheduler m_processScheduler; StdOutputRouting m_stdOutRouting; //!< Standard output routing from each job process to job runner. StdErrorRouting m_stdErrRouting; //!< Standard error routing from each job process to job runner AZStd::optional m_jobTimeout; //!< Maximum time a job can run for before being forcefully terminated. @@ -83,25 +80,20 @@ namespace TestImpact }; template - JobRunner::JobRunner( - StdOutputRouting stdOutRouting, - StdErrorRouting stdErrRouting, - size_t maxConcurrentProcesses, - AZStd::optional jobTimeout, - AZStd::optional runnerTimeout) - : m_maxConcurrentProcesses(maxConcurrentProcesses) - , m_stdOutRouting(stdOutRouting) - , m_stdErrRouting(stdErrRouting) - , m_jobTimeout(jobTimeout) - , m_runnerTimeout(runnerTimeout) + JobRunner::JobRunner(size_t maxConcurrentProcesses) + : m_processScheduler(maxConcurrentProcesses) { } template - AZStd::vector JobRunner::Execute( + AZStd::pair> JobRunner::Execute( const AZStd::vector& jobInfos, - JobCallback jobCallback, - PayloadMapProducer payloadMapProducer) + PayloadMapProducer payloadMapProducer, + StdOutputRouting stdOutRouting, + StdErrorRouting stdErrRouting, + AZStd::optional jobTimeout, + AZStd::optional runnerTimeout, + JobCallback jobCallback) { AZStd::vector processes; AZStd::unordered_map> metas; @@ -115,11 +107,11 @@ namespace TestImpact const auto* jobInfo = &jobInfos[jobIndex]; const auto jobId = jobInfo->GetId().m_value; metas.emplace(jobId, AZStd::pair{JobMeta{}, jobInfo}); - processes.emplace_back(jobId, m_stdOutRouting, m_stdErrRouting, jobInfo->GetCommand().m_args); + processes.emplace_back(jobId, stdOutRouting, stdErrRouting, jobInfo->GetCommand().m_args); } // Wrapper around low-level process launch callback to gather job meta-data and present a simplified callback interface to the client - const auto processLaunchCallback = [&jobCallback, &jobInfos, &metas]( + const ProcessLaunchCallback processLaunchCallback = [&jobCallback, &jobInfos, &metas]( TestImpact::ProcessId pid, TestImpact::LaunchResult launchResult, AZStd::chrono::high_resolution_clock::time_point createTime) @@ -138,7 +130,7 @@ namespace TestImpact }; // Wrapper around low-level process exit callback to gather job meta-data and present a simplified callback interface to the client - const auto processExitCallback = [&jobCallback, &jobInfos, &metas]( + const ProcessExitCallback processExitCallback = [&jobCallback, &jobInfos, &metas]( TestImpact::ProcessId pid, TestImpact::ExitCondition exitCondition, TestImpact::ReturnCode returnCode, @@ -169,14 +161,12 @@ namespace TestImpact }; // Schedule all jobs for execution - ProcessScheduler scheduler( + const auto result = m_processScheduler.Execute( processes, + jobTimeout, + runnerTimeout, processLaunchCallback, - processExitCallback, - m_maxConcurrentProcesses, - m_jobTimeout, - m_runnerTimeout - ); + processExitCallback); // Hand off the jobs to the client for payload generation auto payloadMap = payloadMapProducer(metas); @@ -188,6 +178,6 @@ namespace TestImpact jobs.emplace_back(JobT(jobInfo, AZStd::move(metas.at(jobId).first), AZStd::move(payloadMap[jobId]))); } - return jobs; + return { result, jobs }; } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp index 04a68bf612..8d6c5c6739 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp @@ -18,7 +18,7 @@ namespace TestImpact { - struct ProcessScheduler::ProcessInFlight + struct ProcessInFlight { AZStd::unique_ptr m_process; AZStd::optional m_startTime; @@ -26,29 +26,64 @@ namespace TestImpact AZStd::string m_stdError; }; - ProcessScheduler::ProcessScheduler( - const AZStd::vector& processes, - const ProcessLaunchCallback& processLaunchCallback, - const ProcessExitCallback& processExitCallback, + class ProcessScheduler::ExecutionState + { + public: + ExecutionState( + size_t maxConcurrentProcesses, + AZStd::optional processTimeout, + AZStd::optional scheduleTimeout, + ProcessLaunchCallback& processLaunchCallback, + ProcessExitCallback& processExitCallback); + ~ExecutionState(); + + ProcessSchedulerResult MonitorProcesses(const AZStd::vector& processes); + void TerminateAllProcesses(ExitCondition exitStatus); + private: + ProcessCallbackResult PopAndLaunch(ProcessInFlight& processInFlight); + StdContent ConsumeProcessStdContent(ProcessInFlight& processInFlight); + void AccumulateProcessStdContent(ProcessInFlight& processInFlight); + + size_t m_maxConcurrentProcesses = 0; + ProcessLaunchCallback m_processLaunchCallback; + ProcessExitCallback m_processExitCallback; + AZStd::optional m_processTimeout; + AZStd::optional m_scheduleTimeout; + AZStd::chrono::high_resolution_clock::time_point m_startTime; + AZStd::vector m_processPool; + AZStd::queue m_processQueue; + }; + + ProcessScheduler::ExecutionState::ExecutionState( size_t maxConcurrentProcesses, AZStd::optional processTimeout, - AZStd::optional scheduleTimeout) - : m_processCreateCallback(processLaunchCallback) + AZStd::optional scheduleTimeout, + ProcessLaunchCallback& processLaunchCallback, + ProcessExitCallback& processExitCallback) + : m_maxConcurrentProcesses(maxConcurrentProcesses) + , m_processLaunchCallback(processLaunchCallback) , m_processExitCallback(processExitCallback) , m_processTimeout(processTimeout) , m_scheduleTimeout(scheduleTimeout) - , m_startTime(AZStd::chrono::high_resolution_clock::now()) { - AZ_TestImpact_Eval(maxConcurrentProcesses != 0, ProcessException, "Max Number of concurrent processes in flight cannot be 0"); - AZ_TestImpact_Eval(!processes.empty(), ProcessException, "Number of processes to launch cannot be 0"); AZ_TestImpact_Eval( !m_processTimeout.has_value() || m_processTimeout->count() > 0, ProcessException, "Process timeout must be empty or non-zero value"); AZ_TestImpact_Eval( !m_scheduleTimeout.has_value() || m_scheduleTimeout->count() > 0, ProcessException, "Scheduler timeout must be empty or non-zero value"); + } - const size_t numConcurrentProcesses = AZStd::min(processes.size(), maxConcurrentProcesses); + ProcessScheduler::ExecutionState::~ExecutionState() + { + TerminateAllProcesses(ExitCondition::Terminated); + } + + ProcessSchedulerResult ProcessScheduler::ExecutionState::MonitorProcesses(const AZStd::vector& processes) + { + AZ_TestImpact_Eval(!processes.empty(), ProcessException, "Number of processes to launch cannot be 0"); + m_startTime = AZStd::chrono::high_resolution_clock::now(); + const size_t numConcurrentProcesses = AZStd::min(processes.size(), m_maxConcurrentProcesses); m_processPool.resize(numConcurrentProcesses); for (const auto& process : processes) @@ -61,20 +96,10 @@ namespace TestImpact if (PopAndLaunch(process) == ProcessCallbackResult::Abort) { TerminateAllProcesses(ExitCondition::Terminated); - return; + return ProcessSchedulerResult::Graceful; } } - MonitorProcesses(); - } - - ProcessScheduler::~ProcessScheduler() - { - TerminateAllProcesses(ExitCondition::Terminated); - } - - void ProcessScheduler::MonitorProcesses() - { while (true) { // Check to see whether or not the scheduling has exceeded its specified runtime @@ -86,7 +111,7 @@ namespace TestImpact { // Runtime exceeded, terminate all proccesses and schedule no further TerminateAllProcesses(ExitCondition::Timeout); - return; + return ProcessSchedulerResult::Timeout; } } @@ -98,7 +123,7 @@ namespace TestImpact { if (processInFlight.m_process) { - // Process is alive (note: not necessarilly currently running) + // Process is alive (note: not necessarily currently running) AccumulateProcessStdContent(processInFlight); const ProcessId processId = processInFlight.m_process->GetProcessInfo().GetId(); @@ -119,7 +144,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return; + return ProcessSchedulerResult::Graceful; } else if (!m_processQueue.empty()) { @@ -128,7 +153,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return; + return ProcessSchedulerResult::Graceful; } else { @@ -157,9 +182,9 @@ namespace TestImpact ConsumeProcessStdContent(processInFlight), exitTime)) { - // Flight time exceeded, terminate this process + // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return; + return ProcessSchedulerResult::Graceful; } } @@ -176,7 +201,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return; + return ProcessSchedulerResult::Graceful; } else { @@ -192,9 +217,11 @@ namespace TestImpact break; } } + + return ProcessSchedulerResult::Graceful; } - ProcessCallbackResult ProcessScheduler::PopAndLaunch(ProcessInFlight& processInFlight) + ProcessCallbackResult ProcessScheduler::ExecutionState::PopAndLaunch(ProcessInFlight& processInFlight) { auto processInfo = m_processQueue.front(); m_processQueue.pop(); @@ -212,17 +239,17 @@ namespace TestImpact createResult = LaunchResult::Failure; } - return m_processCreateCallback(processInfo.GetId(), createResult, createTime); + return m_processLaunchCallback(processInfo.GetId(), createResult, createTime); } - void ProcessScheduler::AccumulateProcessStdContent(ProcessInFlight& processInFlight) + void ProcessScheduler::ExecutionState::AccumulateProcessStdContent(ProcessInFlight& processInFlight) { // Accumulate the stdout/stderr so we don't deadlock with the process waiting for the pipe to empty before finishing processInFlight.m_stdOutput += processInFlight.m_process->ConsumeStdOut().value_or(""); processInFlight.m_stdError += processInFlight.m_process->ConsumeStdErr().value_or(""); } - StdContent ProcessScheduler::ConsumeProcessStdContent(ProcessInFlight& processInFlight) + StdContent ProcessScheduler::ExecutionState::ConsumeProcessStdContent(ProcessInFlight& processInFlight) { return { @@ -235,7 +262,7 @@ namespace TestImpact }; } - void ProcessScheduler::TerminateAllProcesses(ExitCondition exitStatus) + void ProcessScheduler::ExecutionState::TerminateAllProcesses(ExitCondition exitStatus) { bool isCallingBackToClient = true; const ReturnCode returnCode = static_cast(exitStatus); @@ -267,4 +294,27 @@ namespace TestImpact } } } + + ProcessScheduler::ProcessScheduler(size_t maxConcurrentProcesses) + : m_maxConcurrentProcesses(maxConcurrentProcesses) + { + AZ_TestImpact_Eval(maxConcurrentProcesses != 0, ProcessException, "Max Number of concurrent processes in flight cannot be 0"); + } + + ProcessScheduler::~ProcessScheduler() = default; + + ProcessSchedulerResult ProcessScheduler::Execute( + const AZStd::vector& processes, + AZStd::optional processTimeout, + AZStd::optional scheduleTimeout, + ProcessLaunchCallback processLaunchCallback, + ProcessExitCallback processExitCallback) + { + AZ_TestImpact_Eval(!m_executionState, ProcessException, "Couldn't execute schedule, schedule already in progress"); + m_executionState = AZStd::make_unique( + m_maxConcurrentProcesses, processTimeout, scheduleTimeout, processLaunchCallback, processExitCallback); + const auto result = m_executionState->MonitorProcesses(processes); + m_executionState.reset(); + return result; + } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h index 27171d25ee..7f562fb99e 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace TestImpact { @@ -49,6 +50,13 @@ namespace TestImpact Abort //!< Abort scheduling immediately. }; + //! Result of the process scheduling sequence. + enum class ProcessSchedulerResult : bool + { + Graceful, //!< The scheduler completed its run without incident or was terminated gracefully in response to a client callback result. + Timeout //!< The scheduler aborted its run prematurely due to its runtime exceeding the scheduler timeout value. + }; + //! Callback for process launch attempt. //! @param processId The id of the process that attempted to launch. //! @param launchResult The result of the process launch attempt. @@ -79,38 +87,28 @@ namespace TestImpact { public: //! Constructs the scheduler with the specified batch of processes. - //! @param processes The batch of processes to schedule. - //! @param processLaunchCallback The process launch callback function. - //! @param processExitCallback The process exit callback function. //! @param maxConcurrentProcesses The maximum number of concurrent processes in-flight. - //! @param processTimeout The maximum duration a process may be in-flight for before being forcefully terminated. - //! @param scheduleTimeout The maximum duration the scheduler may run before forcefully terminating all in-flight processes. - //! processes and abandoning any queued processes. - ProcessScheduler( - const AZStd::vector& processes, - const ProcessLaunchCallback& processLaunchCallback, - const ProcessExitCallback& processExitCallback, - size_t maxConcurrentProcesses, - AZStd::optional processTimeout, - AZStd::optional scheduleTimeout); - + ProcessScheduler(size_t maxConcurrentProcesses); ~ProcessScheduler(); + //! Executes the specified processes and calls the client callbacks (if any) as each process progresses in its life cycle. + //! @note Multiple subsequent calls to Execute are permitted. + //! @param processes The batch of processes to schedule. + //! @param processTimeout The maximum duration a process may be in-flight for before being forcefully terminated. + //! @param scheduleTimeout The maximum duration the scheduler may run before forcefully terminating all in-flight processes. + //! @param processLaunchCallback The process launch callback function. + //! @param processExitCallback The process exit callback function. + //! @returns The state that triggered the end of the schedule sequence. + ProcessSchedulerResult Execute( + const AZStd::vector& processes, + AZStd::optional processTimeout, + AZStd::optional scheduleTimeout, + ProcessLaunchCallback processLaunchCallback, + ProcessExitCallback processExitCallback); + private: - struct ProcessInFlight; - - void MonitorProcesses(); - ProcessCallbackResult PopAndLaunch(ProcessInFlight& processInFlight); - void TerminateAllProcesses(ExitCondition exitStatus); - StdContent ConsumeProcessStdContent(ProcessInFlight& processInFlight); - void AccumulateProcessStdContent(ProcessInFlight& processInFlight); - - const ProcessLaunchCallback m_processCreateCallback; - const ProcessExitCallback m_processExitCallback; - const AZStd::optional m_processTimeout; - const AZStd::optional m_scheduleTimeout; - const AZStd::chrono::high_resolution_clock::time_point m_startTime; - AZStd::vector m_processPool; - AZStd::queue m_processQueue; + class ExecutionState; + AZStd::unique_ptr m_executionState; + size_t m_maxConcurrentProcesses = 0; }; } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp index 882c65c516..09cea87d41 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp @@ -106,19 +106,18 @@ namespace TestImpact return m_cache; } - TestEnumerator::TestEnumerator( - AZStd::optional clientCallback, - size_t maxConcurrentEnumerations, - AZStd::optional enumerationTimeout, - AZStd::optional enumeratorTimeout) - : JobRunner(clientCallback, AZStd::nullopt, StdOutputRouting::None, StdErrorRouting::None, maxConcurrentEnumerations, enumerationTimeout, enumeratorTimeout) + TestEnumerator::TestEnumerator(size_t maxConcurrentEnumerations) + : JobRunner(maxConcurrentEnumerations) { } - - AZStd::vector TestEnumerator::Enumerate( + + AZStd::pair> TestEnumerator::Enumerate( const AZStd::vector& jobInfos, CacheExceptionPolicy cacheExceptionPolicy, - JobExceptionPolicy jobExceptionPolicy) + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional enumerationTimeout, + AZStd::optional enumeratorTimeout, + AZStd::optional clientCallback) { AZStd::vector cachedJobs; AZStd::vector jobQueue; @@ -179,14 +178,23 @@ namespace TestImpact }; // Generate the enumeration results for the jobs that weren't cached - auto jobs = ExecuteJobs(jobQueue, payloadGenerator, jobExceptionPolicy); - + auto [result, jobs] = ExecuteJobs( + jobQueue, + jobExceptionPolicy, + payloadGenerator, + StdOutputRouting::None, + StdErrorRouting::None, + enumerationTimeout, + enumeratorTimeout, + clientCallback, + AZStd::nullopt); + // We need to add the cached jobs to the completed job list even though they technically weren't executed for (auto&& job : cachedJobs) { jobs.emplace_back(AZStd::move(job)); } - return jobs; + return { result, jobs }; } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h index 63d0b82d3e..287dd9e2d9 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h @@ -73,22 +73,23 @@ namespace TestImpact using CacheExceptionPolicy = Bitwise::CacheExceptionPolicy; //! Constructs a test enumerator with the specified parameters common to all enumeration job runs of this enumerator. - //! @param clientCallback The optional client callback to be called whenever an enumeration job changes state. //! @param maxConcurrentEnumerations The maximum number of enumerations to be in flight at any given time. - //! @param enumerationTimeout The maximum duration an enumeration may be in-flight for before being forcefully terminated. - //! @param enumeratorTimeout The maximum duration the enumerator may run before forcefully terminating all in-flight enumerations. - TestEnumerator( - AZStd::optional clientCallback, - size_t maxConcurrentEnumerations, - AZStd::optional enumerationTimeout, - AZStd::optional enumeratorTimeout); + TestEnumerator(size_t maxConcurrentEnumerations); //! Executes the specified test enumeration jobs according to the specified cache and job exception policies. //! @param jobInfos The enumeration jobs to execute. //! @param cacheExceptionPolicy The cache exception policy to be used for this run. //! @param jobExceptionPolicy The enumeration job exception policy to be used for this run. - //! @return the test enumeration jobs with their associated test enumeration payloads. - AZStd::vector Enumerate( - const AZStd::vector& jobInfos, CacheExceptionPolicy cacheExceptionPolicy, JobExceptionPolicy jobExceptionPolicy); + //! @param enumerationTimeout The maximum duration an enumeration may be in-flight for before being forcefully terminated. + //! @param enumeratorTimeout The maximum duration the enumerator may run before forcefully terminating all in-flight enumerations. + //! @param clientCallback The optional client callback to be called whenever an enumeration job changes state. + //! @return The result of the run sequence and the enumeration jobs with their associated test enumeration payloads. + AZStd::pair> Enumerate( + const AZStd::vector& jobInfos, + CacheExceptionPolicy cacheExceptionPolicy, + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional enumerationTimeout, + AZStd::optional enumeratorTimeout, + AZStd::optional clientCallback); }; } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h index c60a93e21d..91f4d4e39c 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h @@ -53,32 +53,31 @@ namespace TestImpact using JobDataMap = JobDataMap; //! Constructs the job runner with the specified parameters common to all job runs of this runner. - //! @param clientCallback The optional callback function provided by the client to be called upon job state change. - //! @param clientCallback The optional callback function provided by the derived job runner to be called upon job state change. - //! @param stdOutRouting The standard output routing from the underlying job processes to the derived runner. - //! @param stdErrorRouting The standard error routing from the underlying job processes to the derived runner. //! @param maxConcurrentJobs The maximum number of jobs to be in flight at any given time. - //! @param jobTimeout The maximum duration a job may be in-flight for before being forcefully terminated (nullopt if no timeout). - //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight jobs (nullopt if no - //! timeout). - TestJobRunner( - AZStd::optional clientCallback, - AZStd::optional derivedJobCallback, - StdOutputRouting stdOutRouting, - StdErrorRouting stdErrRouting, - size_t maxConcurrentJobs, - AZStd::optional jobTimeout, - AZStd::optional runnerTimeout); + TestJobRunner(size_t maxConcurrentJobs); protected: //! Runs the specified jobs and returns the completed payloads produced by each job. //! @param jobInfos The batch of jobs to execute. - //! @param payloadMapProducer The client callback for producing the payload map based on the completed job data. //! @param jobExceptionPolicy The job execution policy for this job run. - AZStd::vector ExecuteJobs( + //! @param payloadMapProducer The client callback for producing the payload map based on the completed job data. + //! @param stdOutRouting The standard output routing from the underlying job processes to the derived runner. + //! @param stdErrorRouting The standard error routing from the underlying job processes to the derived runner. + //! @param jobTimeout The maximum duration a job may be in-flight for before being forcefully terminated (nullopt if no timeout). + //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight jobs (nullopt if no timeout). + //! @param clientCallback The optional callback function provided by the client to be called upon job state change. + //! @param clientCallback The optional callback function provided by the derived job runner to be called upon job state change. + //! @returns The result of the run sequence and the jobs that the sequence produced. + AZStd::pair> ExecuteJobs( const AZStd::vector& jobInfos, + JobExceptionPolicy jobExceptionPolicy, PayloadMapProducer payloadMapProducer, - JobExceptionPolicy jobExceptionPolicy); + StdOutputRouting stdOutRouting, + StdErrorRouting stdErrRouting, + AZStd::optional jobTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback, + AZStd::optional derivedJobCallback); const AZStd::optional m_clientJobCallback; @@ -88,28 +87,25 @@ namespace TestImpact }; template - TestJobRunner::TestJobRunner( - AZStd::optional clientCallback, - AZStd::optional derivedJobCallback, - StdOutputRouting stdOutRouting, - StdErrorRouting stdErrRouting, - size_t maxConcurrentJobs, - AZStd::optional jobTimeout, - AZStd::optional runnerTimeout) - : m_jobRunner(stdOutRouting, stdErrRouting, maxConcurrentJobs, jobTimeout, runnerTimeout) - , m_clientJobCallback(clientCallback) - , m_derivedJobCallback(derivedJobCallback) + TestJobRunner::TestJobRunner(size_t maxConcurrentJobs) + : m_jobRunner(maxConcurrentJobs) { } template - AZStd::vector::Job> TestJobRunner::ExecuteJobs( + AZStd::pair::Job>> TestJobRunner::ExecuteJobs( const AZStd::vector& jobInfos, + JobExceptionPolicy jobExceptionPolicy, PayloadMapProducer payloadMapProducer, - JobExceptionPolicy jobExceptionPolicy) + StdOutputRouting stdOutRouting, + StdErrorRouting stdErrRouting, + AZStd::optional jobTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback, + AZStd::optional derivedJobCallback) { // Callback to handle job exception policies and client/derived callbacks - const auto jobCallback = [this, &jobExceptionPolicy](const JobInfo& jobInfo, const JobMeta& meta, StdContent&& std) + const auto jobCallback = [&clientCallback, &derivedJobCallback, &jobExceptionPolicy](const JobInfo& jobInfo, const JobMeta& meta, StdContent&& std) { auto callbackResult = ProcessCallbackResult::Continue; if (meta.m_result == JobResult::FailedToExecute && IsFlagSet(jobExceptionPolicy, JobExceptionPolicy::OnFailedToExecute)) @@ -121,23 +117,23 @@ namespace TestImpact callbackResult = ProcessCallbackResult::Abort; } - if (m_derivedJobCallback.has_value()) + if (derivedJobCallback.has_value()) { - if (const auto result = (*m_derivedJobCallback)(jobInfo, meta, AZStd::move(std)); + if (const auto result = (*derivedJobCallback)(jobInfo, meta, AZStd::move(std)); result == ProcessCallbackResult::Abort) { callbackResult = ProcessCallbackResult::Abort; } } - if (m_clientJobCallback.has_value()) + if (clientCallback.has_value()) { - (*m_clientJobCallback)(jobInfo, meta); + (*clientCallback)(jobInfo, meta); } return callbackResult; }; - return m_jobRunner.Execute(jobInfos, jobCallback, payloadMapProducer); + return m_jobRunner.Execute(jobInfos, payloadMapProducer, stdOutRouting, stdErrRouting, jobTimeout, runnerTimeout, jobCallback); } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp index 0d27d56af1..c0373e89f5 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp @@ -52,19 +52,18 @@ namespace TestImpact return {AZStd::move(run), AZStd::move(coverage)}; } - InstrumentedTestRunner::InstrumentedTestRunner( - AZStd::optional clientCallback, - size_t maxConcurrentRuns, - AZStd::optional runTimeout, - AZStd::optional runnerTimeout) - : JobRunner(clientCallback, AZStd::nullopt, StdOutputRouting::None, StdErrorRouting::None, maxConcurrentRuns, runTimeout, runnerTimeout) + InstrumentedTestRunner::InstrumentedTestRunner(size_t maxConcurrentRuns) + : JobRunner(maxConcurrentRuns) { } - AZStd::vector InstrumentedTestRunner::RunInstrumentedTests( + AZStd::pair> InstrumentedTestRunner::RunInstrumentedTests( const AZStd::vector& jobInfos, CoverageExceptionPolicy coverageExceptionPolicy, - JobExceptionPolicy jobExceptionPolicy) + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional runTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback) { const auto payloadGenerator = [this, coverageExceptionPolicy](const JobDataMap& jobDataMap) { @@ -98,6 +97,15 @@ namespace TestImpact return runs; }; - return ExecuteJobs(jobInfos, payloadGenerator, jobExceptionPolicy); + return ExecuteJobs( + jobInfos, + jobExceptionPolicy, + payloadGenerator, + StdOutputRouting::None, + StdErrorRouting::None, + runTimeout, + runnerTimeout, + clientCallback, + AZStd::nullopt); } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h index 3b47f53128..5545843e35 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h @@ -53,21 +53,24 @@ namespace TestImpact using CoverageExceptionPolicy = Bitwise::CoverageExceptionPolicy; //! Constructs an instrumented test runner with the specified parameters common to all job runs of this runner. - //! @param clientCallback The optional client callback to be called whenever a run job changes state. - //! @param maxConcurrentRuns The maximum number of runs to be in flight at any given time. - //! @param runTimeout The maximum duration a run may be in-flight for before being forcefully terminated. - //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight runs. - InstrumentedTestRunner( - AZStd::optional clientCallback, size_t maxConcurrentRuns, - AZStd::optional runTimeout, AZStd::optional runnerTimeout); - + //! @param maxConcurrentRuns The maximum number of runs to be in flight at any given time. + InstrumentedTestRunner(size_t maxConcurrentRuns); + //! Executes the specified instrumented test run jobs according to the specified job exception policies. //! @param jobInfos The test run jobs to execute. //! @param CoverageExceptionPolicy The coverage exception policy to be used for this run. //! @param jobExceptionPolicy The test run job exception policy to be used for this run (use //! TestJobExceptionPolicy::OnFailedToExecute to throw on test failures). - //! @return the instrumented test run jobs with their associated test run and test coverage payloads. - AZStd::vector RunInstrumentedTests( - const AZStd::vector& jobInfos, CoverageExceptionPolicy coverageExceptionPolicy, JobExceptionPolicy jobExceptionPolicy); + //! @param runTimeout The maximum duration a run may be in-flight for before being forcefully terminated. + //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight runs. + //! @param clientCallback The optional client callback to be called whenever a run job changes state. + //! @return The result of the run sequence and the instrumented run jobs with their associated test run and coverage payloads. + AZStd::pair> RunInstrumentedTests( + const AZStd::vector& jobInfos, + CoverageExceptionPolicy coverageExceptionPolicy, + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional runTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback); }; } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.cpp index 453b1fa962..4e82857cb2 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.cpp @@ -103,7 +103,7 @@ namespace TestImpact return m_modules.size(); } - const AZStd::vector& TestCoverage::GetSourcesCovered() const + const AZStd::vector& TestCoverage::GetSourcesCovered() const { return m_sourcesCovered; } diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.h index e7599fb145..8de5fbb6c7 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestCoverage.h @@ -44,7 +44,7 @@ namespace TestImpact size_t GetNumModulesCovered() const; //! Returns the sorted set of unique sources covered (empty if no coverage). - const AZStd::vector& GetSourcesCovered() const; + const AZStd::vector& GetSourcesCovered() const; //! Returns the modules covered (empty if no coverage). const AZStd::vector& GetModuleCoverages() const; @@ -56,7 +56,7 @@ namespace TestImpact void CalculateTestMetrics(); AZStd::vector m_modules; - AZStd::vector m_sourcesCovered; + AZStd::vector m_sourcesCovered; AZStd::optional m_coverageLevel; }; } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp index ebb846f406..27780a5f95 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp @@ -26,18 +26,17 @@ namespace TestImpact return TestRun(GTest::TestRunSuitesFactory(ReadFileContents(runFile)), duration); } - TestRunner::TestRunner( - AZStd::optional clientCallback, - size_t maxConcurrentRuns, - AZStd::optional runTimeout, - AZStd::optional runnerTimeout) - : JobRunner(clientCallback, AZStd::nullopt, StdOutputRouting::None, StdErrorRouting::None, maxConcurrentRuns, runTimeout, runnerTimeout) + TestRunner::TestRunner(size_t maxConcurrentRuns) + : JobRunner(maxConcurrentRuns) { } - AZStd::vector TestRunner::RunTests( + AZStd::pair> TestRunner::RunTests( const AZStd::vector& jobInfos, - JobExceptionPolicy jobExceptionPolicy) + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional runTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback) { const auto payloadGenerator = [this](const JobDataMap& jobDataMap) { @@ -62,6 +61,15 @@ namespace TestImpact return runs; }; - return ExecuteJobs(jobInfos, payloadGenerator, jobExceptionPolicy); + return ExecuteJobs( + jobInfos, + jobExceptionPolicy, + payloadGenerator, + StdOutputRouting::None, + StdErrorRouting::None, + runTimeout, + runnerTimeout, + clientCallback, + AZStd::nullopt); } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h index 379c6b424e..597ce2d2f8 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h @@ -26,21 +26,22 @@ namespace TestImpact public: //! Constructs a test runner with the specified parameters common to all job runs of this runner. - //! @param clientCallback The optional client callback to be called whenever a run job changes state. //! @param maxConcurrentRuns The maximum number of runs to be in flight at any given time. - //! @param runTimeout The maximum duration a run may be in-flight for before being forcefully terminated. - //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight runs. - TestRunner( - AZStd::optional clientCallback, - size_t maxConcurrentRuns, - AZStd::optional runTimeout, - AZStd::optional runnerTimeout); + TestRunner(size_t maxConcurrentRuns); //! Executes the specified test run jobs according to the specified job exception policies. //! @param jobInfos The test run jobs to execute. //! @param jobExceptionPolicy The test run job exception policy to be used for this run (use //! TestJobExceptionPolicy::OnFailedToExecute to throw on test failures). - //! @return the test run jobs with their associated test run payloads. - AZStd::vector RunTests(const AZStd::vector& jobInfos, JobExceptionPolicy jobExceptionPolicy); + //! @param runTimeout The maximum duration a run may be in-flight for before being forcefully terminated. + //! @param runnerTimeout The maximum duration the runner may run before forcefully terminating all in-flight runs. + //! @param clientCallback The optional client callback to be called whenever a run job changes state. + //! @return The result of the run sequence and the run jobs with their associated test run payloads. + AZStd::pair> RunTests( + const AZStd::vector& jobInfos, + JobExceptionPolicy jobExceptionPolicy, + AZStd::optional runTimeout, + AZStd::optional runnerTimeout, + AZStd::optional clientCallback); }; } // namespace TestImpact From 787b44db49396487ef295b83d4664d50bcd11f96 Mon Sep 17 00:00:00 2001 From: jonawals Date: Mon, 24 May 2021 14:15:32 +0100 Subject: [PATCH 2/2] Address PR comments --- .../Process/JobRunner/TestImpactProcessJobRunner.h | 2 +- .../Process/Scheduler/TestImpactProcessScheduler.cpp | 11 ++++++----- .../Process/Scheduler/TestImpactProcessScheduler.h | 5 +++-- .../TestEngine/Enumeration/TestImpactTestEnumerator.h | 2 +- .../TestEngine/JobRunner/TestImpactTestJobRunner.h | 2 +- .../TestEngine/Run/TestImpactInstrumentedTestRunner.h | 2 +- .../Code/Source/TestEngine/Run/TestImpactTestRunner.h | 2 +- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h index 384111b823..7d726cecc1 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/JobRunner/TestImpactProcessJobRunner.h @@ -51,7 +51,7 @@ namespace TestImpact public: //! Constructs the job runner with the specified parameters to constrain job runs. //! @param maxConcurrentProcesses he maximum number of concurrent jobs in-flight. - JobRunner(size_t maxConcurrentProcesses); + explicit JobRunner(size_t maxConcurrentProcesses); //! Executes the specified jobs and returns the products of their labor. //! @param jobs The arguments (and other pertinent information) required for each job to be run. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp index 8d6c5c6739..065caf54bd 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp @@ -95,8 +95,9 @@ namespace TestImpact { if (PopAndLaunch(process) == ProcessCallbackResult::Abort) { + // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return ProcessSchedulerResult::Graceful; + return ProcessSchedulerResult::UserAborted; } } @@ -144,7 +145,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return ProcessSchedulerResult::Graceful; + return ProcessSchedulerResult::UserAborted; } else if (!m_processQueue.empty()) { @@ -153,7 +154,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return ProcessSchedulerResult::Graceful; + return ProcessSchedulerResult::UserAborted; } else { @@ -184,7 +185,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return ProcessSchedulerResult::Graceful; + return ProcessSchedulerResult::UserAborted; } } @@ -201,7 +202,7 @@ namespace TestImpact { // Client chose to abort the scheduler TerminateAllProcesses(ExitCondition::Terminated); - return ProcessSchedulerResult::Graceful; + return ProcessSchedulerResult::UserAborted; } else { diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h index 7f562fb99e..769bf59ff8 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.h @@ -51,9 +51,10 @@ namespace TestImpact }; //! Result of the process scheduling sequence. - enum class ProcessSchedulerResult : bool + enum class ProcessSchedulerResult : AZ::u8 { Graceful, //!< The scheduler completed its run without incident or was terminated gracefully in response to a client callback result. + UserAborted, //!< The scheduler aborted prematurely due to the user returning an abort value from thier callback handler. Timeout //!< The scheduler aborted its run prematurely due to its runtime exceeding the scheduler timeout value. }; @@ -88,7 +89,7 @@ namespace TestImpact public: //! Constructs the scheduler with the specified batch of processes. //! @param maxConcurrentProcesses The maximum number of concurrent processes in-flight. - ProcessScheduler(size_t maxConcurrentProcesses); + explicit ProcessScheduler(size_t maxConcurrentProcesses); ~ProcessScheduler(); //! Executes the specified processes and calls the client callbacks (if any) as each process progresses in its life cycle. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h index 287dd9e2d9..fedaf300f7 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.h @@ -74,7 +74,7 @@ namespace TestImpact //! Constructs a test enumerator with the specified parameters common to all enumeration job runs of this enumerator. //! @param maxConcurrentEnumerations The maximum number of enumerations to be in flight at any given time. - TestEnumerator(size_t maxConcurrentEnumerations); + explicit TestEnumerator(size_t maxConcurrentEnumerations); //! Executes the specified test enumeration jobs according to the specified cache and job exception policies. //! @param jobInfos The enumeration jobs to execute. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h index 91f4d4e39c..3078114ef4 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/JobRunner/TestImpactTestJobRunner.h @@ -54,7 +54,7 @@ namespace TestImpact //! Constructs the job runner with the specified parameters common to all job runs of this runner. //! @param maxConcurrentJobs The maximum number of jobs to be in flight at any given time. - TestJobRunner(size_t maxConcurrentJobs); + explicit TestJobRunner(size_t maxConcurrentJobs); protected: //! Runs the specified jobs and returns the completed payloads produced by each job. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h index 5545843e35..42b718b241 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.h @@ -54,7 +54,7 @@ namespace TestImpact //! Constructs an instrumented test runner with the specified parameters common to all job runs of this runner. //! @param maxConcurrentRuns The maximum number of runs to be in flight at any given time. - InstrumentedTestRunner(size_t maxConcurrentRuns); + explicit InstrumentedTestRunner(size_t maxConcurrentRuns); //! Executes the specified instrumented test run jobs according to the specified job exception policies. //! @param jobInfos The test run jobs to execute. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h index 597ce2d2f8..1fdbc16d58 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.h @@ -27,7 +27,7 @@ namespace TestImpact public: //! Constructs a test runner with the specified parameters common to all job runs of this runner. //! @param maxConcurrentRuns The maximum number of runs to be in flight at any given time. - TestRunner(size_t maxConcurrentRuns); + explicit TestRunner(size_t maxConcurrentRuns); //! Executes the specified test run jobs according to the specified job exception policies. //! @param jobInfos The test run jobs to execute.