| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- // 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.Collections.Generic;
- using System.Security.Cryptography;
- using System.Text;
- using Microsoft.AspNetCore.DataProtection.Infrastructure;
- using Microsoft.AspNetCore.DataProtection.Abstractions;
- using Microsoft.AspNetCore.Testing;
- using Microsoft.Extensions.PlatformAbstractions;
- using Moq;
- using Xunit;
- namespace Microsoft.AspNetCore.DataProtection
- {
- public class DataProtectionExtensionsTests
- {
- [Theory]
- [InlineData(new object[] { new string[0] })]
- [InlineData(new object[] { new string[] { null } })]
- [InlineData(new object[] { new string[] { "the next value is bad", null } })]
- public void CreateProtector_ChainedAsIEnumerable_FailureCases(string[] purposes)
- {
- // Arrange
- var mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(o => o.CreateProtector(It.IsAny<string>())).Returns(mockProtector.Object);
- var provider = mockProtector.Object;
- // Act & assert
- ExceptionAssert.ThrowsArgument(
- testCode: () => provider.CreateProtector((IEnumerable<string>)purposes),
- paramName: "purposes",
- exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection);
- }
- [Theory]
- [InlineData(new object[] { new string[] { null } })]
- [InlineData(new object[] { new string[] { "the next value is bad", null } })]
- public void CreateProtector_ChainedAsParams_FailureCases(string[] subPurposes)
- {
- // Arrange
- var mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(o => o.CreateProtector(It.IsAny<string>())).Returns(mockProtector.Object);
- var provider = mockProtector.Object;
- // Act & assert
- ExceptionAssert.ThrowsArgument(
- testCode: () => provider.CreateProtector("primary-purpose", subPurposes),
- paramName: "purposes",
- exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection);
- }
- [Fact]
- public void CreateProtector_ChainedAsIEnumerable_SuccessCase()
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var thirdMock = new Mock<IDataProtector>();
- thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector);
- var secondMock = new Mock<IDataProtector>();
- secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object);
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object);
- // Act
- var retVal = firstMock.Object.CreateProtector((IEnumerable<string>)new string[] { "first", "second", "third" });
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Fact]
- public void CreateProtector_ChainedAsParams_NonEmptyParams_SuccessCase()
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var thirdMock = new Mock<IDataProtector>();
- thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector);
- var secondMock = new Mock<IDataProtector>();
- secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object);
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object);
- // Act
- var retVal = firstMock.Object.CreateProtector("first", "second", "third");
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Theory]
- [InlineData(new object[] { null })]
- [InlineData(new object[] { new string[0] })]
- public void CreateProtector_ChainedAsParams_EmptyParams_SuccessCases(string[] subPurposes)
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(finalExpectedProtector);
- // Act
- var retVal = firstMock.Object.CreateProtector("first", subPurposes);
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Theory]
- [InlineData(" discriminator", "app-path ", "discriminator")] // normalized trim
- [InlineData("", "app-path", null)] // app discriminator not null -> overrides app base path
- [InlineData(null, "app-path ", "app-path")] // normalized trim
- [InlineData(null, " ", null)] // normalized whitespace -> null
- [InlineData(null, null, null)] // nothing provided at all
- public void GetApplicationUniqueIdentifier(string appDiscriminator, string appBasePath, string expected)
- {
- // Arrange
- var mockAppDiscriminator = new Mock<IApplicationDiscriminator>();
- mockAppDiscriminator.Setup(o => o.Discriminator).Returns(appDiscriminator);
- var mockAppEnvironment = new Mock<IApplicationEnvironment>();
- mockAppEnvironment.Setup(o => o.ApplicationBasePath).Returns(appBasePath);
- var mockServiceProvider = new Mock<IServiceProvider>();
- mockServiceProvider.Setup(o => o.GetService(typeof(IApplicationDiscriminator))).Returns(mockAppDiscriminator.Object);
- mockServiceProvider.Setup(o => o.GetService(typeof(IApplicationEnvironment))).Returns(mockAppEnvironment.Object);
- // Act
- string actual = mockServiceProvider.Object.GetApplicationUniqueIdentifier();
- // Assert
- Assert.Equal(expected, actual);
- }
- [Fact]
- public void GetApplicationUniqueIdentifier_NoServiceProvider_ReturnsNull()
- {
- Assert.Null(((IServiceProvider)null).GetApplicationUniqueIdentifier());
- }
- [Fact]
- public void GetDataProtectionProvider_NoServiceFound_Throws()
- {
- // Arrange
- var services = new Mock<IServiceProvider>().Object;
- // Act & assert
- var ex = Assert.Throws<InvalidOperationException>(() => services.GetDataProtectionProvider());
- Assert.Equal(Resources.FormatDataProtectionExtensions_NoService(typeof(IDataProtectionProvider).FullName), ex.Message);
- }
- [Fact]
- public void GetDataProtectionProvider_ServiceFound_ReturnsService()
- {
- // Arrange
- var expected = new Mock<IDataProtectionProvider>().Object;
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(expected);
- var services = mockServices.Object;
- // Act
- var actual = services.GetDataProtectionProvider();
- // Assert
- Assert.Same(expected, actual);
- }
- [Theory]
- [InlineData(new object[] { new string[0] })]
- [InlineData(new object[] { new string[] { null } })]
- [InlineData(new object[] { new string[] { "the next value is bad", null } })]
- public void GetDataProtector_ChainedAsIEnumerable_FailureCases(string[] purposes)
- {
- // Arrange
- var mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(o => o.CreateProtector(It.IsAny<string>())).Returns(mockProtector.Object);
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(mockProtector.Object);
- var services = mockServices.Object;
- // Act & assert
- ExceptionAssert.ThrowsArgument(
- testCode: () => services.GetDataProtector((IEnumerable<string>)purposes),
- paramName: "purposes",
- exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection);
- }
- [Theory]
- [InlineData(new object[] { new string[] { null } })]
- [InlineData(new object[] { new string[] { "the next value is bad", null } })]
- public void GetDataProtector_ChainedAsParams_FailureCases(string[] subPurposes)
- {
- // Arrange
- var mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(o => o.CreateProtector(It.IsAny<string>())).Returns(mockProtector.Object);
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(mockProtector.Object);
- var services = mockServices.Object;
- // Act & assert
- ExceptionAssert.ThrowsArgument(
- testCode: () => services.GetDataProtector("primary-purpose", subPurposes),
- paramName: "purposes",
- exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection);
- }
- [Fact]
- public void GetDataProtector_ChainedAsIEnumerable_SuccessCase()
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var thirdMock = new Mock<IDataProtector>();
- thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector);
- var secondMock = new Mock<IDataProtector>();
- secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object);
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object);
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object);
- var services = mockServices.Object;
- // Act
- var retVal = services.GetDataProtector((IEnumerable<string>)new string[] { "first", "second", "third" });
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Fact]
- public void GetDataProtector_ChainedAsParams_NonEmptyParams_SuccessCase()
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var thirdMock = new Mock<IDataProtector>();
- thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector);
- var secondMock = new Mock<IDataProtector>();
- secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object);
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object);
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object);
- var services = mockServices.Object;
- // Act
- var retVal = services.GetDataProtector("first", "second", "third");
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Theory]
- [InlineData(new object[] { null })]
- [InlineData(new object[] { new string[0] })]
- public void GetDataProtector_ChainedAsParams_EmptyParams_SuccessCases(string[] subPurposes)
- {
- // Arrange
- var finalExpectedProtector = new Mock<IDataProtector>().Object;
- var firstMock = new Mock<IDataProtector>();
- firstMock.Setup(o => o.CreateProtector("first")).Returns(finalExpectedProtector);
- var mockServices = new Mock<IServiceProvider>();
- mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object);
- var services = mockServices.Object;
- // Act
- var retVal = services.GetDataProtector("first", subPurposes);
- // Assert
- Assert.Same(finalExpectedProtector, retVal);
- }
- [Fact]
- public void Protect_InvalidUtf8_Failure()
- {
- // Arrange
- Mock<IDataProtector> mockProtector = new Mock<IDataProtector>();
- // Act & assert
- var ex = Assert.Throws<CryptographicException>(() =>
- {
- mockProtector.Object.Protect("Hello\ud800");
- });
- Assert.IsAssignableFrom(typeof(EncoderFallbackException), ex.InnerException);
- }
- [Fact]
- public void Protect_Success()
- {
- // Arrange
- Mock<IDataProtector> mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(p => p.Protect(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f })).Returns(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 });
- // Act
- string retVal = mockProtector.Object.Protect("Hello");
- // Assert
- Assert.Equal("AQIDBAU", retVal);
- }
- [Fact]
- public void Unprotect_InvalidBase64BeforeDecryption_Failure()
- {
- // Arrange
- Mock<IDataProtector> mockProtector = new Mock<IDataProtector>();
- // Act & assert
- var ex = Assert.Throws<CryptographicException>(() =>
- {
- mockProtector.Object.Unprotect("A");
- });
- }
- [Fact]
- public void Unprotect_InvalidUtf8AfterDecryption_Failure()
- {
- // Arrange
- Mock<IDataProtector> mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(p => p.Unprotect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 })).Returns(new byte[] { 0xff });
- // Act & assert
- var ex = Assert.Throws<CryptographicException>(() =>
- {
- mockProtector.Object.Unprotect("AQIDBAU");
- });
- Assert.IsAssignableFrom(typeof(DecoderFallbackException), ex.InnerException);
- }
- [Fact]
- public void Unprotect_Success()
- {
- // Arrange
- Mock<IDataProtector> mockProtector = new Mock<IDataProtector>();
- mockProtector.Setup(p => p.Unprotect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 })).Returns(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f });
- // Act
- string retVal = DataProtectionExtensions.Unprotect(mockProtector.Object, "AQIDBAU");
- // Assert
- Assert.Equal("Hello", retVal);
- }
- }
- }
|