SmartPointer<ParameterizedCommand> RegistryPersistence::ReadParameters(
    const SmartPointer<IConfigurationElement>& configurationElement,
    QList<SmartPointer<IStatus> >& warningsToLog,
    const SmartPointer<Command>& command)
{
  const QList<IConfigurationElement::Pointer> parameterElements = configurationElement
      ->GetChildren(TAG_PARAMETER);
  if (parameterElements.isEmpty())
  {
    ParameterizedCommand::Pointer result(new ParameterizedCommand(command, QList<Parameterization>()));
    return result;
  }

  QList<Parameterization> parameters;
  foreach (const IConfigurationElement::Pointer& parameterElement, parameterElements)
  {
    // Read out the id.
    const QString id = parameterElement->GetAttribute(ATT_ID);
    if (id.isEmpty())
    {
      // The id should never be null. This is invalid.
      AddWarning(warningsToLog, "Parameters need an id", configurationElement);
      continue;
    }

    // Find the parameter on the command.
    IParameter::Pointer parameter;
    try
    {
      const QList<IParameter::Pointer> commandParameters = command->GetParameters();
      foreach (const IParameter::Pointer& currentParameter, commandParameters)
      {
        if (currentParameter->GetId() == id)
        {
          parameter = currentParameter;
          break;
        }
      }
    }
    catch (const NotDefinedException& /*e*/)
    {
      // This should not happen.
    }
    if (parameter.IsNull())
    {
      // The name should never be null. This is invalid.
      AddWarning(warningsToLog, "Could not find a matching parameter",
                 configurationElement, id);
      continue;
    }

    // Read out the value.
    const QString value = parameterElement->GetAttribute(ATT_VALUE);
    if (value.isEmpty())
    {
      // The name should never be null. This is invalid.
      AddWarning(warningsToLog, "Parameters need a value",
                 configurationElement, id);
      continue;
    }

    parameters.push_back(Parameterization(parameter, value));
  }

  if (parameters.isEmpty())
  {
    ParameterizedCommand::Pointer result(new ParameterizedCommand(command, QList<Parameterization>()));
    return result;
  }

  ParameterizedCommand::Pointer result(new ParameterizedCommand(command, parameters));
  return result;
}
bool UFunctionalTestingManager::RunFirstValidTest()
{
	bool bTestSuccessfullyTriggered = false;

	if (TestReproStrings.Num() > 0)
	{
		UWorld* World = GetWorld();
		UObject* TestsOuter = World ? (UObject*)(World->PersistentLevel) : (UObject*)(ANY_PACKAGE);

		while (TestReproStrings.Num() > 0)
		{
			TArray<FString> TestParams;
			const FString SingleTestReproString = TestReproStrings.Pop(/*bAllowShrinking=*/false);
			SingleTestReproString.ParseIntoArray(&TestParams, TEXT("#"), /*InCullEmpty=*/true);
			
			if (TestParams.Num() == 0)
			{
				AddWarning(FText::FromString(FString::Printf(TEXT("Unable to parse \'%s\'"), *SingleTestReproString)));
				continue;
			}
			// first param is the test name. Look for it		
			const FString TestName = TestParams[0];
			TestParams.RemoveAt(0, 1, /*bAllowShrinking=*/false);
			AFunctionalTest* TestToRun = FindObject<AFunctionalTest>(TestsOuter, *TestName);			
			if (TestToRun)
			{
				TestToRun->TestFinishedObserver = TestFinishedObserver;
				if (TestToRun->StartTest(TestParams))
				{
					bTestSuccessfullyTriggered = true;
					break;
				}
				else
				{
					AddWarning(FText::FromString(FString::Printf(TEXT("Test \'%s\' failed to start"), *TestToRun->GetName())));
				}
			}
			else
			{
				AddWarning(FText::FromString(FString::Printf(TEXT("Unable to find test \'%s\'"), *TestName)));
			}
		}
	}
	
	if (bTestSuccessfullyTriggered == false)
	{
		for (int32 Index = TestsLeft.Num()-1; Index >= 0; --Index)
		{
			bool bRemove = TestsLeft[Index] == NULL;
			if (TestsLeft[Index] != NULL)
			{
				ensure(TestsLeft[Index]->bIsEnabled);
				TestsLeft[Index]->TestFinishedObserver = TestFinishedObserver;
				if (TestsLeft[Index]->StartTest())
				{
					bTestSuccessfullyTriggered = true;
					break;
				}
				else
				{
					AddWarning(FText::FromString(FString::Printf(TEXT("Test: %s failed to start"), *TestsLeft[Index]->GetName())));
					bRemove = true;
				}
			}

			if (bRemove)
			{
				TestsLeft.RemoveAtSwap(Index, 1, false);
			}
		}
	}

	return bTestSuccessfullyTriggered;
}
/** 
 * Runs compile-on-load test against all unloaded, and optionally loaded, blueprints
 * See the TestAllBlueprints config key in the [Automation.Blueprint] config sections
 */
bool FBlueprintCompileOnLoadTest::RunTest(const FString& BlueprintAssetPath)
{
	FCompilerResultsLog Results;

	UBlueprint* ExistingBP = nullptr;
	// if this blueprint was already loaded, then these tests are invalidated 
	// (because dependencies have already been loaded)
	if (FBlueprintAutomationTestUtilities::IsBlueprintLoaded(BlueprintAssetPath, &ExistingBP))
	{
		if (FBlueprintAutomationTestUtilities::IsAssetUnsaved(BlueprintAssetPath))
		{
			AddError(FString::Printf(TEXT("You have unsaved changes made to '%s', please save them before running this test."), *BlueprintAssetPath));
			return false;
		}
		else
		{
			AddWarning(FString::Printf(TEXT("Test may be invalid (the blueprint is already loaded): '%s'"), *BlueprintAssetPath));
			FBlueprintAutomationTestUtilities::UnloadBlueprint(ExistingBP);
		}
	}

	// tracks blueprints that were already loaded (and cleans up any that were 
	// loaded in its lifetime, once it is destroyed)
	FScopedBlueprintUnloader NewBlueprintUnloader(/*bAutoOpenScope =*/true, /*bRunGCOnCloseIn =*/true);

	// We load the blueprint twice and compare the two for discrepancies. This is 
	// to bring dependency load issues to light (among other things). If a blueprint's
	// dependencies are loaded too late, then this first object is the degenerate one.
	UBlueprint* InitialBlueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *BlueprintAssetPath));

	// if we failed to load it the first time, then there is no need to make a 
	// second attempt, leave them to fix up this issue first
	if (InitialBlueprint == NULL)
	{
		AddError(*FString::Printf(TEXT("Unable to load blueprint for: '%s'"), *BlueprintAssetPath));
		return false;
	}

	if (!InitialBlueprint->SkeletonGeneratedClass || !InitialBlueprint->GeneratedClass)
	{
		AddError(*FString::Printf(TEXT("Unable to load blueprint for: '%s'. Probably it derives from an invalid class."), *BlueprintAssetPath));
		return false;
	}

	// GATHER SUBOBJECTS
	TArray<TWeakObjectPtr<UObject>> InitialBlueprintSubobjects;
	{
		TArray<UObject*> InitialBlueprintSubobjectsPtr;
		GetObjectsWithOuter(InitialBlueprint, InitialBlueprintSubobjectsPtr);
		for (auto Obj : InitialBlueprintSubobjectsPtr)
		{
			InitialBlueprintSubobjects.Add(Obj);
		}
	}

	// GATHER DEPENDENCIES
	TSet<TWeakObjectPtr<UBlueprint>> BlueprintDependencies;
	{
		TArray<UBlueprint*> DependentBlueprints;
		FBlueprintEditorUtils::GetDependentBlueprints(InitialBlueprint, DependentBlueprints);
		for (auto BP : DependentBlueprints)
		{
			BlueprintDependencies.Add(BP);
		}
	}
	BlueprintDependencies.Add(InitialBlueprint);

	// GATHER DEPENDENCIES PERSISTENT DATA
	struct FReplaceInnerData
	{
		TWeakObjectPtr<UClass> Class;
		FStringAssetReference BlueprintAsset;
	};
	TArray<FReplaceInnerData> ReplaceInnerData;
	for (auto BPToUnloadWP : BlueprintDependencies)
	{
		auto BPToUnload = BPToUnloadWP.Get();
		auto OldClass = BPToUnload ? *BPToUnload->GeneratedClass : NULL;
		if (OldClass)
		{
			FReplaceInnerData Data;
			Data.Class = OldClass;
			Data.BlueprintAsset = FStringAssetReference(BPToUnload);
			ReplaceInnerData.Add(Data);
		}
	}

	// store off data for the initial blueprint so we can unload it (and reconstruct 
	// later to compare it with a second one)
	TArray<uint8> InitialLoadData;
	FObjectWriter(InitialBlueprint, InitialLoadData);

	// grab the name before we unload the blueprint
	FName const BlueprintName = InitialBlueprint->GetFName();
	// unload the blueprint so we can reload it (to catch any differences, now  
	// that all its dependencies should be loaded as well)

	//UNLOAD DEPENDENCIES, all circular dependencies will be loaded again 
	// unload the blueprint so we can reload it (to catch any differences, now  
	// that all its dependencies should be loaded as well)
	for (auto BPToUnloadWP : BlueprintDependencies)
	{
		if (auto BPToUnload = BPToUnloadWP.Get())
		{
			FBlueprintAutomationTestUtilities::UnloadBlueprint(BPToUnload);
		}
	}

	// this blueprint is now dead (will be destroyed next garbage-collection pass)
	UBlueprint* UnloadedBlueprint = InitialBlueprint;
	InitialBlueprint = NULL;

	// load the blueprint a second time; if the two separately loaded blueprints 
	// are different, then this one is most likely the choice one (it has all its 
	// dependencies loaded)

	UBlueprint* ReloadedBlueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *BlueprintAssetPath));

	UPackage* TransientPackage = GetTransientPackage();
	FName ReconstructedName = MakeUniqueObjectName(TransientPackage, UBlueprint::StaticClass(), BlueprintName);
	// reconstruct the initial blueprint (using the serialized data from its initial load)
	EObjectFlags const StandardBlueprintFlags = RF_Public | RF_Standalone | RF_Transactional;
	InitialBlueprint = ConstructObject<UBlueprint>(UBlueprint::StaticClass(), TransientPackage, ReconstructedName, StandardBlueprintFlags | RF_Transient);
	FObjectReader(InitialBlueprint, InitialLoadData);
	{
		TMap<UObject*, UObject*> ClassRedirects;
		for (auto& Data : ReplaceInnerData)
		{
			UClass* OriginalClass = Data.Class.Get();
			UBlueprint* NewBlueprint = Cast<UBlueprint>(Data.BlueprintAsset.ResolveObject());
			UClass* NewClass = NewBlueprint ? *NewBlueprint->GeneratedClass : NULL;
			if (OriginalClass && NewClass)
			{
				ClassRedirects.Add(OriginalClass, NewClass);
			}
		}
		// REPLACE OLD DATA
		FArchiveReplaceObjectRef<UObject>(InitialBlueprint, ClassRedirects, /*bNullPrivateRefs=*/false, /*bIgnoreOuterRef=*/true, /*bIgnoreArchetypeRef=*/false);
		for (auto SubobjWP : InitialBlueprintSubobjects)
		{
			if (auto Subobj = SubobjWP.Get())
			{
				FArchiveReplaceObjectRef<UObject>(Subobj, ClassRedirects, /*bNullPrivateRefs=*/false, /*bIgnoreOuterRef=*/true, /*bIgnoreArchetypeRef=*/false);
			}
		}

		UPackage* AssetPackage = ReloadedBlueprint->GetOutermost();
		bool bHasUnsavedChanges = AssetPackage->IsDirty();
		FBlueprintEditorUtils::RefreshAllNodes(ReloadedBlueprint);
		AssetPackage->SetDirtyFlag(bHasUnsavedChanges);
	}

	// look for diffs between subsequent loads and log them as errors
	TArray<FDiffSingleResult> BlueprintDiffs;
	bool bDiffsFound = FBlueprintAutomationTestUtilities::DiffBlueprints(InitialBlueprint, ReloadedBlueprint, BlueprintDiffs);
	if (bDiffsFound)
	{
		FBlueprintAutomationTestUtilities::ResolveCircularDependencyDiffs(ReloadedBlueprint, BlueprintDiffs);
		// if there are still diffs after resolving any the could have been from unloaded circular dependencies
		if (BlueprintDiffs.Num() > 0)
		{
			AddError(FString::Printf(TEXT("Inconsistencies between subsequent blueprint loads for: '%s' (was a dependency not preloaded?)"), *BlueprintAssetPath));
		}
		else 
		{
			bDiffsFound = false;
		}
		
		// list all the differences (so as to help identify what dependency was missing)
		for (auto DiffIt(BlueprintDiffs.CreateIterator()); DiffIt; ++DiffIt)
		{
			// will be presented in the context of "what changed between the initial load and the second?"
			FString DiffDescription = DiffIt->ToolTip;
			if (DiffDescription != DiffIt->DisplayString)
			{
				DiffDescription = FString::Printf(TEXT("%s (%s)"), *DiffDescription, *DiffIt->DisplayString);
			}

			const UEdGraphNode* NodeFromPin = DiffIt->Pin1 ? Cast<const UEdGraphNode>(DiffIt->Pin1->GetOuter()) : NULL;
			const UEdGraphNode* Node = DiffIt->Node1 ? DiffIt->Node1 : NodeFromPin;
			const UEdGraph* Graph = Node ? Node->GetGraph() : NULL;
			const FString GraphName = Graph ? Graph->GetName() : FString(TEXT("Unknown Graph"));
			AddError(FString::Printf(TEXT("%s.%s differs between subsequent loads: %s"), *BlueprintName.ToString(), *GraphName, *DiffDescription));
		}
	}

	// At the close of this function, the FScopedBlueprintUnloader should prep 
	// for following tests by unloading any blueprint dependencies that were 
	// loaded for this one (should catch InitialBlueprint and ReloadedBlueprint) 
	// 
	// The FScopedBlueprintUnloader should also run garbage-collection after,
	// in hopes that the imports for this blueprint get destroyed so that they 
	// don't invalidate other tests that share the same dependencies
	return !bDiffsFound;
}
bool FDateTimeFormattingRulesTest::RunTest (const FString& Parameters)
{
#if UE_ENABLE_ICU
	FInternationalization& I18N = FInternationalization::Get();

	const FString OriginalCulture = I18N.GetCurrentCulture()->GetName();

	const FDateTime UnixEpoch = FDateTime::FromUnixTimestamp(0);
	const FDateTime UnixBillennium = FDateTime::FromUnixTimestamp(1000000000);
	const FDateTime UnixOnes = FDateTime::FromUnixTimestamp(1111111111);
	const FDateTime UnixDecimalSequence = FDateTime::FromUnixTimestamp(1234567890);
	const FDateTime TestDateTime( 1990, 6, 13, 12, 34, 56, 789 );

	if (I18N.SetCurrentCulture("en-US"))
	{
		// Unix Time Values via Date Time
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("1/1/70, 12:00 AM") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("Jan 1, 1970, 12:00:00 AM") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("January 1, 1970 at 12:00:00 AM GMT") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("Thursday, January 1, 1970 at 12:00:00 AM GMT") ) );

		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("9/9/01, 1:46 AM") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("Sep 9, 2001, 1:46:40 AM") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("September 9, 2001 at 1:46:40 AM GMT") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("Sunday, September 9, 2001 at 1:46:40 AM GMT") ) );

		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("3/18/05, 1:58 AM") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("Mar 18, 2005, 1:58:31 AM") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("March 18, 2005 at 1:58:31 AM GMT") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("Friday, March 18, 2005 at 1:58:31 AM GMT") ) );

		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("2/13/09, 11:31 PM") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("Feb 13, 2009, 11:31:30 PM") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("February 13, 2009 at 11:31:30 PM GMT") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("Friday, February 13, 2009 at 11:31:30 PM GMT") ) );

		// Date Time
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Short,EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("6/13/90, 12:34 PM") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("Jun 13, 1990, 12:34:56 PM") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("June 13, 1990 at 12:34:56 PM GMT") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("Wednesday, June 13, 1990 at 12:34:56 PM GMT") ) );
	}
	else
	{
		AddWarning(FString::Printf(TEXT("Internationalization data for %s missing - test is partially disabled."), TEXT("en-US")));
	}

	if (I18N.SetCurrentCulture("ja-JP"))
	{
		// Unix Time Values via Date Time
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("1970/01/01 0:00") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("1970/01/01 0:00:00") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("1970\x5E74") TEXT("1\x6708") TEXT("1\x65E5") TEXT(" 0:00:00 GMT") ) );
		Test( this, TEXT("Testing Unix Epoch"), FText::AsDateTime(UnixEpoch, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("1970\x5E74") TEXT("1\x6708") TEXT("1\x65E5\x6728\x66DC\x65E5") TEXT(" ") TEXT("0\x6642") TEXT("00\x5206") TEXT("00\x79D2") TEXT(" GMT") ) );

		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("2001/09/09 1:46") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("2001/09/09 1:46:40") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("2001\x5E74") TEXT("9\x6708") TEXT("9\x65E5") TEXT(" 1:46:40 GMT") ) );
		Test( this, TEXT("Testing Unix Billennium"), FText::AsDateTime(UnixBillennium, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("2001\x5E74") TEXT("9\x6708") TEXT("9\x65E5\x65E5\x66DC\x65E5") TEXT(" ") TEXT("1\x6642") TEXT("46\x5206") TEXT("40\x79D2") TEXT(" GMT") ) );

		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("2005/03/18 1:58") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("2005/03/18 1:58:31") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("2005\x5E74") TEXT("3\x6708") TEXT("18\x65E5") TEXT(" 1:58:31 GMT") ) );
		Test( this, TEXT("Testing Unix Ones"), FText::AsDateTime(UnixOnes, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("2005\x5E74") TEXT("3\x6708") TEXT("18\x65E5\x91D1\x66DC\x65E5") TEXT(" ") TEXT("1\x6642") TEXT("58\x5206") TEXT("31\x79D2") TEXT(" GMT") ) );

		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Short, EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("2009/02/13 23:31") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("2009/02/13 23:31:30") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("2009\x5E74") TEXT("2\x6708") TEXT("13\x65E5 23:31:30 GMT") ) );
		Test( this, TEXT("Testing Unix Decimal Sequence"), FText::AsDateTime(UnixDecimalSequence, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("2009\x5E74") TEXT("2\x6708") TEXT("13\x65E5\x91D1\x66DC\x65E5") TEXT(" ") TEXT("23\x6642") TEXT("31\x5206") TEXT("30\x79D2") TEXT(" GMT") ) );

		// Date Time
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Short,EDateTimeStyle::Short, "GMT"), FText::FromString( TEXT("1990/06/13 12:34") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Medium, EDateTimeStyle::Medium, "GMT"), FText::FromString( TEXT("1990/06/13 12:34:56") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Long, EDateTimeStyle::Long, "GMT"), FText::FromString( TEXT("1990\x5E74") TEXT("6\x6708") TEXT("13\x65E5") TEXT(" 12:34:56 GMT") ) );
		Test( this, TEXT("Testing Date-Time"), FText::AsDateTime(TestDateTime, EDateTimeStyle::Full, EDateTimeStyle::Full, "GMT"), FText::FromString( TEXT("1990\x5E74") TEXT("6\x6708") TEXT("13\x65E5\x6C34\x66DC\x65E5") TEXT(" ") TEXT("12\x6642") TEXT("34\x5206") TEXT("56\x79D2 GMT") ) );
	}
	else
	{
		AddWarning(FString::Printf(TEXT("Internationalization data for %s missing - test is partially disabled."), TEXT("ja-JP")));
	}

	I18N.SetCurrentCulture(OriginalCulture);
#else
	AddWarning("ICU is disabled thus locale-aware date/time formatting is disabled.");
#endif

	return true;
}
bool FBlueprintRenameAndCloneTest::RunTest(const FString& BlueprintAssetPath)
{
	bool bTestFailed = false;
	if (FBlueprintAutomationTestUtilities::IsAssetUnsaved(BlueprintAssetPath))
	{
		bTestFailed = true;
		AddError(FString::Printf(TEXT("You have unsaved changes made to '%s', please save them before running this test."), *BlueprintAssetPath));
	}

	bool bIsAlreadyLoaded = false;
	if (FBlueprintAutomationTestUtilities::IsBlueprintLoaded(BlueprintAssetPath))
	{
		bIsAlreadyLoaded = true;
		AddWarning(FString::Printf(TEXT("'%s' is already loaded, and possibly referenced by external objects (unable to perform rename tests... please run again in an empty map)."), *BlueprintAssetPath));
	}

	// track the loaded blueprint (and any other BP dependencies) so we can 
	// unload them if we end up renaming it.
	FScopedBlueprintUnloader NewBlueprintUnloader(/*bAutoOpenScope =*/true, /*bRunGCOnCloseIn =*/false);

	UBlueprint* const OriginalBlueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *BlueprintAssetPath));
	if (OriginalBlueprint == NULL)
	{
		bTestFailed = true;
		AddError(FString::Printf(TEXT("Failed to load '%s' (has it been renamed?)."), *BlueprintAssetPath));
	}
	if (!OriginalBlueprint->SkeletonGeneratedClass || !OriginalBlueprint->GeneratedClass)
	{
		bTestFailed = true;
		AddError(*FString::Printf(TEXT("Unable to load blueprint for: '%s'. Probably it derives from an invalid class."), *BlueprintAssetPath));
	}
	else if (!bTestFailed)
	{
		// duplicate
		{
			UBlueprint* DuplicateBluprint = FBlueprintAutomationTestUtilities::DuplicateBlueprint(OriginalBlueprint);
			if (!FBlueprintAutomationTestUtilities::TestSaveBlueprint(DuplicateBluprint))
			{
				AddError(FString::Printf(TEXT("Failed to save blueprint after duplication: '%s'"), *BlueprintAssetPath));
				bTestFailed = true;
			}
			FBlueprintAutomationTestUtilities::UnloadBlueprint(DuplicateBluprint);
		}

		// rename
		if (!bIsAlreadyLoaded)
		{
			// store the original package so we can manually invalidate it after the move
			UPackage* const OriginalPackage = Cast<UPackage>(OriginalBlueprint->GetOutermost());

			FString const BlueprintName = OriginalBlueprint->GetName();
			UPackage* TempPackage = FBlueprintAutomationTestUtilities::CreateTempPackage(BlueprintName);

			FString NewName = FString::Printf(TEXT("%s-Rename"), *BlueprintName);
			NewName = MakeUniqueObjectName(TempPackage, OriginalBlueprint->GetClass(), *NewName).ToString();

			OriginalBlueprint->Rename(*NewName, TempPackage, REN_None);

			if (!FBlueprintAutomationTestUtilities::TestSaveBlueprint(OriginalBlueprint))
			{
				AddError(FString::Printf(TEXT("Failed to save blueprint after rename: '%s'"), *BlueprintAssetPath));
				bTestFailed = true;
			}

			// the blueprint has been moved out of this package, invalidate it so 
			// we don't save it in this state and so we can reload the blueprint later
			FBlueprintAutomationTestUtilities::InvalidatePackage(OriginalPackage);

			// need to unload the renamed blueprint (and any other blueprints 
			// that were relying on it), so that the renamed blueprint doesn't get used by the user
			FBlueprintAutomationTestUtilities::UnloadBlueprint(OriginalBlueprint);
			NewBlueprintUnloader.CloseScope();
		}
		else 
		{
			// no need to unload the blueprint or any of its dependencies (since 
			// we didn't muck with it by renaming it) 
			NewBlueprintUnloader.ClearScope();
		}

#if WITH_EDITOR
		// clear undo history to ensure that the transaction buffer isn't 
		// holding onto any references to the blueprints we want unloaded
		GEditor->Trans->Reset(NSLOCTEXT("BpAutomation", "RenameCloneTest", "Rename and Clone Test"));
#endif // #if WITH_EDITOR
		// make sure the unloaded blueprints are properly flushed (for future tests)
		CollectGarbage(RF_Native);		
	}

	return !bTestFailed;
}