Example #1
0
        public async Task TestFileChangeNotification()
        {
            // Prevent multiple tests accessing the app config.
            using (await _configFileLock.LockAsync())
            {
                // Get the test config file path.
                string filePath = TestConfigurationSection.Active.FilePath;

                Trace.WriteLine($"Configuration file: '{filePath}'");

                Assert.IsFalse(string.IsNullOrWhiteSpace(filePath));
                Assert.IsTrue(File.Exists(filePath));

                // Load config file directly (we load into string so we can recreate at end of the test.
                string original = File.ReadAllText(filePath);

                // Parse it and modify
                XDocument document    = XDocument.Parse(original);
                XElement  testElement = document.Element("test");
                Assert.IsNotNull(testElement);

                XElement customElement = testElement.Element("custom");
                Tuple <XObject, XObject> difference = customElement.DeepEquals(
                    TestConfigurationSection.Active.Custom,
                    XObjectComparisonOptions.Semantic);
                Assert.IsNull(difference, $"{difference?.Item1} : {difference?.Item2}");

                // Modify
                string str1Random = Tester.RandomString() ?? string.Empty;
                string str2Random = Tester.RandomString() ?? string.Empty;

                // Update the custom node.
                customElement.RemoveAll();
                XNamespace ns = customElement.Name.Namespace;
                customElement.Add(
                    new XElement(ns + "string1", str1Random),
                    new XElement(ns + "string2", str2Random));

                // Save file
                document.Save(filePath);

                // Check for changes
                ConfigurationSection <TestConfigurationSection> .ConfigurationChangedEventArgs change =
                    await WaitForChanges(new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token);

                Assert.IsNotNull(change);
                Assert.IsTrue(change.Contains("<test>"));
                Assert.IsTrue(change.WasChanged("<test><custom>"));

                XElement activeCustom = TestConfigurationSection.Active.Custom;
                Assert.IsNotNull(activeCustom);
                AssertString("custom", activeCustom.Name.LocalName, options: TextOptions.NormalizeLineEndings);
                AssertString(
                    str1Random,
                    activeCustom.Element("string1")?.Value,
                    options: TextOptions.NormalizeLineEndings);
                AssertString(
                    str2Random,
                    activeCustom.Element("string2")?.Value,
                    options: TextOptions.NormalizeLineEndings);

                // Revert
                File.WriteAllText(filePath, original);

                change = await WaitForChanges(new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token);

                Assert.IsNotNull(change);
                Assert.IsTrue(change.Contains("<test>"));
                Assert.IsTrue(change.WasChanged("<test><custom>"));
            }
        }
Example #2
0
        public async Task TestChangeNotificationAndSave()
        {
            // Prevent multiple tests accessing the app config.
            using (await _configFileLock.LockAsync())
            {
                Assert.IsTrue(TestConfigurationSection.Active.HasFile);
                XElement custom = TestConfigurationSection.Active.Custom;
                Assert.IsNotNull(custom);
                XElement custom2 = TestConfigurationSection.Active.Custom;
                Assert.IsNotNull(custom2);
                Assert.AreNotSame(
                    custom,
                    custom2,
                    "Get element should retrieve fresh XElement objects to prevent corruption.");

                // Get original values.
                string str1 = TestConfigurationSection.Active.String;
                string str2 = TestConfigurationSection.Active.String2;
                string cStr = custom.ToString(SaveOptions.DisableFormatting);
                Assert.AreEqual(cStr, custom2.ToString(SaveOptions.DisableFormatting));
                Assert.AreEqual("custom", custom.Name.LocalName);

                // Generate random values
                string str1Random = Tester.RandomString() ?? string.Empty;
                string str2Random = Tester.RandomString() ?? string.Empty;

                // Update the custom node.
                XNamespace ns = custom.Name.Namespace;
                TestConfigurationSection.Active.Custom = new XElement(
                    ns + "custom",
                    new XElement(ns + "string1", str1Random),
                    new XElement(ns + "string2", str2Random));

                TestConfigurationSection.Active.String  = str1Random;
                TestConfigurationSection.Active.String2 = str2Random;
                TestConfigurationSection.Active.Save();

                // Check for changes
                ConfigurationSection <TestConfigurationSection> .ConfigurationChangedEventArgs change =
                    await WaitForChanges(new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token);

                Assert.IsNotNull(change);
                Assert.IsTrue(change.WasChanged("<test>"));
                Assert.IsTrue(change.Contains("<test><custom>"));
                Assert.IsTrue(change.Contains("<test>.string"));
                Assert.IsTrue(change.Contains("<test>.string2"));

                custom = TestConfigurationSection.Active.Custom;
                Assert.IsNotNull(custom);
                Assert.AreEqual("custom", custom.Name.LocalName);
                AssertString(str1Random, custom.Element("string1")?.Value, options: TextOptions.NormalizeLineEndings);
                AssertString(str2Random, custom.Element("string2")?.Value, options: TextOptions.NormalizeLineEndings);
                AssertString(
                    str1Random,
                    TestConfigurationSection.Active.String,
                    options: TextOptions.NormalizeLineEndings);
                AssertString(
                    str2Random,
                    TestConfigurationSection.Active.String2,
                    options: TextOptions.NormalizeLineEndings);

                // Revert

                // Update the custom node.
                TestConfigurationSection.Active.Custom  = XElement.Parse(cStr, LoadOptions.PreserveWhitespace);
                TestConfigurationSection.Active.String  = str1;
                TestConfigurationSection.Active.String2 = str2;
                TestConfigurationSection.Active.Save();

                // Check for changeschange =
                change = await WaitForChanges(new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token);

                Assert.IsNotNull(change);
                Assert.IsTrue(change.WasChanged("<test>"));
                Assert.IsTrue(change.Contains("<test><custom>"));
                Assert.IsTrue(change.Contains("<test>.string"));
                Assert.IsTrue(change.Contains("<test>.string2"));

                custom = TestConfigurationSection.Active.Custom;
                Assert.IsNotNull(change);
                AssertString("custom", custom.Name.LocalName, options: TextOptions.NormalizeLineEndings);
                AssertString(
                    cStr,
                    custom.ToString(SaveOptions.DisableFormatting),
                    options: TextOptions.NormalizeLineEndings);
                AssertString(str1, TestConfigurationSection.Active.String, options: TextOptions.NormalizeLineEndings);
                AssertString(str2, TestConfigurationSection.Active.String2, options: TextOptions.NormalizeLineEndings);
            }
        }