You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3383163 on 2017/04/06 by james.fox Enabling Overlap automation tests. Change 3387240 on 2017/04/10 by James.Fox Enabling ProcMesh automation tests. Made minor changes to in-level object names. Change 3397994 on 2017/04/18 by Nick.Darnell Automation - Adding some areas for future extension to allow transmission of data, and performance information between controller and client. The next step is to expose a way in blueprints, or via C++ to hook these events and send these messages. Change 3401903 on 2017/04/20 by samuel.proctor Test map for blueprint bitwise operators Change 3405592 on 2017/04/24 by Benjamin.Hyder Updated Roughness only example to be more visible in Decals test map Change 3405625 on 2017/04/24 by Benjamin.Hyder Re-Saving material in decals map to remove log spam Change 3406256 on 2017/04/24 by Mason.Seay Show Collision tests, with Ground Truth Screenshots Change 3410179 on 2017/04/26 by mason.seay Beginning of Math test map Change 3412646 on 2017/04/27 by mason.seay More math tests Change 3413556 on 2017/04/28 by Adric.Worley Add support for expected errors in automation tests Automation tests can now define expected errors/warnings that will not prevent the test from succeeding. If expected messages are not encountered, the test will fail. The intent is to allow unit tests to verify negative or error cases while keeping the test pass report green. It is not intended as an error suppression system. #tests new automation tests Change 3414217 on 2017/04/28 by mason.seay Wake Event functional test map Disabled Collision tests that still need review. Change 3414605 on 2017/04/28 by mason.seay Added more tests to Math map Change 3415806 on 2017/05/01 by Adric.Worley Suspend log parsing during tests with expected errors Electric Commander was failing successful test passes that have expected errors because of its log parsing. BenM added markers to temporarily disable error parsing in CL 3414237, which this implements usage of. #tests preflight Change 3416022 on 2017/05/01 by Mason.Seay Physics/ChildTransform tests Change 3420820 on 2017/05/03 by Nick.Darnell Automation - Allowing users to control the delay from the quick getter functions for Default Game/Rendering settings for screenshots. Avoids needing to add more delay nodes to your graph. Improving the Box Drop example to use the new delay options. The FunctionalTest actor now ticks even when the game is paused. Change 3422013 on 2017/05/03 by Nick.Darnell Automation - Adding an initial version of a ground truth storge mechanism that will only run in the editor. Users can use special runs of their tests to store the ground truth, then rewire things to then in the future read that ground truth. Added an example map showing the usage. Change 3422802 on 2017/05/04 by Nick.Darnell Automation - Fixing a crash in the curve asset actions that assumes there will always be import data. Change 3422803 on 2017/05/04 by Nick.Darnell Automation - Adding some comments to the ground truth function. Change 3423739 on 2017/05/04 by Nick.Darnell Automation - Introducing a way for people to provide Ground Truth for their tests. Change 3423768 on 2017/05/04 by Nick.Darnell Automation - GTD can no longer be modified on the build machine. Unchecking modifiable on the example GTD. Change 3425226 on 2017/05/05 by Nick.Darnell Automation - Fixing the FinishLoading code to only force shader compilation on platforms that don't require cooking. #jira UE-44669 Change 3428140 on 2017/05/08 by Ori.Cohen Added ground truth for scene query testing. Change 3441024 on 2017/05/16 by Nick.Darnell Automation - Ground truth pass, improving system based on feedback. Ditching the bCanModify, there's now a way to reset the data, and if it's been filled, you've got to reset it to save over it. Change 3443894 on 2017/05/17 by Nick.Darnell Automation - Automation tweaking some logging. Change 3446426 on 2017/05/18 by Nick.Darnell Automation - Adding additional logging and attempting to fix the warning on the build machine. Change 3447617 on 2017/05/18 by Nick.Darnell Automation - Found an issue with the automation system keeping an old map around if the names were similar enough, and one contained the entirety of the other map's name. This should fix the overlap warnings on the build machine. Also cleaned up several places in the functional test manager that looked like they could cause confusion and problems with cleaning them up. [CL 3449079 by Nick Darnell in Main branch]
501 lines
16 KiB
C++
501 lines
16 KiB
C++
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AutomationWorkerModule.h"
|
|
#include "HAL/FileManager.h"
|
|
#include "Misc/FileHelper.h"
|
|
#include "Misc/Paths.h"
|
|
#include "Misc/App.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "Helpers/MessageEndpointBuilder.h"
|
|
#include "AutomationWorkerMessages.h"
|
|
#include "AutomationAnalytics.h"
|
|
#include "JsonObjectConverter.h"
|
|
|
|
#if WITH_ENGINE
|
|
#include "ImageUtils.h"
|
|
#include "Engine/Engine.h"
|
|
#include "Engine/GameViewportClient.h"
|
|
#include "UnrealClient.h"
|
|
#include "Tests/AutomationCommon.h"
|
|
#endif
|
|
|
|
#if WITH_EDITOR
|
|
#include "AssetRegistryModule.h"
|
|
#endif
|
|
|
|
#define LOCTEXT_NAMESPACE "AutomationTest"
|
|
|
|
IMPLEMENT_MODULE(FAutomationWorkerModule, AutomationWorker);
|
|
|
|
|
|
/* IModuleInterface interface
|
|
*****************************************************************************/
|
|
|
|
void FAutomationWorkerModule::StartupModule()
|
|
{
|
|
Initialize();
|
|
|
|
FAutomationTestFramework::Get().PreTestingEvent.AddRaw(this, &FAutomationWorkerModule::HandlePreTestingEvent);
|
|
FAutomationTestFramework::Get().PostTestingEvent.AddRaw(this, &FAutomationWorkerModule::HandlePostTestingEvent);
|
|
}
|
|
|
|
void FAutomationWorkerModule::ShutdownModule()
|
|
{
|
|
FAutomationTestFramework::Get().PreTestingEvent.RemoveAll(this);
|
|
FAutomationTestFramework::Get().PostTestingEvent.RemoveAll(this);
|
|
}
|
|
|
|
bool FAutomationWorkerModule::SupportsDynamicReloading()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
/* IAutomationWorkerModule interface
|
|
*****************************************************************************/
|
|
|
|
void FAutomationWorkerModule::Tick()
|
|
{
|
|
//execute latent commands from the previous frame. Gives the rest of the engine a turn to tick before closing the test
|
|
bool bAllLatentCommandsComplete = ExecuteLatentCommands();
|
|
if (bAllLatentCommandsComplete)
|
|
{
|
|
//if we were running the latent commands as a result of executing a network command, report that we are now done
|
|
if (bExecutingNetworkCommandResults)
|
|
{
|
|
ReportNetworkCommandComplete();
|
|
bExecutingNetworkCommandResults = false;
|
|
}
|
|
|
|
//if the controller has requested the next network command be executed
|
|
if (bExecuteNextNetworkCommand)
|
|
{
|
|
//execute network commands if there are any queued up and our role is appropriate
|
|
bool bAllNetworkCommandsComplete = ExecuteNetworkCommands();
|
|
if (bAllNetworkCommandsComplete)
|
|
{
|
|
ReportTestComplete();
|
|
}
|
|
|
|
//we've now executed a network command which may have enqueued further latent actions
|
|
bExecutingNetworkCommandResults = true;
|
|
|
|
//do not execute anything else until expressly told to by the controller
|
|
bExecuteNextNetworkCommand = false;
|
|
}
|
|
}
|
|
|
|
if (MessageEndpoint.IsValid())
|
|
{
|
|
MessageEndpoint->ProcessInbox();
|
|
}
|
|
}
|
|
|
|
|
|
/* ISessionManager implementation
|
|
*****************************************************************************/
|
|
|
|
bool FAutomationWorkerModule::ExecuteLatentCommands()
|
|
{
|
|
bool bAllLatentCommandsComplete = false;
|
|
|
|
if (GIsAutomationTesting)
|
|
{
|
|
// Ensure that latent automation commands have time to execute
|
|
bAllLatentCommandsComplete = FAutomationTestFramework::Get().ExecuteLatentCommands();
|
|
}
|
|
|
|
return bAllLatentCommandsComplete;
|
|
}
|
|
|
|
|
|
bool FAutomationWorkerModule::ExecuteNetworkCommands()
|
|
{
|
|
bool bAllLatentCommandsComplete = false;
|
|
|
|
if (GIsAutomationTesting)
|
|
{
|
|
// Ensure that latent automation commands have time to execute
|
|
bAllLatentCommandsComplete = FAutomationTestFramework::Get().ExecuteNetworkCommands();
|
|
}
|
|
|
|
return bAllLatentCommandsComplete;
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::Initialize()
|
|
{
|
|
if (FPlatformProcess::SupportsMultithreading())
|
|
{
|
|
// initialize messaging
|
|
MessageEndpoint = FMessageEndpoint::Builder("FAutomationWorkerModule")
|
|
.Handling<FAutomationWorkerFindWorkers>(this, &FAutomationWorkerModule::HandleFindWorkersMessage)
|
|
.Handling<FAutomationWorkerNextNetworkCommandReply>(this, &FAutomationWorkerModule::HandleNextNetworkCommandReplyMessage)
|
|
.Handling<FAutomationWorkerPing>(this, &FAutomationWorkerModule::HandlePingMessage)
|
|
.Handling<FAutomationWorkerResetTests>(this, &FAutomationWorkerModule::HandleResetTests)
|
|
.Handling<FAutomationWorkerRequestTests>(this, &FAutomationWorkerModule::HandleRequestTestsMessage)
|
|
.Handling<FAutomationWorkerRunTests>(this, &FAutomationWorkerModule::HandleRunTestsMessage)
|
|
.Handling<FAutomationWorkerImageComparisonResults>(this, &FAutomationWorkerModule::HandleScreenShotCompared)
|
|
.Handling<FAutomationWorkerTestDataResponse>(this, &FAutomationWorkerModule::HandleTestDataRetrieved)
|
|
.WithInbox();
|
|
|
|
if (MessageEndpoint.IsValid())
|
|
{
|
|
MessageEndpoint->Subscribe<FAutomationWorkerFindWorkers>();
|
|
}
|
|
|
|
bExecuteNextNetworkCommand = true;
|
|
}
|
|
else
|
|
{
|
|
bExecuteNextNetworkCommand = false;
|
|
}
|
|
ExecutionCount = INDEX_NONE;
|
|
bExecutingNetworkCommandResults = false;
|
|
bSendAnalytics = false;
|
|
}
|
|
|
|
void FAutomationWorkerModule::ReportNetworkCommandComplete()
|
|
{
|
|
if (GIsAutomationTesting)
|
|
{
|
|
MessageEndpoint->Send(new FAutomationWorkerRequestNextNetworkCommand(ExecutionCount), TestRequesterAddress);
|
|
if (StopTestEvent.IsBound())
|
|
{
|
|
// this is a local test; the message to continue will never arrive, so lets not wait for it
|
|
bExecuteNextNetworkCommand = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Takes a large transport array and splits it into pieces of a desired size and returns the portion of this which is requested
|
|
*
|
|
* @param FullTransportArray The whole series of data
|
|
* @param CurrentChunkIndex The The chunk we are requesting
|
|
* @param NumToSend The maximum number of bytes we should be splitting into.
|
|
* @return The section of the transport array which matches our index requested
|
|
*/
|
|
TArray< uint8 > GetTransportSection( const TArray< uint8 >& FullTransportArray, const int32 NumToSend, const int32 RequestedChunkIndex )
|
|
{
|
|
TArray< uint8 > TransportArray = FullTransportArray;
|
|
|
|
if( NumToSend > 0 )
|
|
{
|
|
int32 NumToRemoveFromStart = RequestedChunkIndex * NumToSend;
|
|
if( NumToRemoveFromStart > 0 )
|
|
{
|
|
TransportArray.RemoveAt( 0, NumToRemoveFromStart );
|
|
}
|
|
|
|
int32 NumToRemoveFromEnd = FullTransportArray.Num() - NumToRemoveFromStart - NumToSend;
|
|
if( NumToRemoveFromEnd > 0 )
|
|
{
|
|
TransportArray.RemoveAt( TransportArray.Num()-NumToRemoveFromEnd, NumToRemoveFromEnd );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TransportArray.Empty();
|
|
}
|
|
|
|
return TransportArray;
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::ReportTestComplete()
|
|
{
|
|
if (GIsAutomationTesting)
|
|
{
|
|
//see if there are any more network commands left to execute
|
|
bool bAllLatentCommandsComplete = FAutomationTestFramework::Get().ExecuteLatentCommands();
|
|
|
|
//structure to track error/warning/log messages
|
|
FAutomationTestExecutionInfo ExecutionInfo;
|
|
|
|
bool bSuccess = FAutomationTestFramework::Get().StopTest(ExecutionInfo);
|
|
|
|
if (StopTestEvent.IsBound())
|
|
{
|
|
StopTestEvent.Execute(bSuccess, TestName, ExecutionInfo);
|
|
}
|
|
else
|
|
{
|
|
// send the results to the controller
|
|
FAutomationWorkerRunTestsReply* Message = new FAutomationWorkerRunTestsReply();
|
|
|
|
Message->TestName = TestName;
|
|
Message->ExecutionCount = ExecutionCount;
|
|
Message->Success = bSuccess;
|
|
Message->Duration = ExecutionInfo.Duration;
|
|
Message->Events = ExecutionInfo.GetEvents();
|
|
Message->WarningTotal = ExecutionInfo.GetWarningTotal();
|
|
Message->ErrorTotal = ExecutionInfo.GetErrorTotal();
|
|
|
|
// sending though the endpoint will free Message memory, so analytics need to be sent first
|
|
if (bSendAnalytics)
|
|
{
|
|
if (!FAutomationAnalytics::IsInitialized())
|
|
{
|
|
FAutomationAnalytics::Initialize();
|
|
}
|
|
FAutomationAnalytics::FireEvent_AutomationTestResults(Message, BeautifiedTestName);
|
|
SendAnalyticsEvents(ExecutionInfo.AnalyticsItems);
|
|
}
|
|
|
|
MessageEndpoint->Send(Message, TestRequesterAddress);
|
|
}
|
|
|
|
|
|
// reset local state
|
|
TestRequesterAddress.Invalidate();
|
|
ExecutionCount = INDEX_NONE;
|
|
TestName.Empty();
|
|
StopTestEvent.Unbind();
|
|
}
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::SendTests( const FMessageAddress& ControllerAddress )
|
|
{
|
|
for( int32 TestIndex = 0; TestIndex < TestInfo.Num(); TestIndex++ )
|
|
{
|
|
MessageEndpoint->Send(new FAutomationWorkerRequestTestsReply(TestInfo[TestIndex], TestInfo.Num()), ControllerAddress);
|
|
}
|
|
MessageEndpoint->Send(new FAutomationWorkerRequestTestsReplyComplete(), ControllerAddress);
|
|
}
|
|
|
|
|
|
/* FAutomationWorkerModule callbacks
|
|
*****************************************************************************/
|
|
|
|
void FAutomationWorkerModule::HandleFindWorkersMessage(const FAutomationWorkerFindWorkers& Message, const IMessageContextRef& Context)
|
|
{
|
|
// Set the Instance name to be the same as the session browser. This information should be shared at some point
|
|
if ((Message.SessionId == FApp::GetSessionId()) && (Message.Changelist == 10000))
|
|
{
|
|
TestRequesterAddress = Context->GetSender();
|
|
|
|
#if WITH_EDITOR
|
|
//If the asset registry is loading assets then we'll wait for it to stop before running our automation tests.
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
|
|
if (AssetRegistryModule.Get().IsLoadingAssets())
|
|
{
|
|
if (!AssetRegistryModule.Get().OnFilesLoaded().IsBoundToObject(this))
|
|
{
|
|
AssetRegistryModule.Get().OnFilesLoaded().AddRaw(this, &FAutomationWorkerModule::SendWorkerFound);
|
|
GLog->Logf(ELogVerbosity::Log, TEXT("...Forcing Asset Registry Load For Automation"));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
//If the registry is not loading then we'll just go ahead and run our tests.
|
|
SendWorkerFound();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::SendWorkerFound()
|
|
{
|
|
FAutomationWorkerFindWorkersResponse* Response = new FAutomationWorkerFindWorkersResponse();
|
|
|
|
FString OSMajorVersionString, OSSubVersionString;
|
|
FPlatformMisc::GetOSVersions(OSMajorVersionString, OSSubVersionString);
|
|
|
|
FString OSVersionString = OSMajorVersionString + TEXT(" ") + OSSubVersionString;
|
|
FString CPUModelString = FPlatformMisc::GetCPUBrand().Trim();
|
|
|
|
Response->DeviceName = FPlatformProcess::ComputerName();
|
|
Response->InstanceName = FString::Printf(TEXT("%s-%i"), FPlatformProcess::ComputerName(), FPlatformProcess::GetCurrentProcessId());
|
|
Response->Platform = FPlatformProperties::PlatformName();
|
|
Response->SessionId = FApp::GetSessionId();
|
|
Response->OSVersionName = OSVersionString;
|
|
Response->ModelName = FPlatformMisc::GetDefaultDeviceProfileName();
|
|
Response->GPUName = FPlatformMisc::GetPrimaryGPUBrand();
|
|
Response->CPUModelName = CPUModelString;
|
|
Response->RAMInGB = FPlatformMemory::GetPhysicalGBRam();
|
|
#if WITH_ENGINE
|
|
Response->RenderModeName = AutomationCommon::GetRenderDetailsString();
|
|
#else
|
|
Response->RenderModeName = TEXT("Unknown");
|
|
#endif
|
|
|
|
MessageEndpoint->Send(Response, TestRequesterAddress);
|
|
TestRequesterAddress.Invalidate();
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandleNextNetworkCommandReplyMessage( const FAutomationWorkerNextNetworkCommandReply& Message, const IMessageContextRef& Context )
|
|
{
|
|
// Allow the next command to execute
|
|
bExecuteNextNetworkCommand = true;
|
|
|
|
// We should never be executing sub-commands of a network command when we're waiting for a cue for the next network command
|
|
check(bExecutingNetworkCommandResults == false);
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandlePingMessage( const FAutomationWorkerPing& Message, const IMessageContextRef& Context )
|
|
{
|
|
MessageEndpoint->Send(new FAutomationWorkerPong(), Context->GetSender());
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandleResetTests( const FAutomationWorkerResetTests& Message, const IMessageContextRef& Context )
|
|
{
|
|
FAutomationTestFramework::Get().ResetTests();
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandleRequestTestsMessage( const FAutomationWorkerRequestTests& Message, const IMessageContextRef& Context )
|
|
{
|
|
FAutomationTestFramework::Get().LoadTestModules();
|
|
FAutomationTestFramework::Get().SetDeveloperDirectoryIncluded(Message.DeveloperDirectoryIncluded);
|
|
FAutomationTestFramework::Get().SetRequestedTestFilter(Message.RequestedTestFlags);
|
|
FAutomationTestFramework::Get().GetValidTestNames( TestInfo );
|
|
|
|
SendTests(Context->GetSender());
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandlePreTestingEvent()
|
|
{
|
|
#if WITH_ENGINE
|
|
if (!GIsEditor && GEngine->GameViewport)
|
|
{
|
|
GEngine->GameViewport->OnScreenshotCaptured().AddRaw(this, &FAutomationWorkerModule::HandleScreenShotCaptured);
|
|
}
|
|
//Register the editor screen shot callback
|
|
FAutomationTestFramework::Get().OnScreenshotCaptured().BindRaw(this, &FAutomationWorkerModule::HandleScreenShotCapturedWithName);
|
|
#endif
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandlePostTestingEvent()
|
|
{
|
|
#if WITH_ENGINE
|
|
if (!GIsEditor && GEngine->GameViewport)
|
|
{
|
|
GEngine->GameViewport->OnScreenshotCaptured().RemoveAll(this);
|
|
}
|
|
//Register the editor screen shot callback
|
|
FAutomationTestFramework::Get().OnScreenshotCaptured().BindRaw(this, &FAutomationWorkerModule::HandleScreenShotCapturedWithName);
|
|
#endif
|
|
}
|
|
|
|
|
|
void FAutomationWorkerModule::HandleScreenShotCompared(const FAutomationWorkerImageComparisonResults& Message, const IMessageContextRef& Context)
|
|
{
|
|
// Image comparison finished.
|
|
FAutomationTestFramework::Get().NotifyScreenshotComparisonComplete(Message.bNew, Message.bSimilar, Message.MaxLocalDifference, Message.GlobalDifference, Message.ErrorMessage);
|
|
}
|
|
|
|
void FAutomationWorkerModule::HandleTestDataRetrieved(const FAutomationWorkerTestDataResponse& Message, const IMessageContextRef& Context)
|
|
{
|
|
FAutomationTestFramework::Get().NotifyTestDataRetrieved(Message.bIsNew, Message.JsonData);
|
|
}
|
|
|
|
void FAutomationWorkerModule::HandlePerformanceDataRetrieved(const FAutomationWorkerPerformanceDataResponse& Message, const IMessageContextRef& Context)
|
|
{
|
|
FAutomationTestFramework::Get().NotifyPerformanceDataRetrieved(Message.bSuccess, Message.ErrorMessage);
|
|
}
|
|
|
|
#if WITH_ENGINE
|
|
void FAutomationWorkerModule::HandleScreenShotCaptured(int32 Width, int32 Height, const TArray<FColor>& Bitmap)
|
|
{
|
|
FAutomationScreenshotData Data;
|
|
Data.Width = Width;
|
|
Data.Height = Height;
|
|
Data.Path = FScreenshotRequest::GetFilename();
|
|
|
|
HandleScreenShotCapturedWithName(Bitmap, Data);
|
|
}
|
|
|
|
void FAutomationWorkerModule::HandleScreenShotCapturedWithName(const TArray<FColor>& RawImageData, const FAutomationScreenshotData& Data)
|
|
{
|
|
int32 NewHeight = Data.Height;
|
|
int32 NewWidth = Data.Width;
|
|
|
|
TArray<uint8> CompressedBitmap;
|
|
FImageUtils::CompressImageArray(NewWidth, NewHeight, RawImageData, CompressedBitmap);
|
|
|
|
FAutomationScreenshotMetadata Metadata(Data);
|
|
|
|
// Send the screen shot if we have a target
|
|
if( TestRequesterAddress.IsValid() )
|
|
{
|
|
FAutomationWorkerScreenImage* Message = new FAutomationWorkerScreenImage();
|
|
|
|
Message->ScreenShotName = FPaths::RootDir() / Data.Path;
|
|
FPaths::MakePathRelativeTo(Message->ScreenShotName, *FPaths::AutomationDir());
|
|
Message->ScreenImage = CompressedBitmap;
|
|
Message->Metadata = Metadata;
|
|
MessageEndpoint->Send(Message, TestRequesterAddress);
|
|
}
|
|
else
|
|
{
|
|
//Save locally
|
|
const bool bTree = true;
|
|
IFileManager::Get().MakeDirectory(*FPaths::GetPath(Data.Path), bTree);
|
|
FFileHelper::SaveArrayToFile(CompressedBitmap, *Data.Path);
|
|
|
|
FString Json;
|
|
if ( FJsonObjectConverter::UStructToJsonObjectString(Metadata, Json) )
|
|
{
|
|
FString MetadataPath = FPaths::ChangeExtension(Data.Path, TEXT("json"));
|
|
FFileHelper::SaveStringToFile(Json, *MetadataPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
void FAutomationWorkerModule::HandleRunTestsMessage( const FAutomationWorkerRunTests& Message, const IMessageContextRef& Context )
|
|
{
|
|
ExecutionCount = Message.ExecutionCount;
|
|
TestName = Message.TestName;
|
|
BeautifiedTestName = Message.BeautifiedTestName;
|
|
bSendAnalytics = Message.bSendAnalytics;
|
|
TestRequesterAddress = Context->GetSender();
|
|
|
|
// Always allow the first network command to execute
|
|
bExecuteNextNetworkCommand = true;
|
|
|
|
// We are not executing network command sub-commands right now
|
|
bExecutingNetworkCommandResults = false;
|
|
|
|
FAutomationTestFramework::Get().StartTestByName(Message.TestName, Message.RoleIndex);
|
|
}
|
|
|
|
|
|
//dispatches analytics events to the data collector
|
|
void FAutomationWorkerModule::SendAnalyticsEvents(TArray<FString>& InAnalyticsItems)
|
|
{
|
|
for (int32 i = 0; i < InAnalyticsItems.Num(); ++i)
|
|
{
|
|
FString EventString = InAnalyticsItems[i];
|
|
if( EventString.EndsWith( TEXT( ",PERF" ) ) )
|
|
{
|
|
// Chop the ",PERF" off the end
|
|
EventString = EventString.Left( EventString.Len() - 5 );
|
|
|
|
FAutomationPerformanceSnapshot PerfSnapshot;
|
|
PerfSnapshot.FromCommaDelimitedString( EventString );
|
|
|
|
RecordPerformanceAnalytics( PerfSnapshot );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FAutomationWorkerModule::RecordPerformanceAnalytics( const FAutomationPerformanceSnapshot& PerfSnapshot )
|
|
{
|
|
// @todo: Pass in additional performance capture data from incoming FAutomationPerformanceSnapshot!
|
|
|
|
FAutomationAnalytics::FireEvent_FPSCapture(PerfSnapshot);
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|