void Test1(TUint32 aInt, TInt aDivisorExp) { TRealX realx; SRatio r0x; SRatio r0; SRatio r1x; SRatio r1; TInt r; test.Printf(_L("Test1 %08x %d\n"), aInt, aDivisorExp); r = RatioSetValue(realx, aInt, aDivisorExp); test_KErrNone(r); r = RealToRatio(r0x, realx); test_KErrNone(r); r = Driver.RatioSet(r0, aInt, aDivisorExp); RatioPrint2("R0X,R0", r0x, r0); TestEqual(r0, r0x); Test1M(r0); r1x = r0x; r = RatioReciprocal(r1x); test_KErrNone(r); r1 = r0; r = Driver.RatioReciprocal(r1); test_KErrNone(r); RatioPrint2("R1X,R1", r1x, r1); TestEqual(r1, r1x); Test1M(r1); }
bool FCircularBufferTest::RunTest( const FString& Parameters ) { // buffer capacity TCircularBuffer<int32> b1_1(127); TCircularBuffer<int32> b1_2(128); TCircularBuffer<int32> b1_3(129); TestEqual(TEXT("Buffer capacity of 127 must be rounded up to 128"), b1_1.Capacity(), 128u); TestEqual(TEXT("Buffer capacity of 128 must not change"), b1_2.Capacity(), 128u); TestEqual(TEXT("Buffer capacity of 129 must be rounded up to 256"), b1_3.Capacity(), 256u); // initial values TCircularBuffer<int32> b2_1(64, 666); for (uint32 Index = 0; Index < b2_1.Capacity(); ++Index) { TestEqual(FString::Printf(TEXT("Initial value must be correct (%i)"), Index), b2_1[Index], 666); } // indexing TCircularBuffer<int32> b3_1(64, 0); TestEqual(TEXT("Next index from 0 must be 1"), b3_1.GetNextIndex(0), 1u); TestEqual(TEXT("Next index from 63 must be 0"), b3_1.GetNextIndex(63), 0u); TestEqual(TEXT("Next index from 64 must be 1"), b3_1.GetNextIndex(64), 1u); b3_1[0] = 42; b3_1[65] = 42; TestEqual(TEXT("Index 0 must be written and read correctly"), b3_1[0], 42); TestEqual(TEXT("Index 1 must be written and read correctly"), b3_1[1], 42); TestEqual(TEXT("Index 65 must be written and read correctly"), b3_1[65], 42); return true; }
void Test_ManaBuff() { const float BuffValue = 30.f; const float StartingMana = DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Mana; FActiveGameplayEffectHandle BuffHandle; // apply the buff { CONSTRUCT_CLASS(UGameplayEffect, DamageBuffEffect); AddModifier(DamageBuffEffect, GET_FIELD_CHECKED(UAbilitySystemTestAttributeSet, Mana), EGameplayModOp::Additive, FScalableFloat(BuffValue)); DamageBuffEffect->DurationPolicy = EGameplayEffectDurationType::Infinite; BuffHandle = SourceComponent->ApplyGameplayEffectToTarget(DamageBuffEffect, DestComponent, 1.f); } // check that the value changed TestEqual(SKILL_TEST_TEXT("Mana Buffed"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Mana, StartingMana + BuffValue); // remove the effect { DestComponent->RemoveActiveGameplayEffect(BuffHandle); } // check that the value changed back TestEqual(SKILL_TEST_TEXT("Mana Restored"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Mana, StartingMana); }
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; }
void Test_PeriodicDamage() { const int32 NumPeriods = 10; const float PeriodSecs = 1.0f; const float DamagePerPeriod = 5.f; const float StartingHealth = DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health; // just try and reduce the health attribute { CONSTRUCT_CLASS(UGameplayEffect, BaseDmgEffect); AddModifier(BaseDmgEffect, GET_FIELD_CHECKED(UAbilitySystemTestAttributeSet, Health), EGameplayModOp::Additive, FScalableFloat(-DamagePerPeriod)); BaseDmgEffect->DurationPolicy = EGameplayEffectDurationType::HasDuration; BaseDmgEffect->DurationMagnitude = FGameplayEffectModifierMagnitude(FScalableFloat(NumPeriods * PeriodSecs)); BaseDmgEffect->Period.Value = PeriodSecs; SourceComponent->ApplyGameplayEffectToTarget(BaseDmgEffect, DestComponent, 1.f); } int32 NumApplications = 0; // Tick a small number to verify the application tick TickWorld(SMALL_NUMBER); ++NumApplications; TestEqual(SKILL_TEST_TEXT("Health Reduced"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health, StartingHealth - (DamagePerPeriod * NumApplications)); // Tick a bit more to address possible floating point issues TickWorld(PeriodSecs * .1f); for (int32 i = 0; i < NumPeriods; ++i) { // advance time by one period TickWorld(PeriodSecs); ++NumApplications; // check that health has been reduced TestEqual(SKILL_TEST_TEXT("Health Reduced"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health, StartingHealth - (DamagePerPeriod * NumApplications)); } // advance time by one extra period TickWorld(PeriodSecs); // should not have reduced further TestEqual(SKILL_TEST_TEXT("Health Reduced"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health, StartingHealth - (DamagePerPeriod * NumApplications)); // TODO: test that the effect is no longer applied }
const char* MockOLED::drawGeneralMock(String stringToPrint,MockOLED& obj) { const char* conversion; const char* smaller; conversion = stringToPrint.c_str(); int printed = obj.MockPrintToOLED (conversion); //There's an interior method here that interacts with the OLED TestEqual ("drawGeneralPrintCheck", printed, 1 ); return conversion; }
void Test_InstantDamageRemap() { const float DamageValue = 5.f; const float StartingHealth = DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health; // This is the same as GameplayEffectsTest_InstantDamage but modifies the Damage attribute and confirms it is remapped to -Health by UAbilitySystemTestAttributeSet::PostAttributeModify { CONSTRUCT_CLASS(UGameplayEffect, BaseDmgEffect); AddModifier(BaseDmgEffect, GET_FIELD_CHECKED(UAbilitySystemTestAttributeSet, Damage), EGameplayModOp::Additive, FScalableFloat(DamageValue)); BaseDmgEffect->DurationPolicy = EGameplayEffectDurationType::Instant; SourceComponent->ApplyGameplayEffectToTarget(BaseDmgEffect, DestComponent, 1.f); } // Now we should have lost some health TestEqual(SKILL_TEST_TEXT("Health Reduced"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health, StartingHealth - DamageValue); // Confirm the damage attribute itself was reset to 0 when it was applied to health TestEqual(SKILL_TEST_TEXT("Damage Applied"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Damage, 0.f); }
void MockSDBeacon::writeToSD (String writeThisString, String fileName, MockSdFat& SD, MockFile& myFile) { //No good way to sensibly shorten const char* conversion = fileName.c_str(); String printedThis; //Serial.println (conversion); //myFile = SD.open(conversion); if (myFile.available()) { printedThis = myFile.println(writeThisString); myFile.close(); } else { Serial.println(F("error opening example.txt")); } TestEqual ("writeToSD", printedThis, writeThisString); }
int main(int argc, const char * argv[]) { auto obj = std::make_shared<HandShaking>(); TestEqual(obj->countPerfect(2), 1); TestEqual(obj->countPerfect(4), 2); TestEqual(obj->countPerfect(6), 5); TestEqual(obj->countPerfect(8), 14); TestEqual(obj->countPerfect(10), 42); TestEqual(obj->countPerfect(16), 1430); return 0; }
void Test_InstantDamage() { const float DamageValue = 5.f; const float StartingHealth = DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health; // just try and reduce the health attribute { CONSTRUCT_CLASS(UGameplayEffect, BaseDmgEffect); AddModifier(BaseDmgEffect, GET_FIELD_CHECKED(UAbilitySystemTestAttributeSet, Health), EGameplayModOp::Additive, FScalableFloat(-DamageValue)); BaseDmgEffect->DurationPolicy = EGameplayEffectDurationType::Instant; SourceComponent->ApplyGameplayEffectToTarget(BaseDmgEffect, DestComponent, 1.f); } // make sure health was reduced TestEqual(SKILL_TEST_TEXT("Health Reduced"), DestComponent->GetSet<UAbilitySystemTestAttributeSet>()->Health, StartingHealth - DamageValue); }
bool FIntSerializationTest::RunTest (const FString& Parameters) { //Create object for serialization //UIntSerialization SerializableObject; //SerializableObject-> auto SerializableObject = NewObject<UIntSerialization>(); SerializableObject->UnsignedInt8Variable = 255U; SerializableObject->UnsignedInt16Variable = 65535U; SerializableObject->UnsignedInt32Variable = 4294967295U; SerializableObject->UnsignedInt64Variable = 18446744073709551615U; SerializableObject->SignedInt8Variable = -128; SerializableObject->SignedInt16Variable = -32768; SerializableObject->SignedInt32Variable = 2147483647 ; SerializableObject->SignedInt64Variable = 9223372036854775807; //Serialize object //FArchive //FMemoryWriter SerializedData = new FMemoryWriter(; TArray<uint8> SaveData; FMemoryWriter OutAr(SaveData, true); SerializableObject->Serialize(OutAr); //Deserialize into new object FMemoryReader InAr(SaveData, true); auto DeSerializableObject = NewObject<UIntSerialization>(); DeSerializableObject->Serialize(InAr); //Compare test TestEqual(TEXT("int8 serialised and deserialised incorrectly"), SerializableObject->SignedInt8Variable, DeSerializableObject->SignedInt8Variable); TestEqual(TEXT("int16 serialised and deserialised incorrectly"), SerializableObject->SignedInt16Variable, DeSerializableObject->SignedInt16Variable); TestEqual(TEXT("int32 serialised and deserialised incorrectly"), SerializableObject->SignedInt32Variable, DeSerializableObject->SignedInt32Variable); TestEqual(TEXT("int64 serialised and deserialised incorrectly"), SerializableObject->SignedInt64Variable, DeSerializableObject->SignedInt64Variable); TestEqual(TEXT("uint8 serialised and deserialised incorrectly"), SerializableObject->UnsignedInt8Variable, DeSerializableObject->UnsignedInt8Variable); TestEqual(TEXT("uint16 serialised and deserialised incorrectly"), SerializableObject->UnsignedInt16Variable, DeSerializableObject->UnsignedInt16Variable); TestEqual(TEXT("uint32 serialised and deserialised incorrectly"), SerializableObject->UnsignedInt32Variable, DeSerializableObject->UnsignedInt32Variable); TestEqual(TEXT("uint64 serialised and deserialised incorrectly"), SerializableObject->UnsignedInt64Variable, DeSerializableObject->UnsignedInt64Variable); 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 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 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 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 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; }
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; }
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 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 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; }
void MockOLED::drawSetupMock(MockOLED& obj) { Serial.begin (9600); //alternately comment out if using more than one setup function TestTrue ("OLED init test", obj.exists); int printed = obj.MockPrintToOLED ("Setting Up"); //There's an interior method here that interacts with the OLED TestEqual ("drawSetup Print Check", printed, 1 ); }