void TestExtHintFieldCreationL(RFs& theFS) { test.Start(_L("Ext Hint field creation")); serv.CopyFileL(KSrcDatabaseFileName, KDatabaseFileName); serv.CopyFileL(KSrcDatabaseFileName, KDatabaseSecurePhysicalName); test.Printf(_L("Checking ExtHintField before loading cntmodel\n")); TestTrue(!ExtHintFieldExistsL(theFS)); //The field shouldn't exist in original table //Contact model must open and upgrade database test.Printf(_L("Loading cntmodel\n")); CContactDatabase* theDatabase = NULL; TestTrap(theDatabase = CContactDatabase::OpenL(KDatabaseSecureName)); delete theDatabase; theDatabase = NULL; //Copy the file to the C drive, where it can be checked by the test code through DBMS serv.CopyFileL(KDatabaseSecurePhysicalName, KDatabaseFileName); test.Printf(_L("Checking ExtHintField after opening with cntmodel\n")); TestTrue(ExtHintFieldExistsL(theFS)); //Contacts model must have created the ExtHintField test.End(); }
bool MockOLED::drawGeneralMock(String stringToPrint,MockOLED& obj) { const char* conversion; conversion = stringToPrint.c_str(); bool printed = obj.MockPrintToOLED (conversion); //There's an interior method here that interacts with the OLED directly and that needed to be changed TestTrue ("The ticket type display on the OLED", printed); return true; //if done }
bool FCircularQueueTest::RunTest( const FString& Parameters ) { const uint32 QueueSize = 8; // empty queue { TCircularQueue<int32> Queue(QueueSize); TestTrue(TEXT("Newly created queues must be empty"), Queue.IsEmpty()); TestFalse(TEXT("Newly created queues must not be full"), Queue.IsFull()); } // partially filled { TCircularQueue<int32> Queue(QueueSize); int32 Value; TestTrue(TEXT("Adding to an empty queue must succeed"), Queue.Enqueue(666)); TestFalse(TEXT("Partially filled queues must not be empty"), Queue.IsEmpty()); TestFalse(TEXT("Partially filled queues must not be full"), Queue.IsFull()); TestTrue(TEXT("Peeking at a partially filled queue must succeed"), Queue.Peek(Value)); } // full queue { TCircularQueue<int32> Queue(QueueSize); for (int32 Index = 0; Index < QueueSize - 1; ++Index) { TestTrue(TEXT("Adding to non-full queue must succeed"), Queue.Enqueue(Index)); } TestFalse(TEXT("Full queues must not be empty"), Queue.IsEmpty()); TestTrue(TEXT("Full queues must be full"), Queue.IsFull()); TestFalse(TEXT("Adding to full queue must fail"), Queue.Enqueue(666)); int32 Value; for (int32 Index = 0; Index < QueueSize - 1; ++Index) { TestTrue(TEXT("Peeking at a none-empty queue must succeed"), Queue.Peek(Value)); TestEqual(TEXT("The peeked at value must be correct"), Value, Index); TestTrue(TEXT("Removing from a non-empty queue must succeed"), Queue.Dequeue(Value)); TestEqual(TEXT("The removed value must be correct"), Value, Index); } TestTrue(TEXT("A queue that had all items removed must be empty"), Queue.IsEmpty()); TestFalse(TEXT("A queue that had all items removed must not be full"), Queue.IsFull()); } return true; }
bool FTimespanTest::RunTest( const FString& Parameters ) { // constructors must create equal objects FTimespan ts1_1 = FTimespan(3, 2, 1); FTimespan ts1_2 = FTimespan(0, 3, 2, 1); FTimespan ts1_3 = FTimespan(0, 3, 2, 1, 0); TestEqual(TEXT("Constructors must create equal objects (Hours/Minutes/Seconds vs. Days/Hours/Minutes/Seconds)"), ts1_1, ts1_2); TestEqual(TEXT("Constructors must create equal objects (Hours/Minutes/Seconds vs. Days/Hours/Minutes/Seconds/Milliseconds)"), ts1_1, ts1_3); // component getters must return correct values FTimespan ts2_1 = FTimespan(1, 2, 3, 4, 5); TestEqual(TEXT("Component getters must return correct values (Days)"), ts2_1.GetDays(), 1); TestEqual(TEXT("Component getters must return correct values (Hours)"), ts2_1.GetHours(), 2); TestEqual(TEXT("Component getters must return correct values (Minutes)"), ts2_1.GetMinutes(), 3); TestEqual(TEXT("Component getters must return correct values (Seconds)"), ts2_1.GetSeconds(), 4); TestEqual(TEXT("Component getters must return correct values (Milliseconds)"), ts2_1.GetMilliseconds(), 5); // durations of positive and negative time spans must match FTimespan ts3_1 = FTimespan(1, 2, 3, 4, 5); FTimespan ts3_2 = FTimespan(-1, -2, -3, -4, -5); TestEqual(TEXT("Durations of positive and negative time spans must match"), ts3_1.GetDuration(), ts3_2.GetDuration()); // static constructors must create correct values TestEqual(TEXT("Static constructors must create correct values (FromDays)"), FTimespan::FromDays(123).GetTotalDays(), 123.0); TestEqual(TEXT("Static constructors must create correct values (FromHours)"), FTimespan::FromHours(123).GetTotalHours(), 123.0); TestEqual(TEXT("Static constructors must create correct values (FromMinutes)"), FTimespan::FromMinutes(123).GetTotalMinutes(), 123.0); TestEqual(TEXT("Static constructors must create correct values (FromSeconds)"), FTimespan::FromSeconds(123).GetTotalSeconds(), 123.0); TestEqual(TEXT("Static constructors must create correct values (FromMilliseconds)"), FTimespan::FromMilliseconds(123).GetTotalMilliseconds(), 123.0); // string conversions must return correct strings FTimespan ts5_1 = FTimespan(1, 2, 3, 4, 5); TestEqual<FString>(TEXT("String conversion (Default)"), ts5_1.ToString(), TEXT("1.02:03:04.005")); TestEqual<FString>(TEXT("String conversion (%n%d.%h:%m:%s.%f)"), ts5_1.ToString(TEXT("%n%d.%h:%m:%s.%f")), TEXT("1.02:03:04.005")); // parsing valid strings must succeed FTimespan ts6_1 = FTimespan(1, 2, 3, 4, 5); FTimespan ts6_2; TestTrue(TEXT("Parsing valid strings must succeed (1.02:03:04.005)"), FTimespan::Parse(TEXT("1.02:03:04.005"), ts6_2)); TestEqual(TEXT("Parsing valid strings must result in correct values (1.02:03:04.005)"), ts6_2, ts6_1); // parsing invalid strings must fail FTimespan ts7_1; //TestFalse(TEXT("Parsing invalid strings must fail (1,02:03:04.005)"), FTimespan::Parse(TEXT("1,02:03:04.005"), ts7_1)); //TestFalse(TEXT("Parsing invalid strings must fail (1.1.02:03:04:005)"), FTimespan::Parse(TEXT("1.1.02:03:04:005"), ts7_1)); //TestFalse(TEXT("Parsing invalid strings must fail (04:005)"), FTimespan::Parse(TEXT("04:005"), ts7_1)); return true; }
void MockSDBeacon::SDBeaconSetup (MockSdFat& SD) {//Checked and good YEP //Serial.begin (9600); Serial.print(F("Initializing SD card...")); pinMode(10, OUTPUT); if (!SD.begin(4)) { Serial.println(F("initialization failed!")); return; } Serial.println(F("initialization done.")); TestTrue ("The SD setup", SD.available()); }
bool FAnalyticsEventAttributeUnitTest::RunTest(const FString& Parameters) { if (FEngineAnalytics::IsAvailable()) { FString AttributeName; FString AttributeValue; AttributeName = "Test of"; AttributeValue = "FAnalyticsEventAttribute '(const FString InName, const FString& InVaue)'"; //Setup the 'Event Attributes' FAnalyticsEventAttribute EventAttributesFStringTest(AttributeName, AttributeValue); TestTrue(TEXT("Expected to take in these type of values '(const FString&, const FString&)'"), (EventAttributesFStringTest.AttrName == TEXT("Test of") && EventAttributesFStringTest.AttrValue == "FAnalyticsEventAttribute '(const FString InName, const FString& InVaue)'")); FAnalyticsEventAttribute EventAttributesTCHARTest(AttributeName, TEXT("FAnalyticsEventAttribute '(const FString InName, const TCHAR* InValue)'")); TestTrue(TEXT("Expected to take in these type of values '(const FString&, const TCHAR*')"), (EventAttributesTCHARTest.AttrName == TEXT("Test of") && EventAttributesTCHARTest.AttrValue == TEXT("FAnalyticsEventAttribute '(const FString InName, const TCHAR* InValue)'"))); bool bIsBoolTest = true; FAnalyticsEventAttribute EventAttributesBoolTest(AttributeName, bIsBoolTest); TestTrue(TEXT("Expected to take in these types of values '(const FString&, bool)'"), (EventAttributesBoolTest.AttrName == TEXT("Test of") && EventAttributesBoolTest.AttrValue == "true")); FGuid GuidTest(FGuid::NewGuid()); FAnalyticsEventAttribute EventAttributesGuidTest(AttributeName, GuidTest); TestTrue(TEXT("Expected to take in these type of values '(const FString&, FGuid)'"), (EventAttributesGuidTest.AttrName == TEXT("Test of") && EventAttributesGuidTest.AttrValue == GuidTest.ToString())); int32 InNumericType = 42; FAnalyticsEventAttribute EventAttributesTInValueTest(AttributeName, InNumericType); TestTrue(TEXT("Expected to take in a arithmetic type (example int32)"), (EventAttributesTInValueTest.AttrName == TEXT("Test of") && EventAttributesTInValueTest.AttrValue == TEXT("42"))); TArray<int32> InNumericArray; InNumericArray.Add(0); InNumericArray.Add(1); InNumericArray.Add(2); FAnalyticsEventAttribute EventAttributesTArray(AttributeName, InNumericArray); TestTrue(TEXT("Expected to take in am arithmetic TArray"), (EventAttributesTArray.AttrName == TEXT("Test of") && EventAttributesTArray.AttrValue == TEXT("0,1,2"))); FString TMapKey1 = "TestKey 1"; FString TMapKey2 = "TestKey 2"; FString TMapKey3 = "TestKey 3"; int32 NumericValue1 = 0; int32 NumericValue2 = 1; int32 NumericValue3 = 99; TMap<FString, int32> InTMap; InTMap.Add(TMapKey1, NumericValue1); InTMap.Add(TMapKey2, NumericValue2); InTMap.Add(TMapKey3, NumericValue3); FAnalyticsEventAttribute EventAttributesTMap(AttributeName, InTMap); TestTrue(TEXT("Expected to take in a TMap "), (EventAttributesTMap.AttrName == TEXT("Test of") && EventAttributesTMap.AttrValue == TEXT("TestKey 1:0,TestKey 2:1,TestKey 3:99"))); return true; } ExecutionInfo.LogItems.Add(TEXT("SKIPPED 'FAnalyticsEventAttributeUnitTest' test. EngineAnalytics are not currently available.")); return true; }
bool FLightingPromotionPointLightPlaceRotScaleTest::RunTest(const FString& Parameters) { //** SETUP **// // Create the world. UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Test Summary AddLogItem(TEXT("Place, Scale, and Rotate.\n- A Point light is placed into the world.\n- The light is moved.\n- The light is rotated.\n- The light is scaled up.")); if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. APointLight* PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), FTransform())); // Set the actors location, rotation, and scale3D. PointLight->SetActorLocation(POINT_LIGHT_UPDATED_LOCATION); PointLight->SetActorRotation(POINT_LIGHT_UPDATED_ROTATION); PointLight->SetActorScale3D(POINT_LIGHT_UPDATED_SCALE3D); //** VERIFY **// FVector CurrentLocation; LightingTestHelpers::GetActorCurrentLocation(CurrentLevel, PointLight->GetName(), CurrentLocation); FRotator CurrentRotation; LightingTestHelpers::GetActorCurrentRotation(CurrentLevel, PointLight->GetName(), CurrentRotation); FVector CurrentScale3D; LightingTestHelpers::GetActorCurrentScale3D(CurrentLevel, PointLight->GetName(), CurrentScale3D); bool RotationsAreEqual = CurrentRotation.Equals(POINT_LIGHT_UPDATED_ROTATION, 1); TestTrue(TEXT("The placed point light was not found."), LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, PointLight->GetName(), PointLight->GetClass())); TestEqual<FVector>(TEXT("The point light is not in correct location"), POINT_LIGHT_UPDATED_LOCATION, CurrentLocation); TestTrue(TEXT("The point light is not rotated correctly."), RotationsAreEqual); TestEqual<FVector>(TEXT("The point light is not scaled correctly."), POINT_LIGHT_UPDATED_SCALE3D, CurrentScale3D); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
void MockSDBeacon::simpleReadSD (String fileName, MockSdFat& SD, MockFile& myFile){ //No way to sensibly shorten const char* conversion = fileName.c_str(); //myFile = SD.open(conversion, FILE_READ); if (myFile.available()) { while (bool success = myFile.available()) { Serial.write(myFile.read()); TestTrue ("simpleRead", success); break; } myFile.close(); } else { Serial.print(F("Error opening ")); Serial.println (fileName); } }
bool FViewportShowflagsToggleOnTest::RunTest( const FString& Parameters ) { // SETUP // // Get the index for the flag and convert it back to an int. int32 FlagIndex = FCString::Atoi( *Parameters ); int32 ViewportClientNumber = 0; bool OrigianlShowFlagState = FViewportTestHelper::GetPerspectiveOriginalFlagstate( FlagIndex, ViewportClientNumber ); FLevelEditorViewportClient* ViewportClient = GEditor->LevelViewportClients[ViewportClientNumber]; // TEST // // Set the show flag to be enabled. ViewportClient->EngineShowFlags.SetSingleFlag(FlagIndex, true); // VERIFY // bool NewFlagState = ViewportClient->EngineShowFlags.GetSingleFlag(FlagIndex); TestTrue(TEXT("The showflag state was not set to true."), NewFlagState); // TEARDOWN // // This sets the view port back to it's default show flag value. ViewportClient->EngineShowFlags.SetSingleFlag(FlagIndex, OrigianlShowFlagState); return true; }
bool FLightPointLightPlacement::RunTest(const FString& Parameters) { //** SETUP **// // Create a new level. UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Light Setup APointLight* PointLight = nullptr; const FTransform Transform; if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), Transform)); //** VERIFY **// TestTrue(TEXT("The placed point light was not found."), LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, PointLight->GetName(), PointLight->GetClass())); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
bool MockSDBeacon::searchDatabaseForTicket(String TicketString, MockSdFat& SD, MockFile& myFile){ //No way to sensibly shorten const char* TicketNo = TicketString.c_str(); bool report = false; //Serial.println (TicketNo); //myFile = SD.open("test.txt"); if (myFile.available()) { const char* buf; const char* reader = myFile.read(buf, 16); //couldn't quite get this to work properly--still working on it if (strncmp(reader, TicketNo, 14) == 0) { //Serial.println(F("Match!")); report = true; } else { Serial.println ("No Match"); } myFile.close(); TestTrue ("Database search", report); return report; } else { Serial.println(F("error opening file")); //error } }
void MockBLE::TflyBLESetup(){ //Use only in the setup loop YEP ble_set_name ("TFLY"); ble_begin (); //Serial.begin (57600); TestTrue ("The ble setup", true); }
void MockOLED::drawSetupMock(MockOLED& obj) { //Serial.begin (9600); //alternately comment out if using more than one setup function TestTrue ("The OLED is setup", obj.exists); bool printed = obj.MockPrintToOLED ("Setting Up"); //There's an interior method here that interacts with the OLED TestTrue ("drawSetup Print Check", printed); }
void MockSDBeacon::fileRemove (String fileName, MockSdFat& SD, MockFile& myFile) { const char* conversion = fileName.c_str(); SD.open(conversion); TestTrue ("fileremove", SD.remove(conversion)); }
bool FIPv4AddressTest::RunTest( const FString& Parameters ) { // component access must be correct FIPv4Address a1_1 = FIPv4Address(1, 2, 3, 4); TestEqual<uint8>(TEXT("Byte 0 of 1.2.3.4 must be 4"), a1_1.GetByte(0), 4); TestEqual<uint8>(TEXT("Byte 1 of 1.2.3.4 must be 3"), a1_1.GetByte(1), 3); TestEqual<uint8>(TEXT("Byte 2 of 1.2.3.4 must be 2"), a1_1.GetByte(2), 2); TestEqual<uint8>(TEXT("Byte 3 of 1.2.3.4 must be 1"), a1_1.GetByte(3), 1); // link local addresses must be recognized FIPv4Address a2_1 = FIPv4Address(169, 254, 0, 1); FIPv4Address a2_2 = FIPv4Address(168, 254, 0, 1); FIPv4Address a2_3 = FIPv4Address(169, 253, 0, 1); TestTrue(TEXT("169.254.0.1 must be a link local address"), a2_1.IsLinkLocal()); TestFalse(TEXT("168.254.0.1 must not be a link local address"), a2_2.IsLinkLocal()); TestFalse(TEXT("169.253.0.1 must not be a link local address"), a2_3.IsLinkLocal()); // loopback addresses must be recognized FIPv4Address a3_1 = FIPv4Address(127, 0, 0, 1); FIPv4Address a3_2 = FIPv4Address(128, 0, 0, 1); TestTrue(TEXT("127.0.0.1 must be a loopback address"), a3_1.IsLoopbackAddress()); TestFalse(TEXT("128.0.0.1 must not be a loopback address"), a3_2.IsLoopbackAddress()); // multicast addresses must be recognized FIPv4Address a4_1 = FIPv4Address(223, 255, 255, 255); FIPv4Address a4_2 = FIPv4Address(224, 0, 0, 0); FIPv4Address a4_3 = FIPv4Address(239, 255, 255, 255); FIPv4Address a4_4 = FIPv4Address(240, 0, 0, 0); TestFalse(TEXT("223.255.255.255 must not be a multicast address"), a4_1.IsMulticastAddress()); TestTrue(TEXT("224.0.0.0 must be a multicast address"), a4_2.IsMulticastAddress()); TestTrue(TEXT("239.255.255.255 must be a multicast address"), a4_3.IsMulticastAddress()); TestFalse(TEXT("240.0.0.0 must not be a multicast address"), a4_4.IsMulticastAddress()); // string conversion FIPv4Address a5_1 = FIPv4Address(1, 2, 3, 4); TestEqual<FString>(TEXT("String conversion (1.2.3.4)"), a5_1.ToText().ToString(), TEXT("1.2.3.4")); // parsing valid strings must succeed FIPv4Address a6_1 = FIPv4Address(1, 2, 3, 4); FIPv4Address a6_2; TestTrue(TEXT("Parsing valid strings must succeed (1.2.3.4)"), FIPv4Address::Parse(TEXT("1.2.3.4"), a6_2)); TestEqual(TEXT("Parsing valid strings must result in correct value (1.2.3.4)"), a6_2, a6_1); // parsing invalid strings must fail FIPv4Address a7_1; TestFalse(TEXT("Parsing invalid strings must fail (1.2.3)"), FIPv4Address::Parse(TEXT("1.2.3"), a6_2)); // site local addresses must be recognized FIPv4Address a8_1 = FIPv4Address(10, 0, 0, 1); FIPv4Address a8_2 = FIPv4Address(172, 16, 0, 1); FIPv4Address a8_3 = FIPv4Address(192, 168, 0, 1); TestTrue(TEXT("10.0.0.1 must be a site local address"), a8_1.IsSiteLocalAddress()); TestTrue(TEXT("172.16.0.1 must be a site local address"), a8_2.IsSiteLocalAddress()); TestTrue(TEXT("192.168.0.1 must be a site local address"), a8_3.IsSiteLocalAddress()); FIPv4Address a8_4 = FIPv4Address(11, 0, 0, 1); FIPv4Address a8_5 = FIPv4Address(173, 16, 0, 1); FIPv4Address a8_6 = FIPv4Address(172, 17, 0, 1); FIPv4Address a8_7 = FIPv4Address(193, 168, 0, 1); FIPv4Address a8_8 = FIPv4Address(192, 169, 0, 1); TestFalse(TEXT("11.0.0.1 must not be a site local address"), a8_4.IsSiteLocalAddress()); TestFalse(TEXT("173.16.0.1 must not be a site local address"), a8_5.IsSiteLocalAddress()); TestFalse(TEXT("172.17.0.1 must not be a site local address"), a8_6.IsSiteLocalAddress()); TestFalse(TEXT("193.168.0.1 must not be a site local address"), a8_7.IsSiteLocalAddress()); TestFalse(TEXT("192.169.0.1 must not be a site local address"), a8_8.IsSiteLocalAddress()); return true; }
/** * Perform some collision sweep tests. Creates a given shape mesh and checks collision normal against a collision shape type. * Data for tests is in the [/Script/UnrealEd.CollisionAutomationTestConfigData] section of BaseEditor.ini * * @param Parameters - Unused for this test * @return TRUE if the test was successful, FALSE otherwise */ bool FComponentSweepMultiTest::RunTest(const FString& Parameters) { CollisionAutomationTests::TestBase = this; // Create map UWorld* World = FAutomationEditorCommonUtils::CreateNewMap(); TestNotNull( TEXT("Failed to create world for Physics.Collision.Ray Test. Tests aborted."), World ); static FName TraceIdent = FName(TEXT("TestTrace")); FVector StartPos; FVector EndPos; ECollisionChannel Channel = ECC_WorldStatic; UCollisionAutomationTestConfigData* Data = UCollisionAutomationTestConfigData::StaticClass()->GetDefaultObject<UCollisionAutomationTestConfigData>(); // Get the tests for (int32 iTest = 0; iTest < Data->ComponentSweepMultiTests.Num(); iTest++) { FCollisionTestEntry OneElement = Data->ComponentSweepMultiTests[iTest]; // Create the Actor to check against AStaticMeshActor* TestRayMeshActor = CollisionAutomationTests::CreateShapeMeshActor( *OneElement.RootShapeAsset, OneElement.HitResult.TraceEnd); // Create the collision component AActor* TestRayCollisionActor = CollisionAutomationTests::CreateCollisionShape( World, OneElement.ShapeType, OneElement.HitResult.TraceStart); if ((TestRayMeshActor != nullptr) && (TestRayCollisionActor != nullptr)) { // Set the collision profile and enable collision and physics TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.SetCollisionProfileName(TEXT("BlockAll")); TestRayMeshActor->SetActorEnableCollision(true); TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.bSimulatePhysics = true; UShapeComponent* CollisionComponent = Cast<UShapeComponent>(TestRayCollisionActor->GetRootComponent()); TestRayCollisionActor->SetActorEnableCollision(true); if( CollisionComponent != nullptr ) { CollisionComponent->SetCollisionProfileName(TEXT("BlockAll")); CollisionComponent->SetSimulatePhysics(true); } // Setup positions StartPos = TestRayCollisionActor->GetActorLocation(); EndPos = TestRayMeshActor->GetActorLocation(); // Setup the query FComponentQueryParams ShapeQueryParameters(TraceIdent, nullptr); ShapeQueryParameters.bTraceComplex = true; ShapeQueryParameters.bTraceAsyncScene = true; // Perform test TArray<FHitResult> OutHits; bool WasBlocked = World->ComponentSweepMulti(OutHits, CollisionComponent, StartPos, EndPos, FRotator::ZeroRotator, ShapeQueryParameters); bool BlockedBySpecified = false; if (WasBlocked == true) { for (int32 iHits = 0; iHits < OutHits.Num(); iHits++) { AActor* EachActor = OutHits[iHits].GetActor(); if (EachActor == TestRayMeshActor) { BlockedBySpecified = true; // This generates a snippet you can copy/paste into the ini file for test validation //UE_LOG(CollisionAutomationTestLog, Log, TEXT("%d:HitResult=(%s)"), iTest+1, *(CollisionAutomationTests::HitToString(OutHits[iHits]))); CollisionAutomationTests::CheckVector( OutHits[iHits].ImpactNormal, OneElement.HitResult.ImpactNormal, TEXT("ComponentSweepMulti"), TEXT("ImpactNormal"), iTest ); CollisionAutomationTests::CheckVector( OutHits[iHits].Normal, OneElement.HitResult.Normal, TEXT("ComponentSweepMulti"), TEXT("Normal"), iTest ); CollisionAutomationTests::CheckVector( OutHits[iHits].ImpactPoint, OneElement.HitResult.ImpactPoint, TEXT("ComponentSweepMulti"), TEXT("ImpactPoint"), iTest ); CollisionAutomationTests::CheckFloat( OutHits[iHits].Time, OneElement.HitResult.Time, TEXT("ComponentSweepMulti"), TEXT("Time"), iTest ); } } } TestTrue(FString::Printf(TEXT("Test %d:ComponentSweepMulti from %s to %s failed. Should return blocking hit"), iTest+1, *TestRayMeshActor->GetName(), *TestRayCollisionActor->GetName()), BlockedBySpecified); } // Remove the actors TestRayMeshActor->Destroy(); TestRayCollisionActor->Destroy(); } return true; }
bool FManifestTest::RunTest( const FString& Parameters ) { // Key metadata TSharedPtr< FLocMetadataObject > KeyMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > KeyMetadataB = MakeShareable( new FLocMetadataObject ); // Info metadata TSharedPtr< FLocMetadataObject > InfoMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > InfoMetadataB = MakeShareable( new FLocMetadataObject ); // Source metadata TSharedPtr< FLocMetadataObject > SourceMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > SourceMetadataB = MakeShareable( new FLocMetadataObject ); // Setup KeyMetadataA KeyMetadataA->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataA->SetStringField( TEXT("TargetGender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup KeyMetadataB KeyMetadataB->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataB->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataB->SetStringField( TEXT("TargetGender" ), TEXT("Feminine") ); KeyMetadataB->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup source metadata SourceMetadataA->SetBoolField( TEXT("*IsMature"), false ); SourceMetadataB->SetBoolField( TEXT("*IsMature"), true ); // Set InfoMetadataA InfoMetadataA->SetStringField( TEXT("VoiceActorDirection"), TEXT("Go big or go home!") ); // Test FInternationalizationManifest { FContext ContextA; ContextA.Key = TEXT("KeyA"); ContextA.SourceLocation = TEXT("SourceLocationA"); ContextA.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataA) ); ContextA.KeyMetadataObj = MakeShareable( new FLocMetadataObject(*KeyMetadataA) ); FContext ContextB; ContextB.Key = TEXT("KeyB"); ContextB.SourceLocation = TEXT("SourceLocationB"); ContextB.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataB) ); ContextB.KeyMetadataObj = MakeShareable( new FLocMetadataObject(*KeyMetadataB) ); FLocItem Source( TEXT("TestText") ); Source.MetadataObj = MakeShareable( new FLocMetadataObject(*SourceMetadataA) ); FString TestNamespace = TEXT("TestNamespace"); // Adding entries with exactly matching Source and matching Context { FInternationalizationManifest TestManifest; TestManifest.AddSource( TestNamespace, Source, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, Source, ContextA ); // Adding a duplicate entry reports success but our entry count is not increased after the first entry is added TestTrue( TEXT("AddSource result == true"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); } // Adding entries with exactly matching Source but different Contexts { FInternationalizationManifest TestManifest; TestManifest.AddSource( TestNamespace, Source, ContextA ); TestManifest.AddSource( TestNamespace, Source, ContextB ); TestEqual( TEXT("ManifestCount == 2"), CountManifestEntries(TestManifest), 2 ); // Test find by context TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryByContext( TestNamespace, ContextA ); if( !FoundEntry1.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryByContext.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry1->Source == Source ); TestEqual( TEXT("FoundEntry->Context.Num() == 2"), FoundEntry1->Contexts.Num(), 2); } TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryByContext( TestNamespace, ContextB ); if( !FoundEntry2.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryByContext.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry2->Source == Source ); TestEqual( TEXT("FoundEntry->Context.Num() == 2"), FoundEntry2->Contexts.Num(), 2); } // Test find by source TSharedPtr< FManifestEntry > FoundEntry3 = TestManifest.FindEntryBySource( TestNamespace, Source ); if( !FoundEntry3.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryBySource.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry3->Source == Source ); TestEqual( TEXT("FoundEntry->Context.Num() == 2"), FoundEntry3->Contexts.Num(), 2); } TestTrue( TEXT("FoundEntry1 == FoundEntry2 == FoundEntry3"), (FoundEntry1 == FoundEntry2) && (FoundEntry1 == FoundEntry3) ); } // Adding entries with Source that is NOT an exact match and matching context { // Source mismatched by Source Text. { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceA( TEXT("Conflicting TestTextA") ); FLocItem ConflictingSourceB( TEXT("Conflicting TestTextB") ); TestManifest.AddSource( TestNamespace, ConflictingSourceA, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceB, ContextA ); // Adding the second entry reports failure and entry count is not increased TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); } // Source mismatched by standard metadata type (not * prefixed) { FInternationalizationManifest ManifestTypeConflict; FLocItem ConflictingSourceMetadataTypeA = Source; FLocItem ConflictingSourceMetadataTypeB = Source; // Set metadata with the same name but different type ConflictingSourceMetadataTypeA.MetadataObj->SetBoolField( TEXT("ConflictingType"), true ); ConflictingSourceMetadataTypeB.MetadataObj->SetStringField( TEXT("ConflictingType"), TEXT("true") ); ManifestTypeConflict.AddSource( TestNamespace, ConflictingSourceMetadataTypeA, ContextA ); bool bResult = ManifestTypeConflict.AddSource( TestNamespace, ConflictingSourceMetadataTypeB, ContextA ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(ManifestTypeConflict), 1 ); // Should not find a match when searching with the second Source we tried to add TSharedPtr< FManifestEntry > FoundEntry = ManifestTypeConflict.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeB ); TestInvalid( TEXT("FoundEntry is not valid"), FoundEntry); } // Source mismatched by standard metadata value (not * prefixed) { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataValueA = Source; FLocItem ConflictingSourceMetadataValueB = Source; // Set metadata with the same name and type but different value ConflictingSourceMetadataValueA.MetadataObj->SetStringField( TEXT("ConflictingValue"), TEXT("A") ); ConflictingSourceMetadataValueB.MetadataObj->SetStringField( TEXT("ConflictingValue"), TEXT("B") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueA, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueB, ContextA ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // Should not find a match when searching with the second Source we tried to add TSharedPtr< FManifestEntry > FoundEntry = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueB ); TestInvalid( TEXT("FoundEntry is not valid"), FoundEntry); } // Source mismatched by * prefixed metadata type { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataTypeA = Source; FLocItem ConflictingSourceMetadataTypeB = Source; // Set metadata with the same name but different type ConflictingSourceMetadataTypeA.MetadataObj->SetBoolField( TEXT("*ConflictingType"), true ); ConflictingSourceMetadataTypeB.MetadataObj->SetStringField( TEXT("*ConflictingType"), TEXT("true") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeA, ContextA ); // Though the Source items are considered to be a match(they are equal) in this case, the manifest reports this as a conflict // and should not add an entry. The reason is that AddSource does an 'exact' match check on the metadata object bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeB, ContextA ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // We should be able to find the entry using either Source FLocItem TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); } // Source mismatched by * prefixed metadata value { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataValueA = Source; FLocItem ConflictingSourceMetadataValueB = Source; // Set metadata with the same name and type but different value ConflictingSourceMetadataValueA.MetadataObj->SetStringField( TEXT("*ConflictingValue"), TEXT("A") ); ConflictingSourceMetadataValueB.MetadataObj->SetStringField( TEXT("*ConflictingValue"), TEXT("B") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueA, ContextA ); // Thought the Source items are considered to be a match(they are equal) in this case, the manifest reports this as a conflict // and should not add an entry. The reason is that AddSource does an 'exact' match check on the metadata object bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueB, ContextA ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // We should be able to find the entry using either Source FLocItem TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); } } // Adding entries with Source that is NOT an exact match and different context { // Source mismatched by Source Text. { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceA( TEXT("Conflicting TestTextA") ); FLocItem ConflictingSourceB( TEXT("Conflicting TestTextB") ); TestManifest.AddSource( TestNamespace, ConflictingSourceA, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceB, ContextB ); TestTrue( TEXT("AddSource result == true"), bResult); TestEqual( TEXT("ManifestCount == 2"), CountManifestEntries(TestManifest), 2 ); // We should be able to find two unique entries by source TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); TestTrue( TEXT("FoundEntry1 != FoundEntry2"), FoundEntry1 != FoundEntry2 ); // We should be able to find two unique entries by context TSharedPtr< FManifestEntry > FoundEntry3 = TestManifest.FindEntryByContext( TestNamespace, ContextA ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry3); TSharedPtr< FManifestEntry > FoundEntry4 = TestManifest.FindEntryByContext( TestNamespace, ContextB ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry4); TestTrue( TEXT("FoundEntry3 != FoundEntry4"), FoundEntry3 != FoundEntry4 ); // Found entry looked up by source A should match entry looked up by context A TestTrue( TEXT("FoundEntry1 == FoundEntry3"), FoundEntry1 == FoundEntry3 ); // Found entry looked up by source B should match entry looked up by context B TestTrue( TEXT("FoundEntry2 == FoundEntry4"), FoundEntry2 == FoundEntry4 ); } // Source mismatched by standard metadata type (not * prefixed) { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataTypeA = Source; FLocItem ConflictingSourceMetadataTypeB = Source; // Set metadata with the same name but different type ConflictingSourceMetadataTypeA.MetadataObj->SetBoolField( TEXT("ConflictingType"), true ); ConflictingSourceMetadataTypeB.MetadataObj->SetStringField( TEXT("ConflictingType"), TEXT("true") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeA, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeB, ContextB ); TestTrue( TEXT("AddSource result == true"), bResult); TestEqual( TEXT("ManifestCount == 2"), CountManifestEntries(TestManifest), 2 ); // We should be able to find two unique entries by source TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); TestTrue( TEXT("FoundEntry1 != FoundEntry2"), FoundEntry1 != FoundEntry2 ); // We should be able to find two unique entries by context TSharedPtr< FManifestEntry > FoundEntry3 = TestManifest.FindEntryByContext( TestNamespace, ContextA ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry3); TSharedPtr< FManifestEntry > FoundEntry4 = TestManifest.FindEntryByContext( TestNamespace, ContextB ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry4); TestTrue( TEXT("FoundEntry3 != FoundEntry4"), FoundEntry3 != FoundEntry4 ); // Found entry looked up by source A should match entry looked up by context A TestTrue( TEXT("FoundEntry1 == FoundEntry3"), FoundEntry1 == FoundEntry3 ); // Found entry looked up by source B should match entry looked up by context B TestTrue( TEXT("FoundEntry2 == FoundEntry4"), FoundEntry2 == FoundEntry4 ); } // Source mismatched by standard metadata value (not * prefixed) { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataValueA = Source; FLocItem ConflictingSourceMetadataValueB = Source; // Set metadata with the same name and type but different value ConflictingSourceMetadataValueA.MetadataObj->SetStringField( TEXT("ConflictingValue"), TEXT("A") ); ConflictingSourceMetadataValueB.MetadataObj->SetStringField( TEXT("ConflictingValue"), TEXT("B") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueA, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueB, ContextB ); TestTrue( TEXT("AddSource result == true"), bResult); TestEqual( TEXT("ManifestCount == 2"), CountManifestEntries(TestManifest), 2 ); // We should be able to find two unique entries by source TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); TestTrue( TEXT("FoundEntry1 != FoundEntry2"), FoundEntry1 != FoundEntry2 ); // We should be able to find two unique entries by context TSharedPtr< FManifestEntry > FoundEntry3 = TestManifest.FindEntryByContext( TestNamespace, ContextA ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry3); TSharedPtr< FManifestEntry > FoundEntry4 = TestManifest.FindEntryByContext( TestNamespace, ContextB ); TestValid( TEXT("FoundEntry3 is valid"), FoundEntry4); TestTrue( TEXT("FoundEntry3 != FoundEntry4"), FoundEntry3 != FoundEntry4 ); // Found entry looked up by source A should match entry looked up by context A TestTrue( TEXT("FoundEntry1 == FoundEntry3"), FoundEntry1 == FoundEntry3 ); // Found entry looked up by source B should match entry looked up by context B TestTrue( TEXT("FoundEntry2 == FoundEntry4"), FoundEntry2 == FoundEntry4 ); } // Source mismatched by * prefixed metadata type { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataTypeA = Source; FLocItem ConflictingSourceMetadataTypeB = Source; // Set metadata with the same name but different type ConflictingSourceMetadataTypeA.MetadataObj->SetBoolField( TEXT("*ConflictingType"), true ); ConflictingSourceMetadataTypeB.MetadataObj->SetStringField( TEXT("*ConflictingType"), TEXT("true") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeA, ContextA ); // Though the Source items are considered to be a match(they are equal) in this case, the manifest reports this as a conflict // and should not add an entry. The reason is that AddSource does an 'exact' match check on the metadata object bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataTypeB, ContextB ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // We should be able to find the entry using either Source FLocItem TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataTypeB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); } // Source mismatched by * prefixed metadata value { FInternationalizationManifest TestManifest; FLocItem ConflictingSourceMetadataValueA = Source; FLocItem ConflictingSourceMetadataValueB = Source; // Set metadata with the same name and type but different value ConflictingSourceMetadataValueA.MetadataObj->SetStringField( TEXT("*ConflictingValue"), TEXT("A") ); ConflictingSourceMetadataValueB.MetadataObj->SetStringField( TEXT("*ConflictingValue"), TEXT("B") ); TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueA, ContextA ); // Thought the Source items are considered to be a match(they are equal) in this case, the manifest reports this as a conflict // and should not add an entry. The reason is that AddSource does an 'exact' match check on the metadata object bool bResult = TestManifest.AddSource( TestNamespace, ConflictingSourceMetadataValueB, ContextB ); TestFalse( TEXT("AddSource result == false"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // We should be able to find the entry using either Source FLocItem TSharedPtr< FManifestEntry > FoundEntry1 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueA ); TestValid( TEXT("FoundEntry1 is valid"), FoundEntry1); TSharedPtr< FManifestEntry > FoundEntry2 = TestManifest.FindEntryBySource( TestNamespace, ConflictingSourceMetadataValueB ); TestValid( TEXT("FoundEntry2 is valid"), FoundEntry2); } } // Adding an entry that only differs in the optional flag { FInternationalizationManifest TestManifest; // Reports success and our entry count does not change. bIsOptional is not a key and is not used during lookup. When // we AddSource, we find an existing matching entry so AddSource returns true but no new entry is added. The original // entry's bIsOptional value is not updated. FContext ContextConflictingOptionalFlag = ContextA; ContextConflictingOptionalFlag.bIsOptional = !ContextA.bIsOptional; TestManifest.AddSource( TestNamespace, Source, ContextA ); bool bResult = TestManifest.AddSource( TestNamespace, Source, ContextConflictingOptionalFlag); TestTrue( TEXT("AddSource result == true"), bResult); TestEqual( TEXT("ManifestCount == 1"), CountManifestEntries(TestManifest), 1 ); // We should be able to look up the existing entry using the ContextConflictingOptionalFlag context but the entries bIsOptional flag will match ContextA TSharedPtr< FManifestEntry > FoundEntry = TestManifest.FindEntryByContext( TestNamespace, ContextConflictingOptionalFlag ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryByContext.")); } else { TestTrue( TEXT("FoundEntry->bIsOptional == ContextA->bIsOptional"), FoundEntry->Contexts[0].bIsOptional == ContextA.bIsOptional ); } } // Add an entry with null key metadata to see if we can retrieve it with non-null but empty key metadata { FInternationalizationManifest TestManifest; FContext ContextC; ContextC.Key = TEXT("KeyC"); ContextC.SourceLocation = TEXT("SourceLocationC"); ContextC.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataB) ); ContextC.KeyMetadataObj = NULL; Source.MetadataObj = NULL; TestManifest.AddSource( TestNamespace, Source, ContextC ); // Now give our context and source valid but empty metadata ContextC.KeyMetadataObj = MakeShareable( new FLocMetadataObject() ); Source.MetadataObj = MakeShareable( new FLocMetadataObject() ); // Ensure we find the entry we added by source TSharedPtr< FManifestEntry > FoundEntry; FoundEntry = TestManifest.FindEntryBySource( TestNamespace, Source ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryBySource.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == Source ); } // Ensure we find the entry we added by context FoundEntry = TestManifest.FindEntryByContext( TestNamespace, ContextC ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryByContext.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == Source ); } } // Add an entry with non-null but empty key metadata and see if we can retrieve null metadata { FInternationalizationManifest TestManifest; FContext ContextC; ContextC.Key = TEXT("KeyC"); ContextC.SourceLocation = TEXT("SourceLocationC"); ContextC.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataB) ); ContextC.KeyMetadataObj = MakeShareable( new FLocMetadataObject()); Source.MetadataObj = MakeShareable( new FLocMetadataObject()); TestManifest.AddSource( TestNamespace, Source, ContextC ); // Now give our context and source Null metadata ContextC.KeyMetadataObj = NULL; Source.MetadataObj = NULL; // Ensure we find the entry we added by source TSharedPtr< FManifestEntry > FoundEntry; FoundEntry = TestManifest.FindEntryBySource( TestNamespace, Source ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryBySource.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == Source ); } // Ensure we find the entry we added by context FoundEntry = TestManifest.FindEntryByContext( TestNamespace, ContextC ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FManifestEntry could not find entry using FindEntryByContext.")); } else { TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == Source ); } } } return true; }
bool FLocItemTest::RunTest( const FString& Parameters ) { // Key metadata TSharedPtr< FLocMetadataObject > KeyMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > KeyMetadataB = MakeShareable( new FLocMetadataObject ); // Info metadata TSharedPtr< FLocMetadataObject > InfoMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > InfoMetadataB = MakeShareable( new FLocMetadataObject ); // Source metadata TSharedPtr< FLocMetadataObject > SourceMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > SourceMetadataB = MakeShareable( new FLocMetadataObject ); // Setup KeyMetadataA KeyMetadataA->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataA->SetStringField( TEXT("TargetGender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup KeyMetadataB KeyMetadataB->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataB->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataB->SetStringField( TEXT("TargetGender" ), TEXT("Feminine") ); KeyMetadataB->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup source metadata SourceMetadataA->SetBoolField( TEXT("*IsMature"), false ); SourceMetadataB->SetBoolField( TEXT("*IsMature"), true ); // Set InfoMetadataA InfoMetadataA->SetStringField( TEXT("VoiceActorDirection"), TEXT("Go big or go home!") ); // Test FLocItem { FLocItem LocItemA( TEXT("TextA") ); LocItemA.MetadataObj = MakeShareable( new FLocMetadataObject(*SourceMetadataA) ); FLocItem LocItemB( TEXT("TextB") ); LocItemB.MetadataObj = MakeShareable( new FLocMetadataObject(*SourceMetadataB) ); // Test copy ctor { FLocItem LocItemAClone = LocItemA; if( LocItemAClone.MetadataObj == LocItemA.MetadataObj ) { AddError(TEXT("FLocItem MetadataObj and its Clone are not unique objects.")); } TestEqual( TEXT("LocItemAClone.Text == LocItemA.Text"), LocItemAClone.Text, LocItemA.Text ); TestTrue( TEXT("LocItemAClone.MetadataObj == LocItemA.MetadataObj"), *(LocItemAClone.MetadataObj) == *(LocItemA.MetadataObj) ); TestEqual( TEXT("LocItemAClone == LocItemA"), LocItemAClone, LocItemA ); TestFalse( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); } // Test assignment operator { FLocItem LocItemAClone( TEXT("New") ); LocItemAClone = LocItemA; if( LocItemAClone.MetadataObj == LocItemA.MetadataObj ) { AddError(TEXT("FLocItem MetadataObj and its Clone are not unique objects.")); } TestEqual( TEXT("LocItemAClone.Text == LocItemA.Text"), LocItemAClone.Text, LocItemA.Text ); TestTrue( TEXT("LocItemAClone.MetadataObj == LocItemA.MetadataObj"), *(LocItemAClone.MetadataObj) == *(LocItemA.MetadataObj) ); TestEqual( TEXT("LocItemAClone == LocItemA"), LocItemAClone, LocItemA ); TestFalse( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); TestFalse( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); } // Test comparison operator { // Text and MetadataObj members should both be taken into account when comparing. Note, Metadata supports a special * name prefix that causes the type // and value of the metadata to be ignored when performing comparisons FLocItem LocItemAClone = LocItemA; TestEqual( TEXT("LocItemAClone == LocItemA"), LocItemAClone, LocItemA ); // Metadata with * prefix does not impact comparison but both FLocItems need a metadata where the name matches( type and value can be different ) FLocItem LocItemAClone2 = LocItemA; LocItemAClone.MetadataObj->SetStringField( TEXT("*NewNonCompare"), TEXT("NewNonCompareValue") ); TestNotEqual( TEXT("LocItemAClone != LocItemAClone2"), LocItemAClone, LocItemAClone2 ); LocItemAClone2.MetadataObj->SetStringField( TEXT("*NewNonCompare"), TEXT("NewNonCompareValue2") ); TestEqual( TEXT("LocItemAClone == LocItemAClone2"), LocItemAClone, LocItemAClone2 ); // Changing the text in any way will cause comparison to fail LocItemAClone = LocItemA; LocItemAClone.Text = LocItemAClone.Text + TEXT("New"); TestNotEqual( TEXT("LocItemAClone != LocItemA"), LocItemAClone, LocItemA ); // LocItem with valid but empty KeyMetadataObject should be equivalent to LocItem with null KeyMetadataObject FLocItem LocItemEmptyA(TEXT("TestText")); FLocItem LocItemEmptyB(TEXT("TestText")); LocItemEmptyB.MetadataObj = MakeShareable( new FLocMetadataObject ); TestEqual( TEXT("LocItemEmptyA == LocItemEmptyB"), LocItemEmptyA, LocItemEmptyB ); } // Testing less than operator { TestTrue( TEXT("LocItemA < LocItemB"), LocItemA < LocItemB ); TestFalse( TEXT("LocItemB < LocItemA"), LocItemB < LocItemA ); FLocItem LocItemAClone = LocItemA; // Differences in Text TestFalse( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); LocItemAClone.Text = LocItemAClone.Text + TEXT("A"); TestFalse( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); //currently failing TestTrue( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); // Adding new key metadata entry LocItemAClone = LocItemA; LocItemAClone.MetadataObj->SetStringField( TEXT("ANewKey"), TEXT("ANewValue") ); //currently failing TestTrue( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); TestFalse( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); // Removing a key metadata entry LocItemAClone = LocItemA; LocItemAClone.MetadataObj->RemoveField( TEXT("*IsMature") ); TestTrue( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); TestFalse( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); // Changing a key metadata entry value LocItemAClone = LocItemA; LocItemAClone.MetadataObj->SetBoolField( TEXT("*IsMature"),true ); //currently failing TestTrue( TEXT("LocItemA < LocItemAClone"), LocItemA < LocItemAClone ); TestFalse( TEXT("LocItemAClone < LocItemA"), LocItemAClone < LocItemA ); // Test null and non-null but empty Metadata FLocItem LocItemEmptyA( TEXT("SameText") ); FLocItem LocItemEmptyB( TEXT("SameText") ); TestFalse( TEXT("LocItemEmptyA < LocItemEmptyB"), LocItemEmptyA < LocItemEmptyB ); LocItemEmptyB.MetadataObj = MakeShareable( new FLocMetadataObject ); TestFalse( TEXT("LocItemEmptyA < LocItemEmptyB"), LocItemEmptyA < LocItemEmptyB ); TestFalse( TEXT("LocItemEmptyB < LocItemEmptyA"), LocItemEmptyB < LocItemEmptyA ); LocItemEmptyB.MetadataObj->SetStringField(TEXT("AMetadataKey"), TEXT("AMetadataValue")); TestTrue( TEXT("LocItemEmptyA < LocItemEmptyB"), LocItemEmptyA < LocItemEmptyB ); } } return true; }
bool FLocContextTest::RunTest( const FString& Parameters ) { // Key metadata TSharedPtr< FLocMetadataObject > KeyMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > KeyMetadataB = MakeShareable( new FLocMetadataObject ); // Info metadata TSharedPtr< FLocMetadataObject > InfoMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > InfoMetadataB = MakeShareable( new FLocMetadataObject ); // Source metadata TSharedPtr< FLocMetadataObject > SourceMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > SourceMetadataB = MakeShareable( new FLocMetadataObject ); // Setup KeyMetadataA KeyMetadataA->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataA->SetStringField( TEXT("TargetGender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup KeyMetadataB KeyMetadataB->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataB->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataB->SetStringField( TEXT("TargetGender" ), TEXT("Feminine") ); KeyMetadataB->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup source metadata SourceMetadataA->SetBoolField( TEXT("*IsMature"), false ); SourceMetadataB->SetBoolField( TEXT("*IsMature"), true ); // Set InfoMetadataA InfoMetadataA->SetStringField( TEXT("VoiceActorDirection"), TEXT("Go big or go home!") ); // Test FContext { FContext ContextA; ContextA.Key = TEXT("KeyA"); ContextA.SourceLocation = TEXT("SourceLocationA"); ContextA.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataA) ); ContextA.KeyMetadataObj = MakeShareable( new FLocMetadataObject(*KeyMetadataA) ); FContext ContextB; ContextB.Key = TEXT("KeyB"); ContextB.SourceLocation = TEXT("SourceLocationB"); ContextB.InfoMetadataObj = MakeShareable( new FLocMetadataObject(*InfoMetadataB) ); ContextB.KeyMetadataObj = MakeShareable( new FLocMetadataObject(*KeyMetadataB) ); // Test copy ctor { FContext ContextAClone = ContextA; if( ContextAClone.InfoMetadataObj == ContextA.InfoMetadataObj ) { AddError(TEXT("FContext InfoMetadataObj and its Clone are not unique objects.")); } if( ContextAClone.KeyMetadataObj == ContextA.KeyMetadataObj ) { AddError(TEXT("FContext KeyMetadataObj and its Clone are not unique objects.")); } TestEqual( TEXT("ContextAClone.Key == ContextA.Key"), ContextAClone.Key, ContextA.Key ); TestEqual( TEXT("ContextAClone.SourceLocation == ContextA.SourceLocation"), ContextAClone.SourceLocation, ContextA.SourceLocation ); TestEqual( TEXT("ContextAClone.bIsOptional == ContextA.bIsOptional"), ContextAClone.bIsOptional, ContextA.bIsOptional ); TestTrue( TEXT("ContextAClone.InfoMetadataObj == ContextA.InfoMetadataObj"), *(ContextAClone.InfoMetadataObj) == *(ContextA.InfoMetadataObj) ); TestTrue( TEXT("ContextAClone.KeyMetadataObj == ContextA.KeyMetadataObj"), *(ContextAClone.KeyMetadataObj) == *(ContextA.KeyMetadataObj) ); TestEqual( TEXT("ContextAClone == ContextA"), ContextAClone, ContextA ); TestFalse( TEXT("ContextAClone < ContextA"), ContextAClone < ContextA ); } // Test assignment operator { FContext ContextAClone; ContextAClone = ContextA; if( ContextAClone.InfoMetadataObj == ContextA.InfoMetadataObj ) { AddError(TEXT("FContext InfoMetadataObj and its Clone are not unique objects.")); } if( ContextAClone.KeyMetadataObj == ContextA.KeyMetadataObj ) { AddError(TEXT("FContext KeyMetadataObj and its Clone are not unique objects.")); } TestEqual( TEXT("ContextAClone.Key == ContextA.Key"), ContextAClone.Key, ContextA.Key ); TestEqual( TEXT("ContextAClone.SourceLocation == ContextA.SourceLocation"), ContextAClone.SourceLocation, ContextA.SourceLocation ); TestEqual( TEXT("ContextAClone.bIsOptional == ContextA.bIsOptional"), ContextAClone.bIsOptional, ContextA.bIsOptional ); TestTrue( TEXT("ContextAClone.InfoMetadataObj == ContextA.InfoMetadataObj"), *(ContextAClone.InfoMetadataObj) == *(ContextA.InfoMetadataObj) ); TestTrue( TEXT("ContextAClone.KeyMetadataObj == ContextA.KeyMetadataObj"), *(ContextAClone.KeyMetadataObj) == *(ContextA.KeyMetadataObj) ); TestEqual( TEXT("ContextAClone == ContextA"), ContextAClone, ContextA ); TestFalse( TEXT("ContextAClone < ContextA"), ContextAClone < ContextA ); } // Test comparison operator { // Key and KeyMetadataObj members should be the only items that are taken into account when comparing FContext ContextAClone = ContextA; TestEqual( TEXT("ContextAClone == ContextA"), ContextAClone, ContextA ); // Arbitrarily change all the non-important members ContextAClone.SourceLocation = ContextA.SourceLocation + TEXT("New"); ContextAClone.bIsOptional = !ContextA.bIsOptional; ContextAClone.InfoMetadataObj.Reset(); ContextAClone.InfoMetadataObj = MakeShareable( new FLocMetadataObject( *InfoMetadataB ) ); TestEqual( TEXT("ContextAClone == ContextA"), ContextAClone, ContextA ); // Changing the key in any way will cause comparison to fail ContextAClone.Key = ContextAClone.Key + TEXT("New"); TestNotEqual( TEXT("ContextAClone != ContextA"), ContextAClone, ContextA ); // Reset and test KeyMetadataObj change to one of the value entries ContextAClone = ContextA; ContextAClone.KeyMetadataObj->SetStringField( TEXT("TargetPlurality"), TEXT("Plural") ); TestNotEqual( TEXT("ContextAClone != ContextA"), ContextAClone, ContextA ); // Reset and test addition of entry to KeyMetadataObj ContextAClone = ContextA; ContextAClone.KeyMetadataObj->SetStringField( TEXT("NewField"), TEXT("NewFieldValue") ); TestNotEqual( TEXT("ContextAClone != ContextA"), ContextAClone, ContextA ); // Reset and test removal of entry from KeyMetadataObj ContextAClone = ContextA; ContextAClone.KeyMetadataObj->RemoveField( TEXT("TargetPlurality") ); TestNotEqual( TEXT("ContextAClone != ContextA"), ContextAClone, ContextA ); // Context with valid but empty KeyMetadataObject should be equivalent to Context with null KeyMetadataObject FContext ContextEmptyA; FContext ContextEmptyB; ContextEmptyB.KeyMetadataObj = MakeShareable( new FLocMetadataObject ); TestEqual( TEXT("ContextEmptyA == ContextEmptyB"), ContextEmptyA, ContextEmptyB ); } // Testing less than operator { TestTrue( TEXT("ContextA < ContextB"), ContextA < ContextB ); FContext ContextAClone = ContextA; // Differences in Key TestFalse( TEXT("ContextA < ContextAClone"), ContextA < ContextAClone ); ContextAClone.Key = ContextAClone.Key + TEXT("A"); //currently failing TestTrue( TEXT("ContextA < ContextAClone"), ContextA < ContextAClone ); // Adding new key metadata entry that will appear before other entries ContextAClone = ContextA; ContextAClone.KeyMetadataObj->SetStringField( TEXT("ANewKey"), TEXT("ANewValue") ); TestTrue( TEXT("ContextAClone < ContextA"), ContextAClone < ContextA ); // Adding new key metadata entry that will appear after other entries ContextAClone = ContextA; ContextAClone.KeyMetadataObj->SetStringField( TEXT("ZNewKey"), TEXT("ZNewValue") ); //currently failing TestTrue( TEXT("ContextA < ContextAClone"), ContextA < ContextAClone ); // Removing a key metadata entry ContextAClone = ContextA; ContextAClone.KeyMetadataObj->RemoveField( TEXT("TargetPlurality") ) ; TestTrue( TEXT("ContextAClone < ContextA"), ContextAClone < ContextA ); // Changing a key metadata entry value ContextAClone = ContextA; ContextAClone.KeyMetadataObj->SetStringField( TEXT("TargetPlurality"), TEXT("A") ) ; TestTrue( TEXT("ContextAClone < ContextA"), ContextAClone < ContextA ); FContext ContextEmptyA; FContext ContextEmptyB; TestFalse( TEXT("ContextEmptyA < ContextEmptyB"), ContextEmptyA < ContextEmptyB ); ContextEmptyB.KeyMetadataObj = MakeShareable( new FLocMetadataObject ); TestFalse( TEXT("ContextEmptyA < ContextEmptyB"), ContextEmptyA < ContextEmptyB ); TestFalse( TEXT("ContextEmptyB < ContextEmptyA"), ContextEmptyB < ContextEmptyA ); ContextEmptyB.KeyMetadataObj->SetStringField(TEXT("AMetadataKey"), TEXT("AMetadataValue")); TestTrue( TEXT("ContextEmptyA < ContextEmptyB"), ContextEmptyA < ContextEmptyB ); } } return true; }
bool FGuidTest::RunTest( const FString& Parameters ) { FGuid g = FGuid(305419896, 2271560481, 305419896, 2271560481); // string conversions TestEqual(TEXT("String conversion (Default) must return EGuidFormats::Digits string"), g.ToString(), g.ToString(EGuidFormats::Digits)); TestEqual<FString>(TEXT("String conversion (EGuidFormats::Digits)"), g.ToString(EGuidFormats::Digits), TEXT("12345678876543211234567887654321")); TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphens)"), g.ToString(EGuidFormats::DigitsWithHyphens), TEXT("12345678-8765-4321-1234-567887654321")); TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphensInBraces)"), g.ToString(EGuidFormats::DigitsWithHyphensInBraces), TEXT("{12345678-8765-4321-1234-567887654321}")); TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphensInParentheses)"), g.ToString(EGuidFormats::DigitsWithHyphensInParentheses), TEXT("(12345678-8765-4321-1234-567887654321)")); TestEqual<FString>(TEXT("String conversion (EGuidFormats::HexValuesInBraces)"), g.ToString(EGuidFormats::HexValuesInBraces), TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}")); TestEqual<FString>(TEXT("String conversion (EGuidFormats::UniqueObjectGuid)"), g.ToString(EGuidFormats::UniqueObjectGuid), TEXT("12345678-87654321-12345678-87654321")); // parsing valid strings (exact) FGuid g2_1; TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::Digits)"), FGuid::ParseExact(TEXT("12345678876543211234567887654321"), EGuidFormats::Digits, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::Digits)"), g2_1, g); TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphens)"), FGuid::ParseExact(TEXT("12345678-8765-4321-1234-567887654321"), EGuidFormats::DigitsWithHyphens, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphens)"), g2_1, g); TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInBraces)"), FGuid::ParseExact(TEXT("{12345678-8765-4321-1234-567887654321}"), EGuidFormats::DigitsWithHyphensInBraces, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInBraces)"), g2_1, g); TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInParentheses)"), FGuid::ParseExact(TEXT("(12345678-8765-4321-1234-567887654321)"), EGuidFormats::DigitsWithHyphensInParentheses, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInParentheses)"), g2_1, g); TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::HexValuesInBraces)"), FGuid::ParseExact(TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}"), EGuidFormats::HexValuesInBraces, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::HexValuesInBraces)"), g2_1, g); TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::UniqueObjectGuid)"), FGuid::ParseExact(TEXT("12345678-87654321-12345678-87654321"), EGuidFormats::UniqueObjectGuid, g2_1)); TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::UniqueObjectGuid)"), g2_1, g); // parsing invalid strings (exact) // parsing valid strings (automatic) FGuid g3_1; TestTrue(TEXT("Parsing valid strings must succeed (12345678876543211234567887654321)"), FGuid::Parse(TEXT("12345678876543211234567887654321"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed (12345678876543211234567887654321)"), g3_1, g); TestTrue(TEXT("Parsing valid strings must succeed (12345678-8765-4321-1234-567887654321)"), FGuid::Parse(TEXT("12345678-8765-4321-1234-567887654321"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed (12345678-8765-4321-1234-567887654321)"), g3_1, g); TestTrue(TEXT("Parsing valid strings must succeed ({12345678-8765-4321-1234-567887654321})"), FGuid::Parse(TEXT("{12345678-8765-4321-1234-567887654321}"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed ({12345678-8765-4321-1234-567887654321})"), g3_1, g); TestTrue(TEXT("Parsing valid strings must succeed ((12345678-8765-4321-1234-567887654321))"), FGuid::Parse(TEXT("(12345678-8765-4321-1234-567887654321)"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed ((12345678-8765-4321-1234-567887654321))"), g3_1, g); TestTrue(TEXT("Parsing valid strings must succeed ({0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}})"), FGuid::Parse(TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed ({0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}})"), g3_1, g); TestTrue(TEXT("Parsing valid strings must succeed (12345678-87654321-12345678-87654321)"), FGuid::Parse(TEXT("12345678-87654321-12345678-87654321"), g3_1)); TestEqual(TEXT("Parsing valid strings must succeed (12345678-87654321-12345678-87654321)"), g3_1, g); //parsing invalid strings (automatic) // GUID validation FGuid g4_1 = FGuid::NewGuid(); TestTrue(TEXT("New GUIDs must be valid"), g4_1.IsValid()); g4_1.Invalidate(); TestFalse(TEXT("Invalidated GUIDs must be invalid"), g4_1.IsValid()); return true; }
bool FAnalyticStartUpSimTest::RunTest(const FString& Parameters) { if (FEngineAnalytics::IsAvailable()) { //Setup a temp AccountID. FGuid TempAccountID(FGuid::NewGuid()); FString OldEpicAccountID = FPlatformMisc::GetEpicAccountId(); FString NewEpicAccountID = TempAccountID.ToString().ToLower(); FPlatformMisc::SetEpicAccountId(NewEpicAccountID); //Setup the 'Event Attributes' TArray<FAnalyticsEventAttribute> EventAttributes; EventAttributes.Add(FAnalyticsEventAttribute(TEXT("MachineID"), FPlatformMisc::GetMachineId().ToString(EGuidFormats::Digits).ToLower())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("AccountID"), FPlatformMisc::GetEpicAccountId())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OSID"), FPlatformMisc::GetOperatingSystemId())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("GameName"), FApp::GetGameName())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("CommandLine"), FCommandLine::Get())); //Record the event with the 'Engine.AutomationTest.Analytics.ProgramStartedEvent' title FEngineAnalytics::GetProvider().RecordEvent(TEXT("Engine.AutomationTest.Analytics.ProgramStartedEvent"), EventAttributes); //Get the event strings used FString MachineIDTest = FPlatformMisc::GetMachineId().ToString(EGuidFormats::Digits).ToLower(); FString AccountIDTest = FPlatformMisc::GetEpicAccountId(); FString OSID = FPlatformMisc::GetOperatingSystemId(); FString GameNameTest = FApp::GetGameName(); FString CommandLineArgs = FCommandLine::Get(); //Test the strings to verify they have data. TestFalse(TEXT("'MachineID' is not expected to be empty!"), MachineIDTest.IsEmpty()); TestFalse(TEXT("'AccountID' is not expected to be empty!"), AccountIDTest.IsEmpty()); TestFalse(TEXT("'OperatingSystemID' is not expected to be empty!"), OSID.IsEmpty()); TestFalse(TEXT("'GameName' is expected."), GameNameTest.IsEmpty()); //Verify record event is holding the actual data. This only triggers if the command line argument of 'AnalyticsDisableCaching' was used. if (CommandLineArgs.Contains(TEXT("AnalyticsDisableCaching"))) { FString FullMachineIDTestEventName = FString::Printf(TEXT("MachineID\":\"%s"), *MachineIDTest); FString FullAccountIDTestEventName = FString::Printf(TEXT("AccountID\":\"%s"), *AccountIDTest); FString FullOSIDTestEventName = FString::Printf(TEXT("OSID\":\"%s"), *OSID); for (int32 i = 0; i < ExecutionInfo.LogItems.Num(); i++) { if (ExecutionInfo.LogItems[i].Contains(TEXT("Engine.AutomationTest.Analytics.ProgramStartedEvent"))) { TestTrue(TEXT("Recorded event name is expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(TEXT("Engine.AutomationTest.Analytics.ProgramStartedEvent"))); TestTrue(TEXT("'MachineID' is expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(*FullMachineIDTestEventName)); TestTrue(TEXT("'AccountID' is expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(*FullAccountIDTestEventName)); TestTrue(TEXT("'OperatingSystemID' is expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(*FullOSIDTestEventName)); TestTrue(TEXT("'GameName' is expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(*GameNameTest)); TestTrue(TEXT("'CommandLine arguments' are expected to be in the sent event."), ExecutionInfo.LogItems[i].Contains(TEXT("AnalyticsDisableCaching"))); } } } //Set the AccountID to it's original state. FPlatformMisc::SetEpicAccountId(OldEpicAccountID); return true; } ExecutionInfo.LogItems.Add(TEXT("SKIPPED 'FAnalyticStartUpSimTest' test. EngineAnalytics are not currently available.")); return true; }
bool FRangeBoundTest::RunTest( const FString& Parameters ) { // ensure template instantiation works FDateRange DateRange; FDoubleRange DoubleRange; FFloatRange FloatRange; FInt8Range Int8Range; FInt16Range Int16Range; FInt32Range Int32Range; FInt64Range Int64Range; // bound types must be correct after construction FFloatRangeBound b1_1 = FFloatRangeBound::Exclusive(2.0f); FFloatRangeBound b1_2 = FFloatRangeBound::Inclusive(2.0f); FFloatRangeBound b1_3 = FFloatRangeBound::Open(); FFloatRangeBound b1_4 = 2; TestTrue(TEXT("Exclusive bound constructor must create exclusive bound"), b1_1.IsExclusive()); TestTrue(TEXT("Exclusive bound constructor must create closed bound"), b1_1.IsClosed()); TestFalse(TEXT("Exclusive bound constructor must not create inclusive bound"), b1_1.IsInclusive()); TestFalse(TEXT("Exclusive bound constructor must not create open bound"), b1_1.IsOpen()); TestEqual(TEXT("Exclusive bound constructor must create the correct value"), b1_1.GetValue(), 2.0f); TestTrue(TEXT("Inclusive bound constructor must create exclusive bound"), b1_2.IsInclusive()); TestTrue(TEXT("Inclusive bound constructor must create closed bound"), b1_2.IsClosed()); TestFalse(TEXT("Inclusive bound constructor must not create exclusive bound"), b1_2.IsExclusive()); TestFalse(TEXT("Inclusive bound constructor must not create open bound"), b1_2.IsOpen()); TestEqual(TEXT("Inclusive bound constructor must create the correct value"), b1_2.GetValue(), 2.0f); TestTrue(TEXT("Open bound constructor must create open bound"), b1_3.IsOpen()); TestFalse(TEXT("Open bound constructor must not create closed bound"), b1_3.IsClosed()); TestFalse(TEXT("Open bound constructor must not create exclusive bound"), b1_3.IsExclusive()); TestFalse(TEXT("Open bound constructor must not create inclusive bound"), b1_3.IsInclusive()); TestTrue(TEXT("Implicit constructor must create an inclusive bound"), b1_4.IsInclusive()); TestEqual(TEXT("Implicit constructor must create the correct value"), b1_4, b1_2); // comparisons must be correct FFloatRangeBound b2_1 = FFloatRangeBound::Exclusive(2.0f); FFloatRangeBound b2_2 = FFloatRangeBound::Exclusive(2.0f); FFloatRangeBound b2_3 = FFloatRangeBound::Inclusive(2.0f); FFloatRangeBound b2_4 = FFloatRangeBound::Inclusive(2.0f); FFloatRangeBound b2_5 = FFloatRangeBound::Open(); FFloatRangeBound b2_6 = FFloatRangeBound::Open(); TestTrue(TEXT("Equal exclusive bounds must be equal"), b2_1 == b2_2); TestTrue(TEXT("Equal inclusive bounds must be equal"), b2_3 == b2_4); TestTrue(TEXT("Open bounds must be equal"), b2_5 == b2_6); TestFalse(TEXT("Equal exclusive bounds must not be unequal"), b2_1 != b2_2); TestFalse(TEXT("Equal inclusive bounds must not be unequal"), b2_3 != b2_4); TestFalse(TEXT("Open bounds must not be unequal"), b2_5 != b2_6); FFloatRangeBound b2_7 = FFloatRangeBound::Exclusive(3.0f); FFloatRangeBound b2_8 = FFloatRangeBound::Inclusive(3.0f); TestTrue(TEXT("Unequal exclusive bounds must be unequal"), b2_1 != b2_7); TestTrue(TEXT("Unequal inclusive bounds must be unequal"), b2_2 != b2_8); TestFalse(TEXT("Unequal exclusive bounds must not be equal"), b2_1 == b2_7); TestFalse(TEXT("Unequal inclusive bounds must not be equal"), b2_2 == b2_8); // min-max comparisons between bounds must be correct FFloatRangeBound b3_1 = FFloatRangeBound::Exclusive(2.0f); FFloatRangeBound b3_2 = FFloatRangeBound::Inclusive(2.0f); FFloatRangeBound b3_3 = FFloatRangeBound::Open(); TestEqual(TEXT("'[2' must be less than '(2' <1>"), FFloatRangeBound::MinLower(b3_2, b3_1), b3_2); TestEqual(TEXT("'[2' must be less than '(2' <2>"), FFloatRangeBound::MinLower(b3_1, b3_2), b3_2); TestEqual(TEXT("Open lower bound must be less than '(2' <1>"), FFloatRangeBound::MinLower(b3_3, b3_1), b3_3); TestEqual(TEXT("Open lower bound must be less than '(2' <2>"), FFloatRangeBound::MinLower(b3_1, b3_3), b3_3); TestEqual(TEXT("Open lower bound must be less than '[2' <1>"), FFloatRangeBound::MinLower(b3_3, b3_2), b3_3); TestEqual(TEXT("Open lower bound must be less than '[2' <2>"), FFloatRangeBound::MinLower(b3_2, b3_3), b3_3); TestEqual(TEXT("'(2' must be greater than '[2' <1>"), FFloatRangeBound::MaxLower(b3_2, b3_1), b3_1); TestEqual(TEXT("'(2' must be greater than '[2' <2>"), FFloatRangeBound::MaxLower(b3_1, b3_2), b3_1); TestEqual(TEXT("'(2' must be greater than open lower bound <1>"), FFloatRangeBound::MaxLower(b3_3, b3_1), b3_1); TestEqual(TEXT("'(2' must be greater than open lower bound <2>"), FFloatRangeBound::MaxLower(b3_1, b3_3), b3_1); TestEqual(TEXT("'[2' must be greater than open lower bound <1>"), FFloatRangeBound::MaxLower(b3_3, b3_2), b3_2); TestEqual(TEXT("'[2' must be greater than open lower bound <2>"), FFloatRangeBound::MaxLower(b3_2, b3_3), b3_2); TestEqual(TEXT("'2)' must be less than '2]' <1>"), FFloatRangeBound::MinUpper(b3_2, b3_1), b3_1); TestEqual(TEXT("'2)' must be less than '2]' <2>"), FFloatRangeBound::MinUpper(b3_1, b3_2), b3_1); TestEqual(TEXT("'2)' must be less than open upper bound <1>"), FFloatRangeBound::MinUpper(b3_3, b3_1), b3_1); TestEqual(TEXT("'2)' must be less than open upper bound <2>"), FFloatRangeBound::MinUpper(b3_1, b3_3), b3_1); TestEqual(TEXT("'2]' must be less than open upper bound <1>"), FFloatRangeBound::MinUpper(b3_3, b3_2), b3_2); TestEqual(TEXT("'2]' must be less than open upper bound"), FFloatRangeBound::MinUpper(b3_2, b3_3), b3_2); TestEqual(TEXT("'2]' must be greater than '2)' <1>"), FFloatRangeBound::MaxUpper(b3_2, b3_1), b3_2); TestEqual(TEXT("'2]' must be greater than '2)' <2>"), FFloatRangeBound::MaxUpper(b3_1, b3_2), b3_2); TestEqual(TEXT("Open upper bound must be greater than '2)' <1>"), FFloatRangeBound::MaxUpper(b3_3, b3_1), b3_3); TestEqual(TEXT("Open upper bound must be greater than '2)' <2>"), FFloatRangeBound::MaxUpper(b3_1, b3_3), b3_3); TestEqual(TEXT("Open upper bound must be greater than '2]' <1>"), FFloatRangeBound::MaxUpper(b3_3, b3_2), b3_3); TestEqual(TEXT("Open upper bound must be greater than '2]' <2>"), FFloatRangeBound::MaxUpper(b3_2, b3_3), b3_3); FFloatRangeBound b4_1 = FFloatRangeBound::Exclusive(3); FFloatRangeBound b4_2 = FFloatRangeBound::Inclusive(3); TestEqual(TEXT("'(2' must be less than '[3' <1>"), FFloatRangeBound::MinLower(b3_1, b4_2), b3_1); TestEqual(TEXT("'(2' must be less than '[3' <2>"), FFloatRangeBound::MinLower(b4_2, b3_1), b3_1); TestEqual(TEXT("'[2' must be less than '[3' <1>"), FFloatRangeBound::MinLower(b3_2, b4_2), b3_2); TestEqual(TEXT("'[2' must be less than '[3' <2>"), FFloatRangeBound::MinLower(b4_2, b3_2), b3_2); TestEqual(TEXT("'[3' must be greater than '(2' <1>"), FFloatRangeBound::MaxLower(b3_1, b4_2), b4_2); TestEqual(TEXT("'[3' must be greater than '(2' <2>"), FFloatRangeBound::MaxLower(b4_2, b3_1), b4_2); TestEqual(TEXT("'[3' must be greater than '[2' <1>"), FFloatRangeBound::MaxLower(b3_2, b4_2), b4_2); TestEqual(TEXT("'[3' must be greater than '[2' <2>"), FFloatRangeBound::MaxLower(b4_2, b3_2), b4_2); return true; }
bool FTripleBufferTest::RunTest(const FString& Parameters) { // uninitialized buffer { TTripleBuffer<int32> Buffer(NoInit); TestFalse(TEXT("Uninitialized triple buffer must not be dirty"), Buffer.IsDirty()); } // initialized buffer { TTripleBuffer<int32> Buffer(1); TestFalse(TEXT("Initialized triple buffer must not be dirty"), Buffer.IsDirty()); TestEqual(TEXT("Initialized triple buffer must have correct read buffer value"), Buffer.Read(), 1); Buffer.SwapReadBuffers(); TestEqual(TEXT("Initialized triple buffer must have correct temp buffer value"), Buffer.Read(), 1); Buffer.SwapWriteBuffers(); TestTrue(TEXT("Write buffer swap must set dirty flag"), Buffer.IsDirty()); Buffer.SwapReadBuffers(); TestFalse(TEXT("Read buffer swap must clear dirty flag"), Buffer.IsDirty()); TestEqual(TEXT("Initialized triple buffer must have correct temp buffer value"), Buffer.Read(), 1); } // pre-set buffer { int32 Array[3] = { 1, 2, 3 }; TTripleBuffer<int32> Buffer(Array); int32 Read = Buffer.Read(); TestEqual(TEXT("Pre-set triple buffer must have correct Read buffer value"), Read, 3); Buffer.SwapReadBuffers(); int32 Temp = Buffer.Read(); TestEqual(TEXT("Pre-set triple buffer must have correct Temp buffer value"), Temp, 1); Buffer.SwapWriteBuffers(); Buffer.SwapReadBuffers(); int32 Write = Buffer.Read(); TestEqual(TEXT("Pre-set triple buffer must have correct Write buffer value"), Write, 2); } // operations { TTripleBuffer<int32> Buffer; for (int32 Index = 0; Index < 6; ++Index) { int32& Write = Buffer.GetWriteBuffer(); Write = Index; Buffer.SwapWriteBuffers(); Buffer.SwapReadBuffers(); TestEqual(*FString::Printf(TEXT("Triple buffer must read correct value (%i)"), Index), Buffer.Read(), Index); } FRandomStream Rand; int32 LastRead = -1; for (int32 Index = 0; Index < 100; ++Index) { int32 Writes = Rand.GetUnsignedInt() % 4; while (Writes > 0) { int32& Write = Buffer.GetWriteBuffer(); Write = Index; Buffer.SwapWriteBuffers(); --Writes; } int32 Reads = Rand.GetUnsignedInt() % 4; while (Reads > 0) { if (!Buffer.IsDirty()) { break; } Buffer.SwapReadBuffers(); int32 Read = Buffer.Read(); TestTrue(TEXT("Triple buffer must read in increasing order"), Read > LastRead); LastRead = Read; --Reads; } } } return true; }
/** * Perform LineTraceSingleByChannel tests. Does a ray trace from a given point to a given shape mesh and verifies blocking is correct. * Data for tests is in the [/Script/UnrealEd.CollisionAutomationTestConfigData] section of BaseEditor.ini * * @param Parameters - Unused for this test * @return TRUE if the test was successful, FALSE otherwise */ bool FLineTraceSingleByChannel::RunTest(const FString& Parameters) { // Create map UWorld* World = FAutomationEditorCommonUtils::CreateNewMap(); TestNotNull(TEXT("Failed to create world for Physics.Collision.Ray Test. Tests aborted."), World); CollisionAutomationTests::TestBase = this; static FName TraceIdent = FName(TEXT("TestTrace")); FVector StartPos; FVector EndPos; ECollisionChannel Channel = ECC_WorldStatic; UCollisionAutomationTestConfigData* Data = UCollisionAutomationTestConfigData::StaticClass()->GetDefaultObject<UCollisionAutomationTestConfigData>(); for (int32 iTest = 0; iTest < Data->LineTraceSingleByChannelTests.Num(); iTest++) { FCollisionTestEntry OneElement = Data->LineTraceSingleByChannelTests[iTest]; AStaticMeshActor* TestRayMeshActor = CollisionAutomationTests::CreateShapeMeshActor(*OneElement.RootShapeAsset, OneElement.HitResult.TraceEnd); if (TestRayMeshActor != nullptr) { // Create the Actor to check against TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.SetCollisionProfileName(TEXT("BlockAll")); TestRayMeshActor->SetActorEnableCollision(true); TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.bSimulatePhysics = true; // Setup trace start/end StartPos = OneElement.HitResult.TraceStart; EndPos = TestRayMeshActor->GetActorLocation(); // Do the trace FHitResult OutHit; bool WasBlocked = World->LineTraceSingleByChannel(OutHit,StartPos,EndPos,Channel); bool BlockedBySpecified = false; if (WasBlocked == true) { if (OutHit.GetActor() == TestRayMeshActor) { BlockedBySpecified = true; // This generates a snippet you can copy/paste into the ini file for test validation //UE_LOG(CollisionAutomationTestLog, Log, TEXT("%d:HitResult=(%s)"), iTest + 1, *(CollisionAutomationTests::HitToString(OutHit))); CollisionAutomationTests::CheckVector(OutHit.ImpactNormal, OneElement.HitResult.ImpactNormal, TEXT("LineTraceSingleByChannel"), TEXT("ImpactNormal"), iTest); CollisionAutomationTests::CheckVector(OutHit.Normal, OneElement.HitResult.Normal, TEXT("LineTraceSingleByChannel"), TEXT("Normal"), iTest); CollisionAutomationTests::CheckVector(OutHit.ImpactPoint, OneElement.HitResult.ImpactPoint, TEXT("LineTraceSingleByChannel"), TEXT("ImpactPoint"), iTest); CollisionAutomationTests::CheckFloat(OutHit.Time, OneElement.HitResult.Time, TEXT("LineTraceSingleByChannel"), TEXT("Time"), iTest); } } TestTrue(FString::Printf(TEXT("Test %d:LineTraceSingleByChannel to %s failed. Should return blocking hit"), iTest + 1, *TestRayMeshActor->GetName()), BlockedBySpecified); // Change the collision profile and ensure we dont get a blocking hit UShapeComponent* CollisionComponent = Cast<UShapeComponent>(TestRayMeshActor->GetRootComponent()); if (CollisionComponent != nullptr) { CollisionComponent->SetCollisionProfileName(TEXT("OverlapAll")); CollisionComponent->SetSimulatePhysics(true); } TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.SetCollisionProfileName(TEXT("OverlapAll")); WasBlocked = World->LineTraceSingleByChannel(OutHit, StartPos, EndPos, Channel); TestFalse(FString::Printf(TEXT("Test %d:LineTraceSingleByChannel to %s failed. Should not return blocking hit"), iTest + 1, *TestRayMeshActor->GetName()), WasBlocked); } // Remove the actor TestRayMeshActor->Destroy(); } return true; }
bool FArchiveTest::RunTest( const FString& Parameters ) { // Key metadata TSharedPtr< FLocMetadataObject > KeyMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > KeyMetadataB = MakeShareable( new FLocMetadataObject ); // Source metadata TSharedPtr< FLocMetadataObject > SourceMetadataA = MakeShareable( new FLocMetadataObject ); TSharedPtr< FLocMetadataObject > SourceMetadataB = MakeShareable( new FLocMetadataObject ); // Setup KeyMetadataA KeyMetadataA->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataA->SetStringField( TEXT("TargetGender" ), TEXT("Masculine") ); KeyMetadataA->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup KeyMetadataB KeyMetadataB->SetStringField( TEXT("Gender" ), TEXT("Masculine") ); KeyMetadataB->SetStringField( TEXT("Plurality" ), TEXT("Singular") ); KeyMetadataB->SetStringField( TEXT("TargetGender" ), TEXT("Feminine") ); KeyMetadataB->SetStringField( TEXT("TargetPlurality"), TEXT("Singular") ); // Setup source metadata SourceMetadataA->SetBoolField( TEXT("*IsMature"), false ); SourceMetadataB->SetBoolField( TEXT("*IsMature"), true ); // Setup source item FLocItem SourceA( TEXT("TextA") ); SourceA.MetadataObj = MakeShareable( new FLocMetadataObject(*SourceMetadataA) ); FLocItem Translation = SourceA; Translation.Text = TEXT("TranslatedTextA"); FString TestNamespace = TEXT("TestNamespace"); FString SourceAKey = TEXT("TextA"); // Test entry add { bool TestOptionalTrue = true; bool TestOptionalFalse = false; // bIsOptional is not used as a key. We ensure adding entries where the bIsOptional member is the only difference works as expected. FInternationalizationArchive TestArchive; TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, NULL, TestOptionalTrue ); // Add duplicate entry that differs in bIsOptional flag. This add should report success because we already have an entry with matching // namespace/source/keymetadata. Differences in bIsOptional are not taken into consideration. bool bResult = TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, NULL, TestOptionalFalse ); TestTrue( TEXT("AddEntry result = true"), bResult); // We should only have one entry in the archive int32 EntryCount = 0; for(auto Iter = TestArchive.GetEntriesBySourceTextIterator(); Iter; ++Iter, ++EntryCount); TestEqual( TEXT("EntryCount == 1"), EntryCount, 1 ); // Make sure the original bIsOptional value is not overwritten by our second add. TSharedPtr< FArchiveEntry > FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, NULL ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->bIsOptional == TestOptionalTrue ); } } // Test lookup an entry { { FInternationalizationArchive TestArchive; TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, KeyMetadataA, false ); TSharedPtr< FArchiveEntry > FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, KeyMetadataA ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->Namespace == TestNamespace ); TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == SourceA ); TestTrue( TEXT("FoundEntry->Translation == Translation"), FoundEntry->Translation == Translation ); if( FoundEntry->KeyMetadataObj == KeyMetadataA ) { AddError(TEXT("FArchiveEntry KeyMetadataObj is not a unique object.")); } TestTrue( TEXT("FoundEntry->KeyMetadataObj == KeyMetadataA"), *(FoundEntry->KeyMetadataObj) == *(KeyMetadataA) ); } // Passing in a mismatched key metadata will fail to find the entry. Any fallback logic is intended to happen at runtime FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, NULL ); TestInvalid( TEXT("!FoundEntry.IsValid()"), FoundEntry); FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, MakeShareable( new FLocMetadataObject() ) ); TestInvalid( TEXT("!FoundEntry.IsValid()"), FoundEntry); FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, KeyMetadataB ); TestInvalid( TEXT("!FoundEntry.IsValid()"), FoundEntry); } // Ensure we can properly lookup entries with non-null but empty key metadata { FInternationalizationArchive TestArchive; TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, MakeShareable( new FLocMetadataObject() ), false ); TSharedPtr< FArchiveEntry > FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, NULL ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->Namespace == TestNamespace ); TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == SourceA ); } } // Ensure we can properly lookup entries with null key metadata { FInternationalizationArchive TestArchive; TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, NULL, false ); TSharedPtr< FArchiveEntry > FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, NULL ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->Namespace == TestNamespace ); TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == SourceA ); } // Test lookup with non-null but empty key metadata FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, MakeShareable( new FLocMetadataObject() ) ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->Namespace == TestNamespace ); TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == SourceA ); } } // Ensure lookup where source metadata has * prefixed entries work as expected. Note: The source metadata object // supports a * prefix on metadata names which modifies the way we perform metadata comparison(ignores entry type and value, only name is checked) { FLocItem SourceCompare( TEXT("TextA") ); SourceCompare.MetadataObj = MakeShareable( new FLocMetadataObject() ); SourceCompare.MetadataObj->SetStringField( TEXT("*IsMature"), TEXT("") ); FInternationalizationArchive TestArchive; // Added entry with String *IsMature entry TestArchive.AddEntry( TestNamespace, SourceAKey, SourceCompare, Translation, KeyMetadataA, false ); // Finding entry using a source that has Boolean *IsMature TSharedPtr< FArchiveEntry > FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, KeyMetadataA ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { TestTrue( TEXT("FoundEntry->Namespace == Namespace"), FoundEntry->Namespace == TestNamespace ); TestTrue( TEXT("FoundEntry->Source == Source"), FoundEntry->Source == SourceA ); } // Attempting to add an entry that only differs by a * prefexed source metadata entry value or type will result in success since // a 'matching' entry already exists in the archive. We should, however, only have one entry in the archive bool bResult = TestArchive.AddEntry( TestNamespace, SourceAKey, SourceA, Translation, KeyMetadataA, false ); TestTrue( TEXT("AddEntry result = true"), bResult); // We should only have one entry in the archive int32 EntryCount = 0; for(auto Iter = TestArchive.GetEntriesBySourceTextIterator(); Iter; ++Iter, ++EntryCount); TestEqual( TEXT("EntryCount == 1"), EntryCount, 1 ); // Check to see that the original type/value of the * prefixed entry did not get modified FoundEntry = TestArchive.FindEntryByKey( TestNamespace, SourceAKey, KeyMetadataA ); if( !FoundEntry.IsValid() ) { AddError(TEXT("FArchiveEntry could not find entry using FindEntryByKey.")); } else { if( FoundEntry->Source.MetadataObj->HasTypedField< ELocMetadataType::String >( TEXT("*IsMature") ) ) { TestTrue( TEXT("Metadata Type == String and Value == Empty string"), FoundEntry->Source.MetadataObj->GetStringField( TEXT("*IsMature") ) == TEXT("") ); } else { AddError(TEXT("FArchiveEntry * prefixed metadata entry on source object was modified unexpectedly.")); } } } } return true; }