Files
UnrealEngineUWP/Engine/Source/Programs/TestPAL/Private/Main.cpp
Dmitry Rekman e86138d4ca Refactored FProcHandle API in platform abstraction layer.
- Deprecated FProcHandle::Close() in favor of existing FPlatformProcess::CloseProc() (symmetric to FPlatformProcess::CreateProc()).
- Linux: made FProcHandle instances safe to pass by value.
- Linux: added support for "fire and forget" children, which will not leave zombies (at the expense of extra threads and a leaked thread handle).
- Extended TestPAL with tests for most of the above functionality.

#codereview Michael.Trepka, Josh.Adams, Robert.Manuszewski, Jaroslaw.Surowiec

[CL 2476050 by Dmitry Rekman in Main branch]
2015-03-11 20:10:19 -04:00

208 lines
5.7 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "PrivatePCH.h"
#include "RequiredProgramMainCPPInclude.h"
DEFINE_LOG_CATEGORY(LogTestPAL);
IMPLEMENT_APPLICATION(TestPAL, "TestPAL");
namespace TestPAL
{
FString CommandLine;
};
/**
* FProcHandle test (child instance)
*/
int32 ProcRunAsChild(const TCHAR* CommandLine)
{
FPlatformMisc::SetCrashHandler(NULL);
FPlatformMisc::SetGracefulTerminationHandler();
GEngineLoop.PreInit(CommandLine);
// set a random delay pretending to do some useful work up to a minute.
srand(FPlatformProcess::GetCurrentProcessId());
double RandomWorkTime = FMath::FRandRange(0.0f, 6.0f);
UE_LOG(LogTestPAL, Display, TEXT("Running proc test as child (pid %d), will be doing work for %f seconds."), FPlatformProcess::GetCurrentProcessId(), RandomWorkTime);
double StartTime = FPlatformTime::Seconds();
// Use all the CPU!
for (;;)
{
double CurrentTime = FPlatformTime::Seconds();
if (CurrentTime - StartTime >= RandomWorkTime)
{
break;
}
}
UE_LOG(LogTestPAL, Display, TEXT("Child (pid %d) finished work."), FPlatformProcess::GetCurrentProcessId());
FEngineLoop::AppPreExit();
FEngineLoop::AppExit();
return 0;
}
/**
* FProcHandle test (parent instance)
*/
int32 ProcRunAsParent(const TCHAR* CommandLine)
{
FPlatformMisc::SetCrashHandler(NULL);
FPlatformMisc::SetGracefulTerminationHandler();
GEngineLoop.PreInit(CommandLine);
UE_LOG(LogTestPAL, Display, TEXT("Running proc test as parent."));
// Run slave instance continuously
int NumChildrenToSpawn = 255, MaxAtOnce = 5;
FParent Parent(NumChildrenToSpawn, MaxAtOnce);
Parent.Run();
UE_LOG(LogTestPAL, Display, TEXT("Parent quit."));
FEngineLoop::AppPreExit();
FEngineLoop::AppExit();
return 0;
}
/**
* Tests a single file.
*/
void TestCaseInsensitiveFile(const FString & Filename, const FString & WrongFilename)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
IFileHandle * CreationHandle = PlatformFile.OpenWrite(*Filename);
checkf(CreationHandle, TEXT("Could not create a test file for '%s'"), *Filename);
delete CreationHandle;
IFileHandle* CheckGoodHandle = PlatformFile.OpenRead(*Filename);
checkf(CheckGoodHandle, TEXT("Could not open a test file for '%s' (zero probe)"), *Filename);
delete CheckGoodHandle;
IFileHandle* CheckWrongCaseRelHandle = PlatformFile.OpenRead(*WrongFilename);
checkf(CheckWrongCaseRelHandle, TEXT("Could not open a test file for '%s'"), *WrongFilename);
delete CheckWrongCaseRelHandle;
PlatformFile.DeleteFile(*Filename);
}
/**
* Case-(in)sensitivity test/
*/
int32 CaseTest(const TCHAR* CommandLine)
{
FPlatformMisc::SetCrashHandler(NULL);
FPlatformMisc::SetGracefulTerminationHandler();
GEngineLoop.PreInit(CommandLine);
UE_LOG(LogTestPAL, Display, TEXT("Running case sensitivity test."));
TestCaseInsensitiveFile(TEXT("Test.Test"), TEXT("teSt.teSt"));
FString File(TEXT("Test^%!CaseInsens"));
FString AbsFile = FPaths::ConvertRelativePathToFull(File);
FString AbsFileUpper = AbsFile.ToUpper();
TestCaseInsensitiveFile(AbsFile, AbsFileUpper);
FEngineLoop::AppPreExit();
FEngineLoop::AppExit();
return 0;
}
/**
* Message box test/
*/
int32 MessageBoxTest(const TCHAR* CommandLine)
{
FPlatformMisc::SetCrashHandler(NULL);
FPlatformMisc::SetGracefulTerminationHandler();
GEngineLoop.PreInit(CommandLine);
UE_LOG(LogTestPAL, Display, TEXT("Running message box test."));
FString Display(TEXT("I am a big big string in a big big game, it's not a big big thing if you print me. But I do do feel that I do do will be displayed wrong, displayed wrong... or not."));
FString Caption(TEXT("I am a big big caption in a big big game, it's not a big big thing if you print me. But I do do feel that I do do will be displayed wrong, displayed wrong... or not."));
EAppReturnType::Type Result = FPlatformMisc::MessageBoxExt(EAppMsgType::YesNo, *Display, *Caption);
UE_LOG(LogTestPAL, Display, TEXT("MessageBoxExt result: %d."), static_cast<int32>(Result));
FEngineLoop::AppPreExit();
FEngineLoop::AppExit();
return 0;
}
/**
* Selects and runs one of test cases.
*
* @param ArgC Number of commandline arguments.
* @param ArgV Commandline arguments.
* @return Test case's return code.
*/
int32 MultiplexedMain(int32 ArgC, char* ArgV[])
{
for (int32 IdxArg = 0; IdxArg < ArgC; ++IdxArg)
{
if (!FCStringAnsi::Strcmp(ArgV[IdxArg], ARG_PROC_TEST_CHILD))
{
return ProcRunAsChild(*TestPAL::CommandLine);
}
else if (!FCStringAnsi::Strcmp(ArgV[IdxArg], ARG_PROC_TEST))
{
return ProcRunAsParent(*TestPAL::CommandLine);
}
else if (!FCStringAnsi::Strcmp(ArgV[IdxArg], ARG_CASE_SENSITIVITY_TEST))
{
return CaseTest(*TestPAL::CommandLine);
}
else if (!FCStringAnsi::Strcmp(ArgV[IdxArg], ARG_MESSAGEBOX_TEST))
{
return MessageBoxTest(*TestPAL::CommandLine);
}
}
FPlatformMisc::SetCrashHandler(NULL);
FPlatformMisc::SetGracefulTerminationHandler();
GEngineLoop.PreInit(*TestPAL::CommandLine);
UE_LOG(LogTestPAL, Warning, TEXT("Unable to find any known test name, no test started."));
FEngineLoop::AppPreExit();
FEngineLoop::AppExit();
return 1;
}
int32 main(int32 ArgC, char* ArgV[])
{
TestPAL::CommandLine = TEXT("");
for (int32 Option = 1; Option < ArgC; Option++)
{
TestPAL::CommandLine += TEXT(" ");
FString Argument(ANSI_TO_TCHAR(ArgV[Option]));
if (Argument.Contains(TEXT(" ")))
{
if (Argument.Contains(TEXT("=")))
{
FString ArgName;
FString ArgValue;
Argument.Split( TEXT("="), &ArgName, &ArgValue );
Argument = FString::Printf( TEXT("%s=\"%s\""), *ArgName, *ArgValue );
}
else
{
Argument = FString::Printf(TEXT("\"%s\""), *Argument);
}
}
TestPAL::CommandLine += Argument;
}
return MultiplexedMain(ArgC, ArgV);
}