namespace Ocelot.UnitTests.Consul { using global::Consul; using Microsoft.Extensions.Options; using Moq; using Newtonsoft.Json; using Ocelot.Cache; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.Configuration.File; using Ocelot.Configuration.Repository; using Ocelot.Logging; using Provider.Consul; using Responses; using Shouldly; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using TestStack.BDDfy; using Xunit; public class ConsulFileConfigurationRepositoryTests { private ConsulFileConfigurationRepository _repo; private Mock> _options; private Mock> _cache; private Mock _factory; private Mock _loggerFactory; private Mock _client; private Mock _kvEndpoint; private FileConfiguration _fileConfiguration; private Response _setResult; private Response _getResult; public ConsulFileConfigurationRepositoryTests() { _cache = new Mock>(); _loggerFactory = new Mock(); _options = new Mock>(); _factory = new Mock(); _client = new Mock(); _kvEndpoint = new Mock(); _client .Setup(x => x.KV) .Returns(_kvEndpoint.Object); _factory .Setup(x => x.Get(It.IsAny())) .Returns(_client.Object); _options .SetupGet(x => x.Value) .Returns(() => _fileConfiguration); } [Fact] public void should_set_config() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .And(_ => GivenWritingToConsulSucceeds()) .When(_ => WhenISetTheConfiguration()) .Then(_ => ThenTheConfigurationIsStoredAs(config)) .BDDfy(); } [Fact] public void should_get_config() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .And(_ => GivenFetchFromConsulSucceeds()) .When(_ => WhenIGetTheConfiguration()) .Then(_ => ThenTheConfigurationIs(config)) .BDDfy(); } [Fact] public void should_get_null_config() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .Given(_ => GivenFetchFromConsulReturnsNull()) .When(_ => WhenIGetTheConfiguration()) .Then(_ => ThenTheConfigurationIsNull()) .BDDfy(); } [Fact] public void should_get_config_from_cache() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .And(_ => GivenFetchFromCacheSucceeds()) .When(_ => WhenIGetTheConfiguration()) .Then(_ => ThenTheConfigurationIs(config)) .BDDfy(); } [Fact] public void should_set_config_key() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .And(_ => GivenTheConfigKeyComesFromFileConfig("Tom")) .And(_ => GivenFetchFromConsulSucceeds()) .When(_ => WhenIGetTheConfiguration()) .And(_ => ThenTheConfigKeyIs("Tom")) .BDDfy(); } [Fact] public void should_set_default_config_key() { var config = FakeFileConfiguration(); this.Given(_ => GivenIHaveAConfiguration(config)) .And(_ => GivenFetchFromConsulSucceeds()) .When(_ => WhenIGetTheConfiguration()) .And(_ => ThenTheConfigKeyIs("InternalConfiguration")) .BDDfy(); } private void ThenTheConfigKeyIs(string expected) { _kvEndpoint .Verify(x => x.Get(expected, It.IsAny()), Times.Once); } private void GivenTheConfigKeyComesFromFileConfig(string key) { _fileConfiguration.GlobalConfiguration.ServiceDiscoveryProvider.ConfigurationKey = key; _repo = new ConsulFileConfigurationRepository(_options.Object, _cache.Object, _factory.Object, _loggerFactory.Object); } private void ThenTheConfigurationIsNull() { _getResult.Data.ShouldBeNull(); } private void ThenTheConfigurationIs(FileConfiguration config) { var expected = JsonConvert.SerializeObject(config, Formatting.Indented); var result = JsonConvert.SerializeObject(_getResult.Data, Formatting.Indented); result.ShouldBe(expected); } private async Task WhenIGetTheConfiguration() { _getResult = await _repo.Get(); } private void GivenWritingToConsulSucceeds() { var response = new WriteResult(); response.Response = true; _kvEndpoint .Setup(x => x.Put(It.IsAny(), It.IsAny())).ReturnsAsync(response); } private void GivenFetchFromCacheSucceeds() { _cache.Setup(x => x.Get(It.IsAny(), It.IsAny())).Returns(_fileConfiguration); } private void GivenFetchFromConsulReturnsNull() { QueryResult result = new QueryResult(); _kvEndpoint .Setup(x => x.Get(It.IsAny(), It.IsAny())) .ReturnsAsync(result); } private void GivenFetchFromConsulSucceeds() { var json = JsonConvert.SerializeObject(_fileConfiguration, Formatting.Indented); var bytes = Encoding.UTF8.GetBytes(json); var kvp = new KVPair("OcelotConfiguration"); kvp.Value = bytes; var query = new QueryResult(); query.Response = kvp; _kvEndpoint .Setup(x => x.Get(It.IsAny(), It.IsAny())) .ReturnsAsync(query); } private void ThenTheConfigurationIsStoredAs(FileConfiguration config) { var json = JsonConvert.SerializeObject(config, Formatting.Indented); var bytes = Encoding.UTF8.GetBytes(json); _kvEndpoint .Verify(x => x.Put(It.Is(k => k.Value.SequenceEqual(bytes)), It.IsAny()), Times.Once); } private async Task WhenISetTheConfiguration() { _setResult = await _repo.Set(_fileConfiguration); } private void GivenIHaveAConfiguration(FileConfiguration config) { _fileConfiguration = config; _repo = new ConsulFileConfigurationRepository(_options.Object, _cache.Object, _factory.Object, _loggerFactory.Object); } private FileConfiguration FakeFileConfiguration() { var reRoutes = new List { new FileReRoute { DownstreamHostAndPorts = new List { new FileHostAndPort { Host = "123.12.12.12", Port = 80, } }, DownstreamScheme = "https", DownstreamPathTemplate = "/asdfs/test/{test}" } }; var globalConfiguration = new FileGlobalConfiguration { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { Port = 198, Host = "blah" } }; return new FileConfiguration { GlobalConfiguration = globalConfiguration, ReRoutes = reRoutes }; } } }