/** * Helper method to dump the contents of the provided test name to execution info map to the provided feedback context * * @param InContext Context to dump the execution info to * @param InInfoToDump Execution info that should be dumped to the provided feedback context */ void FAutomationTestFramework::DumpAutomationTestExecutionInfo( const TMap<FString, FAutomationTestExecutionInfo>& InInfoToDump ) { const FString SuccessMessage = NSLOCTEXT("UnrealEd", "AutomationTest_Success", "Success").ToString(); const FString FailMessage = NSLOCTEXT("UnrealEd", "AutomationTest_Fail", "Fail").ToString(); for ( TMap<FString, FAutomationTestExecutionInfo>::TConstIterator MapIter(InInfoToDump); MapIter; ++MapIter ) { const FString& CurTestName = MapIter.Key(); const FAutomationTestExecutionInfo& CurExecutionInfo = MapIter.Value(); UE_LOG(LogAutomationTest, Log, TEXT("%s: %s"), *CurTestName, CurExecutionInfo.bSuccessful ? *SuccessMessage : *FailMessage); if ( CurExecutionInfo.Errors.Num() > 0 ) { SET_WARN_COLOR(COLOR_RED); CLEAR_WARN_COLOR(); for ( TArray<FAutomationEvent>::TConstIterator ErrorIter( CurExecutionInfo.Errors ); ErrorIter; ++ErrorIter ) { UE_LOG(LogAutomationTest, Error, TEXT("%s"), *(*ErrorIter).Message); } } if ( CurExecutionInfo.Warnings.Num() > 0 ) { SET_WARN_COLOR(COLOR_YELLOW); CLEAR_WARN_COLOR(); for ( TArray<FString>::TConstIterator WarningIter( CurExecutionInfo.Warnings ); WarningIter; ++WarningIter ) { UE_LOG(LogAutomationTest, Warning, TEXT("%s"), **WarningIter ); } } if ( CurExecutionInfo.LogItems.Num() > 0 ) { //InContext->Logf( *FString::Printf( TEXT("%s"), *NSLOCTEXT("UnrealEd", "AutomationTest_LogItems", "Log Items").ToString() ) ); for ( TArray<FString>::TConstIterator LogItemIter( CurExecutionInfo.LogItems ); LogItemIter; ++LogItemIter ) { UE_LOG(LogAutomationTest, Log, TEXT("%s"), **LogItemIter ); } } //InContext->Logf( TEXT("") ); } }
/** * Nulls out references to a given object * * @param InObject - Object to null references to */ void NullReferencesToObject(UObject* InObject) { TArray<UObject*> ReplaceableObjects; TMap<UObject*, UObject*> ReplacementMap; ReplacementMap.Add(InObject, NULL); ReplacementMap.GenerateKeyArray(ReplaceableObjects); // Find all the properties (and their corresponding objects) that refer to any of the objects to be replaced TMap< UObject*, TArray<UProperty*> > ReferencingPropertiesMap; for (FObjectIterator ObjIter; ObjIter; ++ObjIter) { UObject* CurObject = *ObjIter; // Find the referencers of the objects to be replaced FFindReferencersArchive FindRefsArchive(CurObject, ReplaceableObjects); // Inform the object referencing any of the objects to be replaced about the properties that are being forcefully // changed, and store both the object doing the referencing as well as the properties that were changed in a map (so that // we can correctly call PostEditChange later) TMap<UObject*, int32> CurNumReferencesMap; TMultiMap<UObject*, UProperty*> CurReferencingPropertiesMMap; if (FindRefsArchive.GetReferenceCounts(CurNumReferencesMap, CurReferencingPropertiesMMap) > 0) { TArray<UProperty*> CurReferencedProperties; CurReferencingPropertiesMMap.GenerateValueArray(CurReferencedProperties); ReferencingPropertiesMap.Add(CurObject, CurReferencedProperties); for (TArray<UProperty*>::TConstIterator RefPropIter(CurReferencedProperties); RefPropIter; ++RefPropIter) { CurObject->PreEditChange(*RefPropIter); } } } // Iterate over the map of referencing objects/changed properties, forcefully replacing the references and then // alerting the referencing objects the change has completed via PostEditChange int32 NumObjsReplaced = 0; for (TMap< UObject*, TArray<UProperty*> >::TConstIterator MapIter(ReferencingPropertiesMap); MapIter; ++MapIter) { ++NumObjsReplaced; UObject* CurReplaceObj = MapIter.Key(); const TArray<UProperty*>& RefPropArray = MapIter.Value(); FArchiveReplaceObjectRef<UObject> ReplaceAr(CurReplaceObj, ReplacementMap, false, true, false); for (TArray<UProperty*>::TConstIterator RefPropIter(RefPropArray); RefPropIter; ++RefPropIter) { FPropertyChangedEvent PropertyEvent(*RefPropIter); CurReplaceObj->PostEditChangeProperty(PropertyEvent); } if (!CurReplaceObj->HasAnyFlags(RF_Transient) && CurReplaceObj->GetOutermost() != GetTransientPackage()) { if (!CurReplaceObj->RootPackageHasAnyFlags(PKG_CompiledIn)) { CurReplaceObj->MarkPackageDirty(); } } } }