Files
UnrealEngineUWP/Engine/Source/Developer/FunctionalTesting/Classes/FunctionalTest.h
Andrew Grant f25badee7f Copying //UE4/Orion-Staging to //UE4/Main (Origin: //Orion/Dev-General @2826496)
#lockdown Nick.Penwarden

==========================
MAJOR FEATURES + CHANGES
==========================

Change 2826201 on 2016/01/13 by Zabir.Hoque

	Add more verbose logging to try to understand #OR-11297

	#lockdown Andrew.Grant
	#CodeReview Marcus.Wassmer
	#RB none
	#TESTS compiled Win64 debug editor, ran agora_p

Change 2826170 on 2016/01/13 by Marcus.Wassmer

	Flush unloaded resource properly in LoadMap
	#codereview Gil.Gribb
	#rb none
	#test cycling game.  memory is freed properly now.
	#lockdown Andrew.Grant

Change 2826135 on 2016/01/12 by Michael.Noland

	Orion: Improve login screen on PC to reduce the potential impact of framerate on data center ping calculation
	- Disabled async streaming for the duration of the QOS ping measurement to avoid hitches
	- Added a circular throbber in the top left corner of the login screen indicating that something is async streaming (as a diagnostic tool for users affected by the datacenter ping, can be removed in the future)
	- Added logging of the current average frame time when the datacenter ping is finalized
	- Added a 'Pick Ideal Settings' button to the login screen (note: on the actual screen, not the login widget, so it will not appear on PS4)
	#jira OR-12453
	#rb paul.moore
	#tests Ran a QOS server and client and verified that the new logging is occurring, tried out the new benchmark button, etc...

	Merging CL# 2826128 using //Orion/Main_to_//Orion/Dev-General

Change 2826131 on 2016/01/12 by Michael.Noland

	#UE4 - added print out of MS/FPS during Qos ping evaluation
	#rb michael.noland
	#tests loaded up through login screen to see output

	Merging CL# 2825678 using //Orion/Main_to_//Orion/Dev-General

Change 2826128 on 2016/01/12 by Michael.Noland

	Orion: Improve login screen on PC to reduce the potential impact of framerate on data center ping calculation
	- Disabled async streaming for the duration of the QOS ping measurement to avoid hitches
	- Added a circular throbber in the top left corner of the login screen indicating that something is async streaming (as a diagnostic tool for users affected by the datacenter ping, can be removed in the future)
	- Added logging of the current average frame time when the datacenter ping is finalized
	- Added a 'Pick Ideal Settings' button to the login screen (note: on the actual screen, not the login widget, so it will not appear on PS4)
	#jira OR-12453
	#rb paul.moore
	#tests Ran a QOS server and client and verified that the new logging is occurring, tried out the new benchmark button, etc...

	Merging CL# 2826116 using //Orion/Release-Next->//Orion/Main

Change 2826116 on 2016/01/12 by Michael.Noland

	Orion: Improve login screen on PC to reduce the potential impact of framerate on data center ping calculation
	- Disabled async streaming for the duration of the QOS ping measurement to avoid hitches
	- Added a circular throbber in the top left corner of the login screen indicating that something is async streaming (as a diagnostic tool for users affected by the datacenter ping, can be removed in the future)
	- Added logging of the current average frame time when the datacenter ping is finalized
	- Added a 'Pick Ideal Settings' button to the login screen (note: on the actual screen, not the login widget, so it will not appear on PS4)
	#jira OR-12453
	#rb paul.moore
	#tests Ran a QOS server and client and verified that the new logging is occurring, tried out the new benchmark button, etc...
	#lockdown andrew.grant
	#codereview josh.markiewicz

Change 2825772 on 2016/01/12 by Dmitry.Rekman

	Linux signal handling improvements.

	- Switch crash handlers to use "crash malloc" (preallocated memory) on crash.
	- Remove unnecessary memory allocations from graceful termination handler.

	#rb none
	#tests Run the Linux server and crashed it a few times.
	#codereview David.Vossel, Michael.Trepka

Change 2825768 on 2016/01/12 by Josh.Markiewicz

	#UE4 - added print out of MS/FPS during Qos ping evaluation
	#rb michael.noland
	#tests loaded up through login screen to see output

Change 2825703 on 2016/01/12 by Brian.Karis

	Switched on new motion blur. Set temporal AA sharpness to 1.

	#rb none
	#TESTS editor

Change 2825689 on 2016/01/12 by Lina.Halper

	Fix for get animation notify crash

	https://jira.ol.epicgames.net/browse/OR-12248
	https://jira.ol.epicgames.net/browse/OR-12348

	- Also fixed the crash in preview of persona due to blend sample cache contains previous animation data
	- Also fixed blend space player to reinitialize cache data
	- The main issue is marker doesn't clamp the length, causing notifies ensure to trigger.

	#rb : Laurent.Delayen
	#tests: 10 Sparrows bot match for long time
	#code review: Martin.Wilson
	#lockdown: Andrew.Grant

Change 2825680 on 2016/01/12 by Martin.Mittring

	fixed all cases with r.Tonemapper.ScreenPercentage, ScreenPercentage, Fringe, Vignette, ViewRect, flickering with transluceny (View members have been modified while other thread was reading)
	#rb:Olaf.Piesche, David.Hill
	#test: PC, many cases

Change 2825579 on 2016/01/12 by Chris.Bunner

	Force shadow shape bone indices on the required update list.
	#rb Lina.Halper, Rolando.Caloca
	#tests Editor
	#codereview Daniel.Wright
	#jira OR-12339

Change 2825443 on 2016/01/12 by Martin.Mittring
2016-01-14 08:11:47 -05:00

371 lines
12 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GameFramework/Actor.h"
#include "Math/RandomStream.h"
#include "FunctionalTest.generated.h"
class UBillboardComponent;
//Experimental effort at automated cpu captures from the functional testing.
class FFunctionalTestExternalProfiler : public FScopedExternalProfilerBase
{
public:
void StartProfiler(const bool bWantPause){ StartScopedTimer(bWantPause); }
void StopProfiler(){StopScopedTimer();}
};
// Used to measure a distribution
struct FStatisticalFloat
{
public:
FStatisticalFloat()
: MinValue(0.0)
, MaxValue(0.0)
, Accumulator(0.0)
, NumSamples(0)
{
}
void AddSample(double Value)
{
if (NumSamples == 0)
{
MinValue = MaxValue = Value;
}
else
{
MinValue = FMath::Min(MinValue, Value);
MaxValue = FMath::Max(MaxValue, Value);
}
Accumulator += Value;
++NumSamples;
}
double GetMinValue() const
{
return MinValue;
}
double GetMaxValue() const
{
return MaxValue;
}
double GetAvgValue() const
{
return Accumulator / (double)NumSamples;
}
int32 GetCount() const
{
return NumSamples;
}
private:
double MinValue;
double MaxValue;
double Accumulator;
int32 NumSamples;
};
struct FStatsData
{
FStatsData() :NumFrames(0), SumTimeSeconds(0.0f){}
uint32 NumFrames;
uint32 SumTimeSeconds;
FStatisticalFloat FrameTimeTracker;
FStatisticalFloat GameThreadTimeTracker;
FStatisticalFloat RenderThreadTimeTracker;
FStatisticalFloat GPUTimeTracker;
};
/** A set of simple perf stats recorded over a period of frames. */
struct FUNCTIONALTESTING_API FPerfStatsRecord
{
FPerfStatsRecord(FString InName);
FString Name;
/** Stats data for the period we're interested in timing. */
FStatsData Record;
/** Stats data for the baseline. */
FStatsData Baseline;
float GPUBudget;
float RenderThreadBudget;
float GameThreadBudget;
void SetBudgets(float InGPUBudget, float InRenderThreadBudget, float InGameThreadBudget);
void Sample(UWorld* Owner, float DeltaSeconds, bool bBaseline);
FString GetReportString()const;
FString GetBaselineString()const;
FString GetRecordString()const;
FString GetOverBudgetString()const;
void GetGPUTimes(double& OutMin, double& OutMax, double& OutAvg)const;
void GetGameThreadTimes(double& OutMin, double& OutMax, double& OutAvg)const;
void GetRenderThreadTimes(double& OutMin, double& OutMax, double& OutAvg)const;
bool IsWithinGPUBudget()const;
bool IsWithinGameThreadBudget()const;
bool IsWithinRenderThreadBudget()const;
};
/**
* Class for use with functional tests which provides various performance measuring features.
* Recording of basic, unintrusive performance stats.
* Automatic captures using external CPU and GPU profilers.
* Triggering and ending of writing full stats to a file.
*/
UCLASS(Blueprintable)
class FUNCTIONALTESTING_API UAutomationPerformaceHelper : public UObject
{
GENERATED_BODY()
TArray<FPerfStatsRecord> Records;
bool bRecordingBasicStats;
bool bRecordingBaselineBasicStats;
bool bRecordingCPUCapture;
bool bRecordingStatsFile;
/** If true we check the GPU times vs GPU budget each tick and trigger a GPU trace if we fall below budget.*/
bool bGPUTraceIfBelowBudget;
public:
UAutomationPerformaceHelper();
//Begin basic stat recording
UFUNCTION(BlueprintCallable, Category = Perf)
void Tick(float DeltaSeconds);
/** Adds a sample to the stats counters for the current performance stats record. */
UFUNCTION(BlueprintCallable, Category = Perf)
void Sample(float DeltaSeconds);
/** Begins recording a new named performance stats record. We start by recording the baseline */
UFUNCTION(BlueprintCallable, Category = Perf)
void BeginRecordingBaseline(FString RecordName);
/** Stops recording the baseline and moves to the main record. */
UFUNCTION(BlueprintCallable, Category = Perf)
void EndRecordingBaseline();
/** Begins recording a new named performance stats record. We start by recording the baseline. */
UFUNCTION(BlueprintCallable, Category = Perf)
void BeginRecording(FString RecordName, float InGPUBudget, float InRenderThreadBudget, float InGameThreadBudget);
/** Stops recording performance stats. */
UFUNCTION(BlueprintCallable, Category = Perf)
void EndRecording();
/** Writes the current set of performance stats records to a csv file in the profiling directory. An additional directory and an extension override can also be used. */
UFUNCTION(BlueprintCallable, Category = Perf)
void WriteLogFile(const FString& CaptureDir, const FString& CaptureExtension);
/** Returns true if this stats tracker is currently recording performance stats. */
UFUNCTION(BlueprintCallable, Category = Perf)
bool IsRecording()const;
/** Does any init work across all tests.. */
UFUNCTION(BlueprintCallable, Category = Perf)
void OnBeginTests();
/** Does any final work needed as all tests are complete. */
UFUNCTION(BlueprintCallable, Category = Perf)
void OnAllTestsComplete();
const FPerfStatsRecord* GetCurrentRecord()const;
FPerfStatsRecord* GetCurrentRecord();
UFUNCTION(BlueprintCallable, Category = Perf)
bool IsCurrentRecordWithinGPUBudget()const;
UFUNCTION(BlueprintCallable, Category = Perf)
bool IsCurrentRecordWithinGameThreadBudget()const;
UFUNCTION(BlueprintCallable, Category = Perf)
bool IsCurrentRecordWithinRenderThreadBudget()const;
//End basic stats recording.
// Automatic traces capturing
/** Communicates with external profiler to being a CPU capture. */
UFUNCTION(BlueprintCallable, Category = Perf)
void StartCPUProfiling();
/** Communicates with external profiler to end a CPU capture. */
UFUNCTION(BlueprintCallable, Category = Perf)
void StopCPUProfiling();
/** Will trigger a GPU trace next time the current test falls below GPU budget. */
UFUNCTION(BlueprintCallable, Category = Perf)
void TriggerGPUTraceIfRecordFallsBelowBudget();
/** Begins recording stats to a file. */
UFUNCTION(BlueprintCallable, Category = Perf)
void BeginStatsFile(const FString& RecordName);
/** Ends recording stats to a file. */
UFUNCTION(BlueprintCallable, Category = Perf)
void EndStatsFile();
FFunctionalTestExternalProfiler ExternalProfiler;
/** The path and base name for all output files. */
FString OutputFileBase;
FString StartOfTestingTime;
};
UENUM()
namespace EFunctionalTestResult
{
enum Type
{
Invalid,
Error,
Running,
Failed,
Succeeded,
};
}
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FFunctionalTestEventSignature);
DECLARE_DELEGATE_OneParam(FFunctionalTestDoneSignature, class AFunctionalTest*);
UCLASS(Blueprintable, MinimalAPI)
class AFunctionalTest : public AActor
{
GENERATED_UCLASS_BODY()
static const uint32 DefaultTimeLimit = 60; // seconds
private_subobject:
DEPRECATED_FORGAME(4.6, "SpriteComponent should not be accessed directly, please use GetSpriteComponent() function instead. SpriteComponent will soon be private and your code will not compile.")
UPROPERTY()
UBillboardComponent* SpriteComponent;
public:
UPROPERTY(BlueprintReadWrite, Category=FunctionalTesting)
TEnumAsByte<EFunctionalTestResult::Type> Result;
/** If test is limited by time this is the result that will be returned when time runs out */
UPROPERTY(EditAnywhere, Category=FunctionalTesting)
TEnumAsByte<EFunctionalTestResult::Type> TimesUpResult;
/** Test's time limit. '0' means no limit */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=FunctionalTesting)
float TimeLimit;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=FunctionalTesting)
FText TimesUpMessage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=FunctionalTesting)
AActor* ObservationPoint;
/** Called when the test is started */
UPROPERTY(BlueprintAssignable)
FFunctionalTestEventSignature OnTestStart;
/** Called when the test is finished. Use it to clean up */
UPROPERTY(BlueprintAssignable)
FFunctionalTestEventSignature OnTestFinished;
UPROPERTY(Transient)
TArray<AActor*> AutoDestroyActors;
FString FailureMessage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = FunctionalTesting)
FRandomStream RandomNumbersStream;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = FunctionalTesting)
FString Description;
#if WITH_EDITORONLY_DATA
UPROPERTY()
class UFuncTestRenderingComponent* RenderComp;
#endif // WITH_EDITORONLY_DATA
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=FunctionalTesting)
uint32 bIsEnabled:1;
/** List of causes we need a re-run. */
TArray<FName> RerunCauses;
/** Cause of the current rerun if we're in a named rerun. */
FName CurrentRerunCause;
public:
virtual bool StartTest(const TArray<FString>& Params = TArray<FString>());
UFUNCTION(BlueprintCallable, Category="Development")
virtual void FinishTest(TEnumAsByte<EFunctionalTestResult::Type> TestResult, const FString& Message);
UFUNCTION(BlueprintCallable, Category="Development")
virtual void LogMessage(const FString& Message);
UFUNCTION(BlueprintCallable, Category="Development")
virtual void SetTimeLimit(float NewTimeLimit, TEnumAsByte<EFunctionalTestResult::Type> ResultWhenTimeRunsOut);
/** Used by debug drawing to gather actors this test is using and point at them on the level to better understand test's setup */
UFUNCTION(BlueprintImplementableEvent, Category = "FunctionalTesting")
TArray<AActor*> DebugGatherRelevantActors() const;
virtual void GatherRelevantActors(TArray<AActor*>& OutActors) const;
/** retrieves information whether test wants to have another run just after finishing */
UFUNCTION(BlueprintImplementableEvent, Category="FunctionalTesting")
bool OnWantsReRunCheck() const;
virtual bool WantsToRunAgain() const { return false; }
/** Causes the test to be rerun for a specific named reason. */
UFUNCTION(BlueprintCallable, Category = "FunctionalTesting")
void AddRerun(FName Reason);
/** Returns the current re-run reason if we're in a named re-run. */
UFUNCTION(BlueprintCallable, Category = "FunctionalTesting")
FName GetCurrentRerunReason()const;
UFUNCTION(BlueprintImplementableEvent, Category = "FunctionalTesting")
FString OnAdditionalTestFinishedMessageRequest(EFunctionalTestResult::Type TestResult) const;
virtual FString GetAdditionalTestFinishedMessage(EFunctionalTestResult::Type TestResult) const { return FString(); }
/** ACtors registered this way will be automatically destroyed (by limiting their lifespan)
* on test finish */
UFUNCTION(BlueprintCallable, Category="Development", meta=(Keywords = "Delete"))
virtual void RegisterAutoDestroyActor(AActor* ActorToAutoDestroy);
/** Called to clean up when tests is removed from the list of active tests after finishing execution.
* Note that FinishTest gets called after every "cycle" of a test (where further cycles are enabled by
* WantsToRunAgain calls). CleanUp gets called when all cycles are done. */
virtual void CleanUp();
virtual FString GetReproString() const { return GetFName().ToString(); }
#if WITH_EDITOR
void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
static void OnSelectObject(UObject* NewSelection);
#endif // WITH_EDITOR
// AActor interface begin
virtual void Tick(float DeltaSeconds) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
// AActor interface end
bool IsSuccessful() const { return Result == EFunctionalTestResult::Succeeded; }
bool IsRunning() const { return !!bIsRunning; }
protected:
void GoToObservationPoint();
public:
FFunctionalTestDoneSignature TestFinishedObserver;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=FunctionalTesting)
bool bIsRunning;
float TotalTime;
public:
/** Returns SpriteComponent subobject **/
UBillboardComponent* GetSpriteComponent();
};