<commit_before>﻿// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.

using Azure.Core;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;

namespace Azure.ApplicationModel.Configuration.Tests
{
    [Category("Live")]
    public class ConfigurationLiveTests
    {
        static readonly ConfigurationSetting s_testSetting = new ConfigurationSetting(
            string.Concat("key-", Guid.NewGuid().ToString("N")),
            "test_value"
        )
        {
            Label = "test_label",
            ContentType = "test_content_type",
            LastModified = new DateTimeOffset(2018, 11, 28, 9, 55, 0, 0, default),
            Locked = false,
            Tags = new Dictionary<string, string>
            {
                { "tag1", "value1" },
                { "tag2", "value2" }
            }
        };

        private static void AssertEqual(ConfigurationSetting expected, ConfigurationSetting actual)
        {
            Assert.AreEqual(expected.Key, actual.Key);
            Assert.AreEqual(expected.Label, actual.Label);
            Assert.AreEqual(expected.ContentType, actual.ContentType);
            Assert.AreEqual(expected.Locked, actual.Locked);
            Assert.IsTrue(TagsEqual(expected.Tags, actual.Tags));
        }

        private static bool TagsEqual(IDictionary<string, string> expected, IDictionary<string, string> actual)
        {
            if (expected == null && actual == null) return true;
            if (expected?.Count != actual?.Count) return false;
            foreach (var pair in expected)
            {
                if (!actual.TryGetValue(pair.Key, out string value)) return false;
                if (!string.Equals(value, pair.Value, StringComparison.Ordinal)) return false;
            }
            return true;
        }

        private async Task<string> SetMultipleKeys(ConfigurationClient service, int expectedEvents)
        {
            string key = string.Concat("key-", Guid.NewGuid().ToString("N")); ;
            
            /*
             * The configuration store contains a KV with the Key
             * that represents {expectedEvents} data points.
             * If not set, create the {expectedEvents} data points and the "BatchKey"
            */
            const string batchKey = "BatchKey";
            
            try
            {
                var responseGet = await service.GetAsync(batchKey);
                key = responseGet.Result.Value;
                responseGet.Dispose();
            }
            catch
            {
                for (int i = 0; i < expectedEvents; i++)
                {
                    await service.AddAsync(new ConfigurationSetting(key, "test_value", $"{i.ToString()}"));
                }

                await service.SetAsync(new ConfigurationSetting(batchKey, key));
            }
            return key;
        }

        [Test]
        public async Task DeleteNotFound()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var response = await service.DeleteAsync(key: s_testSetting.Key, filter: default, CancellationToken.None);

            Assert.AreEqual(204, response.Status);
            response.Dispose();
        }

        [Test]
        public async Task Delete()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                // Prepare environment
                var testSettingDiff = s_testSetting.Clone();
                testSettingDiff.Label = "test_label_diff";
                await service.SetAsync(s_testSetting, CancellationToken.None);
                await service.SetAsync(testSettingDiff, CancellationToken.None);

                // Test
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task DeleteWithLabel()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            // Prepare environment
            await service.SetAsync(s_testSetting, CancellationToken.None);

            // Test
            await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
        }

        [Test]
        public async Task DeleteWithETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            // Prepare environment
            await service.SetAsync(s_testSetting, CancellationToken.None);

            // Test
            ConfigurationSetting settting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);
            SettingFilter filter = new SettingFilter()
            {
                ETag = new ETagFilter() { IfMatch = new ETag(settting.ETag) },
                Label = settting.Label
            };

            await service.DeleteAsync(key: s_testSetting.Key, filter: filter, CancellationToken.None);
        }

        [Test]
        public async Task Set()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                Response<ConfigurationSetting> response = await service.SetAsync(s_testSetting, CancellationToken.None);

                Assert.True(response.TryGetHeader("ETag", out string etagHeader));

                ConfigurationSetting setting = response.Result;
                AssertEqual(s_testSetting, setting);
                response.Dispose();
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task Add()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                Response<ConfigurationSetting> response = await service.AddAsync(s_testSetting, CancellationToken.None);

                Assert.True(response.TryGetHeader("ETag", out string etagHeader));

                ConfigurationSetting setting = response.Result;
                AssertEqual(s_testSetting, setting);
                response.Dispose();
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfAny()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var testSettingDiff = s_testSetting.Clone();
            testSettingDiff.Label = "test_label_diff";

            var testSettingUpdate = s_testSetting.Clone();
            testSettingUpdate.Value = "test_value_update";

            try
            {
                await service.SetAsync(s_testSetting, CancellationToken.None);
                await service.SetAsync(testSettingDiff, CancellationToken.None);

                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag("*") }
                };

                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingUpdate, filter, CancellationToken.None);

                AssertEqual(testSettingUpdate, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: testSettingUpdate.Key, filter: testSettingUpdate.Label, CancellationToken.None);
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting responseGet = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            var testSettingDiff = responseGet.Clone();
            testSettingDiff.Value = "test_value_diff";

            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag(testSettingDiff.ETag) }
                };

                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);

                AssertEqual(testSettingDiff, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfNoMatch()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting setting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfNoneMatch = new ETag(setting.ETag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.UpdateAsync(setting, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(412, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: setting.Key, filter: setting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateWrongETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var testSettingDiff = s_testSetting.Clone();
            testSettingDiff.Value = "test_value_diff";

            try
            {
                await service.SetAsync(s_testSetting, CancellationToken.None);

                var eTag = "ehHuajgQNq5Qg4ruJVB7hlhX8xs";
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag(eTag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(412, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateTags()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting responseGet = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            SettingFilter filter = new SettingFilter()
            {
                ETag = new ETagFilter() { IfMatch = new ETag("*") }
            };
            
            try
            {
                // Different tags
                var testSettingDiff = responseGet.Clone();
                var settingTags = testSettingDiff.Tags;
                if (settingTags.ContainsKey("tag1")) settingTags["tag1"] = "value-updated";
                settingTags.Add("tag3", "test_value3");
                testSettingDiff.Tags = settingTags;
                
                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);
                AssertEqual(testSettingDiff, responseSetting);

                // No tags
                var testSettingNoTags = responseGet.Clone();
                testSettingNoTags.Tags = null;

                responseSetting = await service.UpdateAsync(testSettingNoTags, filter, CancellationToken.None);
                AssertEqual(testSettingNoTags, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task GetIfNoMatch()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting setting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);
            
            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    Label = setting.Label,
                    ETag = new ETagFilter() { IfNoneMatch = new ETag(setting.ETag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.GetAsync(setting.Key, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(304, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: setting.Key, filter: setting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task Revisions()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            //Prepare environment
            ConfigurationSetting setting = s_testSetting;
            setting.Key = string.Concat("key-", Guid.NewGuid().ToString("N"));
            var testSettingUpdate = setting.Clone();
            testSettingUpdate.Label = "test_label_update";
            int expectedEvents = 2;

            try
            {
                await service.SetAsync(setting, CancellationToken.None);
                await service.SetAsync(testSettingUpdate, CancellationToken.None);

                // Test
                var filter = new SettingBatchFilter();
                filter.Key = setting.Key;
                filter.Revision = DateTimeOffset.Now;
                SettingBatch batch = await service.GetRevisionsAsync(filter, CancellationToken.None);

                int resultsReturned = 0;
                for (int i = 0; i < batch.Count; i++)
                {
                    var value = batch[i];
                    if (value.Label.Contains("update"))<commit_msg>Improve reliability of ConfigurationLiveTests.Revisions (#114)<commit_after>﻿// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.

using Azure.Core;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;

namespace Azure.ApplicationModel.Configuration.Tests
{
    [Category("Live")]
    public class ConfigurationLiveTests
    {
        static readonly ConfigurationSetting s_testSetting = new ConfigurationSetting(
            string.Concat("key-", Guid.NewGuid().ToString("N")),
            "test_value"
        )
        {
            Label = "test_label",
            ContentType = "test_content_type",
            LastModified = new DateTimeOffset(2018, 11, 28, 9, 55, 0, 0, default),
            Locked = false,
            Tags = new Dictionary<string, string>
            {
                { "tag1", "value1" },
                { "tag2", "value2" }
            }
        };

        private static void AssertEqual(ConfigurationSetting expected, ConfigurationSetting actual)
        {
            Assert.AreEqual(expected.Key, actual.Key);
            Assert.AreEqual(expected.Label, actual.Label);
            Assert.AreEqual(expected.ContentType, actual.ContentType);
            Assert.AreEqual(expected.Locked, actual.Locked);
            Assert.IsTrue(TagsEqual(expected.Tags, actual.Tags));
        }

        private static bool TagsEqual(IDictionary<string, string> expected, IDictionary<string, string> actual)
        {
            if (expected == null && actual == null) return true;
            if (expected?.Count != actual?.Count) return false;
            foreach (var pair in expected)
            {
                if (!actual.TryGetValue(pair.Key, out string value)) return false;
                if (!string.Equals(value, pair.Value, StringComparison.Ordinal)) return false;
            }
            return true;
        }

        private async Task<string> SetMultipleKeys(ConfigurationClient service, int expectedEvents)
        {
            string key = string.Concat("key-", Guid.NewGuid().ToString("N")); ;
            
            /*
             * The configuration store contains a KV with the Key
             * that represents {expectedEvents} data points.
             * If not set, create the {expectedEvents} data points and the "BatchKey"
            */
            const string batchKey = "BatchKey";
            
            try
            {
                var responseGet = await service.GetAsync(batchKey);
                key = responseGet.Result.Value;
                responseGet.Dispose();
            }
            catch
            {
                for (int i = 0; i < expectedEvents; i++)
                {
                    await service.AddAsync(new ConfigurationSetting(key, "test_value", $"{i.ToString()}"));
                }

                await service.SetAsync(new ConfigurationSetting(batchKey, key));
            }
            return key;
        }

        [Test]
        public async Task DeleteNotFound()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var response = await service.DeleteAsync(key: s_testSetting.Key, filter: default, CancellationToken.None);

            Assert.AreEqual(204, response.Status);
            response.Dispose();
        }

        [Test]
        public async Task Delete()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                // Prepare environment
                var testSettingDiff = s_testSetting.Clone();
                testSettingDiff.Label = "test_label_diff";
                await service.SetAsync(s_testSetting, CancellationToken.None);
                await service.SetAsync(testSettingDiff, CancellationToken.None);

                // Test
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task DeleteWithLabel()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            // Prepare environment
            await service.SetAsync(s_testSetting, CancellationToken.None);

            // Test
            await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
        }

        [Test]
        public async Task DeleteWithETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            // Prepare environment
            await service.SetAsync(s_testSetting, CancellationToken.None);

            // Test
            ConfigurationSetting settting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);
            SettingFilter filter = new SettingFilter()
            {
                ETag = new ETagFilter() { IfMatch = new ETag(settting.ETag) },
                Label = settting.Label
            };

            await service.DeleteAsync(key: s_testSetting.Key, filter: filter, CancellationToken.None);
        }

        [Test]
        public async Task Set()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                Response<ConfigurationSetting> response = await service.SetAsync(s_testSetting, CancellationToken.None);

                Assert.True(response.TryGetHeader("ETag", out string etagHeader));

                ConfigurationSetting setting = response.Result;
                AssertEqual(s_testSetting, setting);
                response.Dispose();
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task Add()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            try
            {
                Response<ConfigurationSetting> response = await service.AddAsync(s_testSetting, CancellationToken.None);

                Assert.True(response.TryGetHeader("ETag", out string etagHeader));

                ConfigurationSetting setting = response.Result;
                AssertEqual(s_testSetting, setting);
                response.Dispose();
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfAny()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var testSettingDiff = s_testSetting.Clone();
            testSettingDiff.Label = "test_label_diff";

            var testSettingUpdate = s_testSetting.Clone();
            testSettingUpdate.Value = "test_value_update";

            try
            {
                await service.SetAsync(s_testSetting, CancellationToken.None);
                await service.SetAsync(testSettingDiff, CancellationToken.None);

                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag("*") }
                };

                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingUpdate, filter, CancellationToken.None);

                AssertEqual(testSettingUpdate, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: testSettingUpdate.Key, filter: testSettingUpdate.Label, CancellationToken.None);
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting responseGet = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            var testSettingDiff = responseGet.Clone();
            testSettingDiff.Value = "test_value_diff";

            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag(testSettingDiff.ETag) }
                };

                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);

                AssertEqual(testSettingDiff, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: testSettingDiff.Key, filter: testSettingDiff.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateIfNoMatch()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting setting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfNoneMatch = new ETag(setting.ETag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.UpdateAsync(setting, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(412, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: setting.Key, filter: setting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateWrongETag()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            var testSettingDiff = s_testSetting.Clone();
            testSettingDiff.Value = "test_value_diff";

            try
            {
                await service.SetAsync(s_testSetting, CancellationToken.None);

                var eTag = "ehHuajgQNq5Qg4ruJVB7hlhX8xs";
                SettingFilter filter = new SettingFilter()
                {
                    ETag = new ETagFilter() { IfMatch = new ETag(eTag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(412, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task UpdateTags()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting responseGet = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);

            SettingFilter filter = new SettingFilter()
            {
                ETag = new ETagFilter() { IfMatch = new ETag("*") }
            };
            
            try
            {
                // Different tags
                var testSettingDiff = responseGet.Clone();
                var settingTags = testSettingDiff.Tags;
                if (settingTags.ContainsKey("tag1")) settingTags["tag1"] = "value-updated";
                settingTags.Add("tag3", "test_value3");
                testSettingDiff.Tags = settingTags;
                
                ConfigurationSetting responseSetting = await service.UpdateAsync(testSettingDiff, filter, CancellationToken.None);
                AssertEqual(testSettingDiff, responseSetting);

                // No tags
                var testSettingNoTags = responseGet.Clone();
                testSettingNoTags.Tags = null;

                responseSetting = await service.UpdateAsync(testSettingNoTags, filter, CancellationToken.None);
                AssertEqual(testSettingNoTags, responseSetting);
            }
            finally
            {
                await service.DeleteAsync(key: s_testSetting.Key, filter: s_testSetting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task GetIfNoMatch()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            await service.SetAsync(s_testSetting, CancellationToken.None);
            ConfigurationSetting setting = await service.GetAsync(s_testSetting.Key, s_testSetting.Label, CancellationToken.None);
            
            try
            {
                SettingFilter filter = new SettingFilter()
                {
                    Label = setting.Label,
                    ETag = new ETagFilter() { IfNoneMatch = new ETag(setting.ETag) }
                };

                var exception = Assert.ThrowsAsync<ResponseFailedException>(async () =>
                {
                    await service.GetAsync(setting.Key, filter, CancellationToken.None);
                });

                var response = exception.Response;
                Assert.AreEqual(304, response.Status);
            }
            finally
            {
                await service.DeleteAsync(key: setting.Key, filter: setting.Label, CancellationToken.None);
            }
        }

        [Test]
        public async Task Revisions()
        {
            var connectionString = Environment.GetEnvironmentVariable("AZ_CONFIG_CONNECTION");
            Assert.NotNull(connectionString, "Set AZ_CONFIG_CONNECTION environment variable to the connection string");
            var service = new ConfigurationClient(connectionString);

            //Prepare environment
            ConfigurationSetting setting = s_testSetting;
            setting.Key = string.Concat("key-", Guid.NewGuid().ToString("N"));
            var testSettingUpdate = setting.Clone();
            testSettingUpdate.Label = "test_label_update";
            int expectedEvents = 2;

            try
            {
                await service.SetAsync(setting, CancellationToken.None);
                await service.SetAsync(testSettingUpdate, CancellationToken.None);

                // Test
                var filter = new SettingBatchFilter();
                filter.Key = setting.Key;
                filter.Revision = DateTimeOffset.MaxValue;
                SettingBatch batch = await service.GetRevisionsAsync(filter, CancellationToken.None);

                int resultsReturned = 0;
                for (int i = 0; i < batch.Count; i++)
                {
                    var value = batch[i];
                    if (value.Label.Contains("update"))
{'fraction_non_alphanumeric': 0.08061196105702365, 'fraction_numerical': 0.002364394993045897, 'mean_word_length': 1.9745987092503723, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6453', 'n_tokens_mistral': 8427, 'n_tokens_neox': 8226, 'n_words': 1859}