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 FViewportShowflagsToggleOffTest::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 disabled. ViewportClient->EngineShowFlags.SetSingleFlag(FlagIndex, false); // VERIFY // bool NewFlagState = ViewportClient->EngineShowFlags.GetSingleFlag(FlagIndex); TestFalse(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; }
/** * 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 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 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 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 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; }
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; }
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; }