using System; using System.Collections.Generic; using System.Globalization; using NUnit.Framework; using Robust.Shared.ContentPack; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Localization; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; using Robust.Shared.Utility; namespace Robust.UnitTesting.Shared.Localization { [TestFixture] internal sealed class LocalizationTests : RobustUnitTest { protected override Type[] ExtraComponents => new[] {typeof(GrammarComponent)}; [OneTimeSetUp] public void Setup() { IoCManager.Resolve().Initialize(); var res = IoCManager.Resolve(); res.MountString("/Locale/en-US/a.ftl", FluentCode); res.MountString("/EnginePrototypes/a.yml", YAMLCode); var protoMan = IoCManager.Resolve(); protoMan.RegisterKind(typeof(EntityPrototype), typeof(EntityCategoryPrototype)); protoMan.LoadDirectory(new ResPath("/EnginePrototypes")); protoMan.ResolveResults(); var loc = IoCManager.Resolve(); var culture = new CultureInfo("en-US", false); loc.Initialize(); loc.LoadCulture(culture); } private const string YAMLCode = @" # Values specified in prototype - type: entity id: PropsInPrototype name: A description: B suffix: C loc: gender: male proper: true # Values specified in fluent - type: entity id: PropsInLoc # Values specified in YAML but overriden by fluent. - type: entity id: PropsInLocOverriding name: XA description: XB suffix: XC loc: gender: female proper: false # Values specified in fluent at PARENT and replaced by child YAML. - type: entity id: TestInheritOverridingParent - type: entity id: TestInheritOverridingChild parent: TestInheritOverridingParent name: A description: B suffix: C loc: gender: male proper: true # Attribures stored in grammar component - type: entity id: PropsInGrammar name: A description: B suffix: C loc: gender: female proper: false components: - type: Grammar attributes: gender: male proper: true - type: entity id: GenderTestEntityNoComp - type: entity id: GenderTestEntityWithComp components: - type: Grammar attributes: gender: Female "; private const string FluentCode = @" enum-match = { $enum -> [foo] A *[bar] B } num-selector = { $num -> [0] A [1] B *[2] C } ent-GenderTestEntityNoComp = Gender Test Entity .gender = male .otherAttrib = sausages ent-GenderTestEntityWithComp = Gender Test Entity 2 ent-PropsInLoc = A .desc = B .suffix = C .gender = male .proper = true ent-PropsInLocOverriding = A .desc = B .suffix = C .gender = male .proper = true ent-TestInheritOverridingParent = XA .desc = XB .suffix = XC .gender = female .proper = false test-message-gender = { GENDER($entity) -> [male] male [female] female *[neuter] BAD } test-message-proper = { PROPER($entity) -> [true] true *[false] false } test-message-custom-attrib = { ATTRIB($entity, ""otherAttrib"") } "; [Test] public void TestEnumSelect() { var loc = IoCManager.Resolve(); Assert.That(loc.GetString("enum-match", ("enum", TestEnum.Foo)), Is.EqualTo("A")); Assert.That(loc.GetString("enum-match", ("enum", TestEnum.Bar)), Is.EqualTo("B")); Assert.That(loc.GetString("enum-match", ("enum", TestEnum.Baz)), Is.EqualTo("B")); } [Test] public void TestCustomFunctions() { var entMan = IoCManager.Resolve(); var testEntNoComp = entMan.CreateEntityUninitialized("GenderTestEntityNoComp"); var testEntWithComp = entMan.CreateEntityUninitialized("GenderTestEntityWithComp"); var loc = IoCManager.Resolve(); var genderFromAttrib = loc.GetString("test-message-gender", ("entity", testEntNoComp)); var genderFromGrammar = loc.GetString("test-message-gender", ("entity", testEntWithComp)); var customAttrib = loc.GetString("test-message-custom-attrib", ("entity", testEntNoComp)); Assert.Multiple(() => { Assert.That(genderFromAttrib, Is.EqualTo("male")); Assert.That(genderFromGrammar, Is.EqualTo("female")); Assert.That(customAttrib, Is.EqualTo("sausages")); }); } static IEnumerable NumericTestSource() { const byte b1 = 0, b2 = 1, b3 = 5; const sbyte sb1 = 0, sb2 = 1, sb3 = 5; const short sh1 = 0, sh2 = 1, sh3 = 5; const ushort ush1 = 0, ush2 = 1, ush3 = 5; const int i1 = 0, i2 = 1, i3 = 5; const uint ui1 = 0, ui2 = 1, ui3 = 5; const long lng1 = 0, lng2 = 1, lng3 = 5; const ulong ulng1 = 0, ulng2 = 1, ulng3 = 5; const float f1 = 0, f2 = 1, f3 = 5; const double d1 = 0, d2 = 1, d3 = 5; yield return new object[] { b1, b2, b3 }; yield return new object[] { sb1, sb2, sb3 }; yield return new object[] { sh1, sh2, sh3 }; yield return new object[] { ush1, ush2, ush3 }; yield return new object[] { i1, i2, i3 }; yield return new object[] { ui1, ui2, ui3 }; yield return new object[] { lng1, lng2, lng3 }; yield return new object[] { ulng1, ulng2, ulng3 }; yield return new object[] { f1, f2, f3 }; yield return new object[] { d1, d2, d3 }; } [Test] [TestCaseSource(nameof(NumericTestSource))] public void TestNumbers(object o1, object o2, object o3) { // Small test to check numbers are being properly converted var loc = IoCManager.Resolve(); var func = new Func(x1 => loc.GetString("num-selector", ("num", x1))); Assert.Multiple(() => { Assert.That(func(o1), Is.EqualTo("A")); Assert.That(func(o2), Is.EqualTo("B")); Assert.That(func(o3), Is.EqualTo("C")); }); } [Test] [TestCase("PropsInPrototype")] [TestCase("PropsInLoc")] [TestCase("PropsInLocOverriding")] [TestCase("PropsInGrammar")] [TestCase("TestInheritOverridingChild")] public void TestLocData(string prototype) { var loc = IoCManager.Resolve(); var entMan = IoCManager.Resolve(); var ent = entMan.CreateEntityUninitialized(prototype); Assert.That(IoCManager.Resolve().GetComponent(ent).EntityName, Is.EqualTo("A")); Assert.That(IoCManager.Resolve().GetComponent(ent).EntityDescription, Is.EqualTo("B")); Assert.That(IoCManager.Resolve().GetComponent(ent).EntityPrototype!.EditorSuffix, Is.EqualTo("C")); Assert.That(loc.GetString("test-message-gender", ("entity", ent)), Is.EqualTo("male")); Assert.That(loc.GetString("test-message-proper", ("entity", ent)), Is.EqualTo("true")); } private enum TestEnum { Foo, Bar, Baz } } }