2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-08-31 02:05:44 -04:00
# include "PrivatePCH.h"
# include "RequiredProgramMainCPPInclude.h"
2015-03-14 04:00:19 -04:00
# include "TestDirectoryWatcher.h"
2014-08-31 02:05:44 -04:00
DEFINE_LOG_CATEGORY ( LogTestPAL ) ;
IMPLEMENT_APPLICATION ( TestPAL , " TestPAL " ) ;
2014-12-11 03:08:58 -05:00
namespace TestPAL
2014-08-31 02:05:44 -04:00
{
2014-12-11 03:08:58 -05:00
FString CommandLine ;
} ;
2014-08-31 02:05:44 -04:00
2014-12-11 03:08:58 -05:00
/**
* FProcHandle test ( child instance )
*/
int32 ProcRunAsChild ( const TCHAR * CommandLine )
2014-08-31 02:05:44 -04:00
{
FPlatformMisc : : SetCrashHandler ( NULL ) ;
FPlatformMisc : : SetGracefulTerminationHandler ( ) ;
GEngineLoop . PreInit ( CommandLine ) ;
// set a random delay pretending to do some useful work up to a minute.
2015-03-11 20:10:19 -04:00
srand ( FPlatformProcess : : GetCurrentProcessId ( ) ) ;
double RandomWorkTime = FMath : : FRandRange ( 0.0f , 6.0f ) ;
2014-08-31 02:05:44 -04:00
2014-12-11 03:08:58 -05:00
UE_LOG ( LogTestPAL , Display , TEXT ( " Running proc test as child (pid %d), will be doing work for %f seconds. " ) , FPlatformProcess : : GetCurrentProcessId ( ) , RandomWorkTime ) ;
2014-08-31 02:05:44 -04:00
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 ;
}
2014-12-11 03:08:58 -05:00
/**
* FProcHandle test ( parent instance )
*/
int32 ProcRunAsParent ( const TCHAR * CommandLine )
2014-08-31 02:05:44 -04:00
{
FPlatformMisc : : SetCrashHandler ( NULL ) ;
FPlatformMisc : : SetGracefulTerminationHandler ( ) ;
GEngineLoop . PreInit ( CommandLine ) ;
2014-12-11 03:08:58 -05:00
UE_LOG ( LogTestPAL , Display , TEXT ( " Running proc test as parent. " ) ) ;
2014-08-31 02:05:44 -04:00
// 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 ;
}
2014-12-11 03:08:58 -05:00
/**
* 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 ;
}
2015-02-06 18:12:42 -05:00
/**
* 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 ;
}
2015-03-23 12:51:12 -04:00
/**
* * * * * * * * * * * * * Thread singleton test * * * * * * * * * * * * * * * * *
*/
/**
* Per - thread singleton
*/
struct FPerThreadTestSingleton : public TThreadSingleton < FPerThreadTestSingleton >
{
FPerThreadTestSingleton ( )
{
UE_LOG ( LogTestPAL , Log , TEXT ( " FPerThreadTestSingleton (this=%p) created for thread %d " ) ,
this ,
FPlatformTLS : : GetCurrentThreadId ( ) ) ;
}
void DoSomething ( )
{
UE_LOG ( LogTestPAL , Log , TEXT ( " Thread %d is about to quit " ) , FPlatformTLS : : GetCurrentThreadId ( ) ) ;
}
virtual ~ FPerThreadTestSingleton ( )
{
UE_LOG ( LogTestPAL , Log , TEXT ( " FPerThreadTestSingleton (%p) destroyed for thread %d " ) ,
this ,
FPlatformTLS : : GetCurrentThreadId ( ) ) ;
}
} ;
//DECLARE_THREAD_SINGLETON( FPerThreadTestSingleton );
/**
* Thread runnable
*/
struct FSingletonTestingThread : public FRunnable
{
virtual uint32 Run ( )
{
FPerThreadTestSingleton & Dummy = FPerThreadTestSingleton : : Get ( ) ;
FPlatformProcess : : Sleep ( 3.0f ) ;
Dummy . DoSomething ( ) ;
return 0 ;
}
} ;
/**
* Thread singleton test
*/
int32 ThreadSingletonTest ( const TCHAR * CommandLine )
{
FPlatformMisc : : SetCrashHandler ( NULL ) ;
FPlatformMisc : : SetGracefulTerminationHandler ( ) ;
GEngineLoop . PreInit ( CommandLine ) ;
UE_LOG ( LogTestPAL , Display , TEXT ( " Running thread singleton test. " ) ) ;
const int kNumTestThreads = 10 ;
FSingletonTestingThread * RunnableArray [ kNumTestThreads ] = { nullptr } ;
FRunnableThread * ThreadArray [ kNumTestThreads ] = { nullptr } ;
// start all threads
for ( int Idx = 0 ; Idx < kNumTestThreads ; + + Idx )
{
RunnableArray [ Idx ] = new FSingletonTestingThread ( ) ;
ThreadArray [ Idx ] = FRunnableThread : : Create ( RunnableArray [ Idx ] ,
* FString : : Printf ( TEXT ( " TestThread%d " ) , Idx ) ) ;
}
GLog - > FlushThreadedLogs ( ) ;
GLog - > Flush ( ) ;
// join all threads
for ( int Idx = 0 ; Idx < kNumTestThreads ; + + Idx )
{
ThreadArray [ Idx ] - > WaitForCompletion ( ) ;
delete ThreadArray [ Idx ] ;
ThreadArray [ Idx ] = nullptr ;
delete RunnableArray [ Idx ] ;
RunnableArray [ Idx ] = nullptr ;
}
FEngineLoop : : AppPreExit ( ) ;
FEngineLoop : : AppExit ( ) ;
return 0 ;
}
2014-12-11 03:08:58 -05:00
/**
* 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 ) ;
}
2015-02-06 18:12:42 -05:00
else if ( ! FCStringAnsi : : Strcmp ( ArgV [ IdxArg ] , ARG_MESSAGEBOX_TEST ) )
{
return MessageBoxTest ( * TestPAL : : CommandLine ) ;
}
2015-03-14 04:00:19 -04:00
else if ( ! FCStringAnsi : : Strcmp ( ArgV [ IdxArg ] , ARG_DIRECTORY_WATCHER_TEST ) )
{
return DirectoryWatcherTest ( * TestPAL : : CommandLine ) ;
}
2015-03-23 12:51:12 -04:00
else if ( ! FCStringAnsi : : Strcmp ( ArgV [ IdxArg ] , ARG_THREAD_SINGLETON_TEST ) )
{
return ThreadSingletonTest ( * TestPAL : : CommandLine ) ;
}
2014-12-11 03:08:58 -05:00
}
FPlatformMisc : : SetCrashHandler ( NULL ) ;
FPlatformMisc : : SetGracefulTerminationHandler ( ) ;
GEngineLoop . PreInit ( * TestPAL : : CommandLine ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " Unable to find any known test name, no test started. " ) ) ;
2015-03-14 04:00:19 -04:00
UE_LOG ( LogTestPAL , Warning , TEXT ( " " ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " Available test cases: " ) ) ;
2015-03-24 08:07:26 -04:00
UE_LOG ( LogTestPAL , Warning , TEXT ( " %s: test process handling API " ) , ANSI_TO_TCHAR ( ARG_PROC_TEST ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " %s: test case-insensitive file operations " ) , ANSI_TO_TCHAR ( ARG_CASE_SENSITIVITY_TEST ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " %s: test message box bug (too long strings) " ) , ANSI_TO_TCHAR ( ARG_MESSAGEBOX_TEST ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " %s: test directory watcher " ) , ANSI_TO_TCHAR ( ARG_DIRECTORY_WATCHER_TEST ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " %s: test per-thread singletons " ) , ANSI_TO_TCHAR ( ARG_THREAD_SINGLETON_TEST ) ) ;
2015-03-14 04:00:19 -04:00
UE_LOG ( LogTestPAL , Warning , TEXT ( " " ) ) ;
UE_LOG ( LogTestPAL , Warning , TEXT ( " Pass one of those to run an appropriate test. " ) ) ;
2014-12-11 03:08:58 -05:00
FEngineLoop : : AppPreExit ( ) ;
FEngineLoop : : AppExit ( ) ;
return 1 ;
}
2014-08-31 02:05:44 -04:00
int32 main ( int32 ArgC , char * ArgV [ ] )
{
2014-12-11 03:08:58 -05:00
TestPAL : : CommandLine = TEXT ( " " ) ;
2014-08-31 02:05:44 -04:00
for ( int32 Option = 1 ; Option < ArgC ; Option + + )
{
2014-12-11 03:08:58 -05:00
TestPAL : : CommandLine + = TEXT ( " " ) ;
2014-08-31 02:05:44 -04:00
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 ) ;
}
}
2014-12-11 03:08:58 -05:00
TestPAL : : CommandLine + = Argument ;
2014-08-31 02:05:44 -04:00
}
2014-12-11 03:08:58 -05:00
return MultiplexedMain ( ArgC , ArgV ) ;
2014-08-31 02:05:44 -04:00
}