2014-03-14 14:13:41 -04:00
|
|
|
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "FunctionalTestingPrivatePCH.h"
|
|
|
|
|
#include "ObjectEditorUtils.h"
|
Remove more headers from Engine.h (StaticMeshResources.h, AnimTree.h, SkeletalMeshTypes.h, SkeletalMeshActor.h, LightingBuildOptions.h, PixelFormat.h, WorldComposition.h, VisualLog.h, StaticLighting.h, Lightmap.h, ShadowMap.h, Model.h)
[CL 2086772 by James Golding in Main branch]
2014-05-29 17:21:47 -04:00
|
|
|
#include "VisualLog.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
AFunctionalTest::AFunctionalTest( const class FPostConstructInitializeProperties& PCIP )
|
|
|
|
|
: Super(PCIP)
|
|
|
|
|
, TimesUpResult(EFunctionalTestResult::Failed)
|
|
|
|
|
, TimeLimit(DefaultTimeLimit)
|
|
|
|
|
, TimesUpMessage( NSLOCTEXT("FunctionalTest", "DefaultTimesUpMessage", "Time's up!") )
|
2014-04-23 19:29:53 -04:00
|
|
|
, bIsEnabled(true)
|
2014-03-14 14:13:41 -04:00
|
|
|
, bIsRunning(false)
|
2014-06-06 06:27:44 -04:00
|
|
|
, TotalTime(0.f)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
|
|
|
PrimaryActorTick.bStartWithTickEnabled = false;
|
|
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
SpriteComponent = PCIP.CreateDefaultSubobject<UBillboardComponent>(this, TEXT("Sprite"));
|
|
|
|
|
if (SpriteComponent)
|
|
|
|
|
{
|
|
|
|
|
SpriteComponent->bHiddenInGame = false;
|
|
|
|
|
SpriteComponent->AlwaysLoadOnClient = false;
|
|
|
|
|
SpriteComponent->AlwaysLoadOnServer = false;
|
2014-03-14 14:13:41 -04:00
|
|
|
#if WITH_EDITORONLY_DATA
|
2014-04-23 19:29:53 -04:00
|
|
|
|
|
|
|
|
if (!IsRunningCommandlet())
|
2014-04-02 18:09:23 -04:00
|
|
|
{
|
2014-04-23 19:29:53 -04:00
|
|
|
struct FConstructorStatics
|
2014-04-02 18:09:23 -04:00
|
|
|
{
|
2014-04-23 19:29:53 -04:00
|
|
|
ConstructorHelpers::FObjectFinderOptional<UTexture2D> Texture;
|
|
|
|
|
FName ID_FTests;
|
|
|
|
|
FText NAME_FTests;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
FConstructorStatics()
|
|
|
|
|
: Texture(TEXT("/Engine/EditorResources/S_FTest"))
|
|
|
|
|
, ID_FTests(TEXT("FTests"))
|
|
|
|
|
, NAME_FTests(NSLOCTEXT( "SpriteCategory", "FTests", "FTests" ))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
static FConstructorStatics ConstructorStatics;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
SpriteComponent->Sprite = ConstructorStatics.Texture.Get();
|
|
|
|
|
SpriteComponent->SpriteInfo.Category = ConstructorStatics.ID_FTests;
|
|
|
|
|
SpriteComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_FTests;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-04-23 19:29:53 -04:00
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
RootComponent = SpriteComponent;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AFunctionalTest::Tick(float DeltaSeconds)
|
|
|
|
|
{
|
|
|
|
|
// already requested not to tick.
|
|
|
|
|
if (bIsRunning == false)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-06 06:27:44 -04:00
|
|
|
TotalTime += DeltaSeconds;
|
|
|
|
|
if (TimeLimit > 0.f && TotalTime > TimeLimit)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
FinishTest(TimesUpResult, TimesUpMessage.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Super::Tick(DeltaSeconds);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
bool AFunctionalTest::StartTest()
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-04-23 19:29:53 -04:00
|
|
|
FailureMessage = TEXT("");
|
|
|
|
|
|
2014-06-06 06:27:44 -04:00
|
|
|
TotalTime = 0.f;
|
2014-03-14 14:13:41 -04:00
|
|
|
if (TimeLimit > 0)
|
|
|
|
|
{
|
|
|
|
|
SetActorTickEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bIsRunning = true;
|
2014-06-09 11:13:04 -04:00
|
|
|
|
|
|
|
|
GoToObservationPoint();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
OnTestStart.Broadcast();
|
2014-04-23 19:29:53 -04:00
|
|
|
|
|
|
|
|
return true;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AFunctionalTest::FinishTest(TEnumAsByte<EFunctionalTestResult::Type> TestResult, const FString& Message)
|
|
|
|
|
{
|
|
|
|
|
const static UEnum* FTestResultTypeEnum = FindObject<UEnum>( NULL, TEXT("FunctionalTesting.FunctionalTest.EFunctionalTestResult") );
|
|
|
|
|
|
2014-06-09 11:13:04 -04:00
|
|
|
if (bIsRunning == false)
|
|
|
|
|
{
|
|
|
|
|
// ignore
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
bIsRunning = false;
|
|
|
|
|
SetActorTickEnabled(false);
|
|
|
|
|
|
|
|
|
|
OnTestFinished.Broadcast();
|
|
|
|
|
|
|
|
|
|
AActor** ActorToDestroy = AutoDestroyActors.GetTypedData();
|
|
|
|
|
|
|
|
|
|
for (int32 ActorIndex = 0; ActorIndex < AutoDestroyActors.Num(); ++ActorIndex, ++ActorToDestroy)
|
|
|
|
|
{
|
|
|
|
|
if (*ActorToDestroy != NULL)
|
|
|
|
|
{
|
|
|
|
|
// will be removed next frame
|
|
|
|
|
(*ActorToDestroy)->SetLifeSpan( 0.01f );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FText ResultText = FTestResultTypeEnum->GetEnumText( TestResult.GetValue() );
|
|
|
|
|
const FString OutMessage = FString::Printf(TEXT("%s> Result: %s> %s")
|
|
|
|
|
, *GetActorLabel()
|
|
|
|
|
, *ResultText.ToString()
|
|
|
|
|
, Message.IsEmpty() == false ? *Message : TEXT("Test finished") );
|
2014-06-06 06:27:44 -04:00
|
|
|
const FString AdditionalDetails = GetAdditionalTestFinishedMessage(TestResult) + FString::Printf(TEXT(", time %.2fs"), TotalTime);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
AutoDestroyActors.Reset();
|
|
|
|
|
|
|
|
|
|
EMessageSeverity::Type MessageLogSeverity = EMessageSeverity::Info;
|
|
|
|
|
|
|
|
|
|
switch (TestResult.GetValue())
|
|
|
|
|
{
|
|
|
|
|
case EFunctionalTestResult::Invalid:
|
|
|
|
|
case EFunctionalTestResult::Error:
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Error, TEXT("%s"), *OutMessage);
|
|
|
|
|
MessageLogSeverity = EMessageSeverity::Error;
|
|
|
|
|
break;
|
|
|
|
|
case EFunctionalTestResult::Running:
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Warning, TEXT("%s"), *OutMessage);
|
|
|
|
|
MessageLogSeverity = EMessageSeverity::Warning;
|
|
|
|
|
break;
|
|
|
|
|
case EFunctionalTestResult::Failed:
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Error, TEXT("%s"), *OutMessage);
|
|
|
|
|
MessageLogSeverity = EMessageSeverity::Error;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Log, TEXT("%s"), *OutMessage);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-16 09:55:19 -04:00
|
|
|
TSharedRef<FTokenizedMessage> LogMessage = FTokenizedMessage::Create(MessageLogSeverity, FText::FromString(GetActorLabel()))
|
2014-04-23 19:29:53 -04:00
|
|
|
->AddToken(FTextToken::Create(ResultText))
|
|
|
|
|
->AddToken(FTextToken::Create(FText::FromString(Message)))
|
|
|
|
|
->AddToken(FTextToken::Create(FText::FromString(AdditionalDetails)))
|
|
|
|
|
->AddToken(FTextToken::Create(FText::FromString(FailureMessage)));
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-06-16 09:55:19 -04:00
|
|
|
switch (MessageLogSeverity)
|
|
|
|
|
{
|
|
|
|
|
case EMessageSeverity::Error:
|
|
|
|
|
UFunctionalTestingManager::AddError(LogMessage->ToText());
|
|
|
|
|
break;
|
|
|
|
|
case EMessageSeverity::Warning:
|
|
|
|
|
UFunctionalTestingManager::AddWarning(LogMessage->ToText());
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
UFunctionalTestingManager::AddLogItem(LogMessage->ToText());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
TestFinishedObserver.ExecuteIfBound(this);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
void AFunctionalTest::CleanUp()
|
|
|
|
|
{
|
|
|
|
|
FailureMessage = TEXT("");
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
//@todo add "warning" level here
|
|
|
|
|
void AFunctionalTest::LogMessage(const FString& Message)
|
|
|
|
|
{
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Warning
|
|
|
|
|
, TEXT("%s> %s")
|
|
|
|
|
, *GetActorLabel(), *Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AFunctionalTest::SetTimeLimit(float InTimeLimit, TEnumAsByte<EFunctionalTestResult::Type> InResult)
|
|
|
|
|
{
|
|
|
|
|
if (InTimeLimit < 0.f)
|
|
|
|
|
{
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Warning
|
|
|
|
|
, TEXT("%s> Trying to set TimeLimit to less than 0. Falling back to 0 (infinite).")
|
|
|
|
|
, *GetActorLabel());
|
|
|
|
|
|
|
|
|
|
InTimeLimit = 0.f;
|
|
|
|
|
}
|
|
|
|
|
TimeLimit = InTimeLimit;
|
|
|
|
|
|
|
|
|
|
if (InResult == EFunctionalTestResult::Invalid)
|
|
|
|
|
{
|
|
|
|
|
UE_VLOG(this, LogFunctionalTest, Warning
|
|
|
|
|
, TEXT("%s> Trying to set test Result to \'Invalid\'. Falling back to \'Failed\'")
|
|
|
|
|
, *GetActorLabel());
|
|
|
|
|
|
2014-05-12 08:42:24 -04:00
|
|
|
InResult = EFunctionalTestResult::Failed;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
TimesUpResult = InResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AFunctionalTest::RegisterAutoDestroyActor(AActor* ActorToAutoDestroy)
|
|
|
|
|
{
|
|
|
|
|
AutoDestroyActors.AddUnique(ActorToAutoDestroy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
|
|
|
|
|
void AFunctionalTest::PostEditChangeProperty( struct FPropertyChangedEvent& PropertyChangedEvent)
|
|
|
|
|
{
|
|
|
|
|
static const FName NAME_FunctionalTesting = FName(TEXT("FunctionalTesting"));
|
|
|
|
|
static const FName NAME_TimeLimit = FName(TEXT("TimeLimit"));
|
|
|
|
|
static const FName NAME_TimesUpResult = FName(TEXT("TimesUpResult"));
|
|
|
|
|
|
|
|
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
|
|
|
|
|
|
if (PropertyChangedEvent.Property != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (FObjectEditorUtils::GetCategoryFName(PropertyChangedEvent.Property) == NAME_FunctionalTesting)
|
|
|
|
|
{
|
|
|
|
|
// first validate new data since there are some dependencies
|
|
|
|
|
if (PropertyChangedEvent.Property->GetFName() == NAME_TimeLimit)
|
|
|
|
|
{
|
|
|
|
|
if (TimeLimit < 0.f)
|
|
|
|
|
{
|
|
|
|
|
TimeLimit = 0.f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (PropertyChangedEvent.Property->GetFName() == NAME_TimesUpResult)
|
|
|
|
|
{
|
|
|
|
|
if (TimesUpResult == EFunctionalTestResult::Invalid)
|
|
|
|
|
{
|
|
|
|
|
TimesUpResult = EFunctionalTestResult::Failed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
#endif // WITH_EDITOR
|
2014-06-09 11:13:04 -04:00
|
|
|
|
|
|
|
|
void AFunctionalTest::GoToObservationPoint()
|
|
|
|
|
{
|
|
|
|
|
if (ObservationPoint == NULL)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (World)
|
|
|
|
|
{
|
|
|
|
|
APlayerController* PC = World->GetFirstPlayerController();
|
|
|
|
|
if (PC && PC->GetPawn())
|
|
|
|
|
{
|
|
|
|
|
PC->GetPawn()->TeleportTo(ObservationPoint->GetActorLocation(), ObservationPoint->GetActorRotation());
|
|
|
|
|
PC->SetControlRotation(ObservationPoint->GetActorRotation());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|