From e0235b1e2102a9bf700c8f40fc01884acec427ef Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Aug 2018 15:20:09 -0700 Subject: [PATCH] Fix aspnet/Home#3379 - add a functional test for Redis storage provider to ensure keys round-trip (#321) --- .vsts-pipelines/builds/ci-internal.yml | 13 ----- .vsts-pipelines/builds/ci-public.yml | 16 ++++++ build/dependencies.props | 1 + .../DataProtectionRedisTests.cs | 51 +++++++++++++++++++ ...spNetCore.DataProtection.Redis.Test.csproj | 8 +++ .../TestRedisServer.cs | 28 ++++++++++ .../TestRedisServerIsAvailableAttribute.cs | 15 ++++++ .../testconfig.json | 10 ++++ 8 files changed, 129 insertions(+), 13 deletions(-) delete mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServer.cs create mode 100644 test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServerIsAvailableAttribute.cs create mode 100644 test/Microsoft.AspNetCore.DataProtection.Redis.Test/testconfig.json diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml deleted file mode 100644 index dc7b8a3cb9..0000000000 --- a/.vsts-pipelines/builds/ci-internal.yml +++ /dev/null @@ -1,13 +0,0 @@ -trigger: -- master -- release/* - -resources: - repositories: - - repository: buildtools - type: git - name: aspnet-BuildTools - ref: refs/heads/release/2.2 - -phases: -- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index f5087d9c30..554cc2be4c 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -13,3 +13,19 @@ resources: phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + phaseName: Linux_RedisTests + queueName: DotNetCore-Docker + agentOs: Linux + demands: + - docker + variables: + Test__Redis__Server: localhost:6379,127.0.0.1:6379 + beforeBuild: + - script: docker run --rm -d --name test-redis-server -p 6379:6379 redis + displayName: Start Redis in Docker + afterBuild: + - script: docker stop test-redis-server + displayName: Stop Redis in Docker + condition: always() diff --git a/build/dependencies.props b/build/dependencies.props index c09050bb04..b2bb6f5bcc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,6 +8,7 @@ 2.2.0-preview1-34896 2.2.0-preview1-34896 2.3.2 + 2.2.0-preview1-34896 2.2.0-preview1-34896 2.2.0-preview1-34896 2.2.0-preview1-34896 diff --git a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/DataProtectionRedisTests.cs b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/DataProtectionRedisTests.cs index 9e010090f8..c6bdad14cb 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/DataProtectionRedisTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/DataProtectionRedisTests.cs @@ -1,17 +1,29 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; +using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; +using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.Testing.xunit; using Moq; using StackExchange.Redis; using Xunit; +using Xunit.Abstractions; namespace Microsoft.AspNetCore.DataProtection { public class DataProtectionRedisTests { + private readonly ITestOutputHelper _output; + + public DataProtectionRedisTests(ITestOutputHelper output) + { + _output = output; + } + [Fact] public void GetAllElements_ReturnsAllXmlValuesForGivenKey() { @@ -55,5 +67,44 @@ namespace Microsoft.AspNetCore.DataProtection database.Verify(); } + + [ConditionalFact] + [TestRedisServerIsAvailable] + public async Task XmlRoundTripsToActualRedisServer() + { + var connStr = TestRedisServer.GetConnectionString(); + + _output.WriteLine("Attempting to connect to " + connStr); + + var guid = Guid.NewGuid().ToString(); + RedisKey key = "Test:DP:Key" + guid; + + try + { + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + var repo = new RedisXmlRepository(() => redis.GetDatabase(), key); + var element = new XElement("HelloRedis", guid); + repo.StoreElement(element, guid); + } + + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + var repo = new RedisXmlRepository(() => redis.GetDatabase(), key); + var elements = repo.GetAllElements(); + + Assert.Contains(elements, e => e.Name == "HelloRedis" && e.Value == guid); + } + } + finally + { + // cleanup + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + await redis.GetDatabase().KeyDeleteAsync(key); + } + } + + } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/Microsoft.AspNetCore.DataProtection.Redis.Test.csproj b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/Microsoft.AspNetCore.DataProtection.Redis.Test.csproj index d359ab936e..5b2296721e 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/Microsoft.AspNetCore.DataProtection.Redis.Test.csproj +++ b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/Microsoft.AspNetCore.DataProtection.Redis.Test.csproj @@ -8,12 +8,20 @@ + + + PreserveNewest + + + + + diff --git a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServer.cs b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServer.cs new file mode 100644 index 0000000000..dfe369625a --- /dev/null +++ b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServer.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Configuration; +using System; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class TestRedisServer + { + public const string ConnectionStringKeyName = "Test:Redis:Server"; + private static readonly IConfigurationRoot _config; + + static TestRedisServer() + { + _config = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) + .AddJsonFile("testconfig.json") + .AddEnvironmentVariables() + .Build(); + } + + internal static string GetConnectionString() + { + return _config[ConnectionStringKeyName]; + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServerIsAvailableAttribute.cs b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServerIsAvailableAttribute.cs new file mode 100644 index 0000000000..04857c494b --- /dev/null +++ b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/TestRedisServerIsAvailableAttribute.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Testing.xunit; +using System; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class TestRedisServerIsAvailableAttribute : Attribute, ITestCondition + { + public bool IsMet => !string.IsNullOrEmpty(TestRedisServer.GetConnectionString()); + + public string SkipReason => $"A test redis server must be configured to run. Set the connection string as an environment variable as {TestRedisServer.ConnectionStringKeyName.Replace(":", "__")} or in testconfig.json"; + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.DataProtection.Redis.Test/testconfig.json b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/testconfig.json new file mode 100644 index 0000000000..2e2f447946 --- /dev/null +++ b/test/Microsoft.AspNetCore.DataProtection.Redis.Test/testconfig.json @@ -0,0 +1,10 @@ +{ + "Test": { + "Redis": { + // You can setup a local Redis server easily with Docker by running + // docker run --rm -it -p 6379:6379 redis + // Then uncomment this config below + // "Server": "localhost:6379,127.0.0.1:6379" + } + } +} \ No newline at end of file