/** Opens an input file, trying multiple times if necessary. */
	FArchive* OpenInputFile()
	{
		FArchive* InputFile = nullptr;
		bool bFirstOpenTry = true;
		while(!InputFile && !GIsRequestingExit)
		{
			// Try to open the input file that we are going to process
			if (CommunicationMode == ThroughFile)
			{
				InputFile = IFileManager::Get().CreateFileReader(*InputFilePath,FILEREAD_Silent);
			}
			else
			{
#if PLATFORM_SUPPORTS_NAMED_PIPES
				check(IsUsingNamedPipes()); //UE_LOG(LogShaders, Log, TEXT("Opening Pipe %s\n"), *InputFilePath);
//FPlatformMisc::LowLevelOutputDebugStringf(TEXT("*** Trying to open pipe %s\n"), *InputFilePath);
				if (Pipe.Create(InputFilePath, false, false))
				{
//FPlatformMisc::LowLevelOutputDebugStringf(TEXT("\tOpened!!!\n"));
					// Read the total number of bytes
					int32 TransferSize = 0;
					VerifyResult(Pipe.ReadInt32(TransferSize));

					// Prealloc and read the full buffer
					TransferBufferIn.Empty(TransferSize);
					TransferBufferIn.AddUninitialized(TransferSize);	//UE_LOG(LogShaders, Log, TEXT("Reading Buffer\n"));
					VerifyResult(Pipe.ReadBytes(TransferSize, TransferBufferIn.GetData()));

					return new FMemoryReader(TransferBufferIn);
				}

				double DeltaTime = FPlatformTime::Seconds();
				if (DeltaTime - LastConnectionTime > 20.0f)
				{
					// If can't connect for more than 20 seconds, let's exit
					FPlatformMisc::RequestExit(false);
				}
#endif	// PLATFORM_SUPPORTS_NAMED_PIPES
			}

			if(!InputFile && !bFirstOpenTry)
			{
				CheckExitConditions();
				// Give up CPU time while we are waiting
				FPlatformProcess::Sleep(0.01f);
			}
			bFirstOpenTry = false;
		}
		return InputFile;
	}
Example #2
0
bool ANUTActor::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, FInBunch& Bunch)
{
	bool bHandledMessage = false;

	if (MessageType == NMT_NUTControl)
	{
		uint8 CmdType = 0;
		FString Command;
		FNetControlMessage<NMT_NUTControl>::Receive(Bunch, CmdType, Command);

		// Console command
		if (CmdType == ENUTControlCommand::Command_NoResult || CmdType == ENUTControlCommand::Command_SendResult)
		{
			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Executing command: %s"), *Command);

			FStringOutputDevice CmdResult;
			CmdResult.SetAutoEmitLineTerminator(true);

			bool bCmdSuccess = false;

			bCmdSuccess = GEngine->Exec(GetWorld(), *Command, CmdResult);

			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Command result: %s"), *CmdResult);


			bool bSendResult = CmdType == ENUTControlCommand::Command_SendResult;

			if (bSendResult)
			{
				uint8 ReturnCmdType = (bCmdSuccess ? ENUTControlCommand::CommandResult_Success :
										ENUTControlCommand::CommandResult_Failed);

				FNetControlMessage<NMT_NUTControl>::Send(Connection, ReturnCmdType, CmdResult);
			}
		}
		// Console command result
		else if (CmdType == ENUTControlCommand::CommandResult_Failed || CmdType == ENUTControlCommand::CommandResult_Success)
		{
			bool bCmdSuccess = CmdType == ENUTControlCommand::CommandResult_Success;

			if (bCmdSuccess)
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Got command result:"));
				UE_LOG(LogUnitTest, Log, TEXT("%s"), *Command);
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Failed to execute command"));
			}
		}
		// Ping request
		else if (CmdType == ENUTControlCommand::Ping)
		{
			uint8 TempCmdType = ENUTControlCommand::Pong;
			FString Dud;

			FNetControlMessage<NMT_NUTControl>::Send(Connection, TempCmdType, Dud);
		}
		// Pong reply - this should only be implemented by custom unit tests; hence the assert
		else if (CmdType == ENUTControlCommand::Pong)
		{
			UNIT_ASSERT(false);
		}
		// Custom implemented events, with the result triggered through 'NotifyEvent'
		else if (CmdType == ENUTControlCommand::WatchEvent)
		{
			// NOTE: Only the last NetConnection to request a WatchEvent, will receive notifications
			EventWatcher = Connection;

			// Watch for the end of seamless travel
			if (Command == TEXT("SeamlessTravelEnd"))
			{
				FCoreUObjectDelegates::PostLoadMap.AddStatic(&ANUTActor::NotifyPostLoadMap);
			}
		}
		// Event watch notification - should only be implemented by custom unit tests
		else if (CmdType == ENUTControlCommand::NotifyEvent)
		{
			UNIT_ASSERT(false);
		}
		// Create an actor instance (the 'summon' console command, doesn't work without a cheat manager)
		else if (CmdType == ENUTControlCommand::Summon)
		{
			const TCHAR* Cmd = *Command;
			FString SpawnClassName = FParse::Token(Cmd, false);
			bool bForceBeginPlay = FParse::Param(Cmd, TEXT("ForceBeginPlay"));

			// Hack specifically for getting the GameplayDebugger working - think the mainline code is broken
			bool bGameplayDebuggerHack = FParse::Param(Cmd, TEXT("GameplayDebuggerHack"));

			UClass* SpawnClass = FindObject<UClass>(NULL, *SpawnClassName);

			if (SpawnClass != NULL)
			{
				FActorSpawnParameters SpawnParms;
				SpawnParms.Owner = GetOwner();

				AActor* NewActor = GetWorld()->SpawnActor<AActor>(SpawnClass, SpawnParms);

				if (NewActor != NULL)
				{
					UE_LOG(LogUnitTest, Log, TEXT("Successfully summoned actor of class '%s'"), *SpawnClassName);

					if (bForceBeginPlay && !NewActor->HasActorBegunPlay())
					{
						UE_LOG(LogUnitTest, Log, TEXT("Forcing call to 'BeginPlay' on newly spawned actor."));

						NewActor->BeginPlay();
					}

					if (bGameplayDebuggerHack)
					{
						// Assign the LocalPlayerOwner property, to the PC owning this NUTActor, using reflection (to avoid dependency)
						UObjectProperty* LocalPlayerOwnerProp =
								FindField<UObjectProperty>(NewActor->GetClass(), TEXT("LocalPlayerOwner"));

						if (LocalPlayerOwnerProp != NULL)
						{
							LocalPlayerOwnerProp->SetObjectPropertyValue(
								LocalPlayerOwnerProp->ContainerPtrToValuePtr<UObject*>(NewActor), GetOwner());
						}
						else
						{
							UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to find 'LocalPlayerOwner' property. Unit test broken."));
						}

						// Also hack-disable ticking, so that the replicator doesn't spawn a second replicator
						NewActor->SetActorTickEnabled(false);
					}
				}
				else
				{
					UE_LOG(LogUnitTest, Log, TEXT("SpawnActor failed for class '%s'"), *Command);
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("Could not find actor class '%s'"), *Command);
			}
		}
		// Suspend the game, until a resume request is received (used for giving time, to attach a debugger)
		else if (CmdType == ENUTControlCommand::SuspendProcess)
		{
			UE_LOG(LogUnitTest, Log, TEXT("Suspend start."));


			// Setup a named pipe, to monitor for the resume request
			FString ResumePipeName = FString::Printf(TEXT("%s%u"), NUT_SUSPEND_PIPE, FPlatformProcess::GetCurrentProcessId());
			FPlatformNamedPipe ResumePipe;
			bool bPipeCreated = ResumePipe.Create(ResumePipeName, true, false);

			if (bPipeCreated)
			{
				if (!ResumePipe.OpenConnection())
				{
					UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to open pipe connection."));
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to create resume pipe."));
			}



			// Spin/sleep (effectively suspended) until a resume request is received
			while (true)
			{
				if (bPipeCreated && ResumePipe.IsReadyForRW())
				{
					int32 ResumeVal = 0;

					if (ResumePipe.ReadInt32(ResumeVal) && !!ResumeVal)
					{
						UE_LOG(LogUnitTest, Log, TEXT("Got resume request."));
						break;
					}
				}


				FPlatformProcess::Sleep(1.0f);
			}


			ResumePipe.Destroy();

			UE_LOG(LogUnitTest, Log, TEXT("Suspend end."));
		}

		bHandledMessage = true;
	}

	return bHandledMessage;
}