예제 #1
0
        public async Task RetrieverReturnsNullManagerReturnsNullWithoutCallingResizingStrategy()
        {
            var imageRetrieverMock = new Mock <IMapImageRetriever>();
            var imageResizerMock   = new Mock <IImageResizingStrategy>();
            var optionsMock        = OptionsTestHelper.CreateBackendOptionsMock();
            var logger             = LoggingTestHelper.CreateLogger <GeoManager>(this.outputHelper);

            var manager = new GeoManager(imageRetrieverMock.Object, imageResizerMock.Object, optionsMock.Object, logger);

            var zipCode     = "1234AB";
            var houseNumber = 1;
            var zoomLevel   = ZoomLevel.CITY;

            imageRetrieverMock.Setup(x => x.GetMapImageAsync(
                                         zipCode,
                                         houseNumber,
                                         zoomLevel,
                                         It.IsAny <CancellationToken>()))
            .ReturnsAsync(null as Stream)
            .Verifiable();

            var imageStream = await manager.GetMapImageAsync(
                zipCode,
                houseNumber,
                zoomLevel,
        /// <summary>
        /// Initializes a new instance of the <see cref="AuthenticationFlowTest"/> class.
        /// </summary>
        /// <param name="outputHelper">The test output helper.</param>
        public AuthenticationFlowTest(ITestOutputHelper outputHelper)
        {
            this.outputHelper             = outputHelper;
            this.testDatabase             = new TestDatabase(outputHelper);
            this.dbContext                = this.testDatabase.CreateContext();
            this.identityInstance         = IdentityTestHelper.CreateInstance(this.testDatabase, this.outputHelper);
            this.usedHttpContext          = new DefaultHttpContext();
            this.httpConctextAccessorMock = new Mock <IHttpContextAccessor>();
            this.jwtCrypoMock             = new Mock <IJwtCryptoProvider>();
            this.momentMock               = MomentTestHelper.CreateMomentMock();
            this.optionsMonitorMock       = OptionsTestHelper.CreateBackendOptionsMock();
            this.randomGenerator          = new SecureRandomGenerator();
            this.loggerFactory            = LoggingTestHelper.CreateLoggerFactory(this.outputHelper);

            this.httpConctextAccessorMock.SetupGet(m => m.HttpContext).Returns(this.usedHttpContext);

            this.jwtCrypoMock.SetupGet(c => c.Algorithm).Returns(SigningAlgorithm);
            this.jwtCrypoMock.SetupGet(c => c.SecurityKey).Returns(SigningKey);

            this.authenticationFlow = new AuthenticationFlow(
                this.httpConctextAccessorMock.Object,
                this.jwtCrypoMock.Object,
                this.identityInstance.UserManager,
                this.dbContext,
                this.randomGenerator,
                this.momentMock.Object,
                this.optionsMonitorMock.Object,
                this.loggerFactory.CreateLogger <AuthenticationFlow>());
        }
        public async Task DoesNotEvictWithinCachePeriod()
        {
            var evictionPeriod  = TimeSpan.FromDays(14);
            var imageAccessTime = DateTimeOffset.UtcNow - (evictionPeriod - TimeSpan.FromDays(2));
            var postalCode      = "1234";
            var zoomLevel       = ZoomLevel.CITY;

            var optionsMock = OptionsTestHelper.CreateBackendOptionsMock(
                x => x.Geo.CacheTimesPerZoomLevel = ImmutableDictionary <ZoomLevel, TimeSpan> .Empty
                                                    .Add(zoomLevel, evictionPeriod));

            using var testDb = new TestDatabase(this.outputHelper);

            using (var ctx = await testDb.CreateContextAsync().ConfigureAwait(true))
            {
                ctx.MapImages.Add(
                    new MapImage
                {
                    ImageData        = new byte[] { 0x01 },
                    LastTimeAccessed = imageAccessTime,
                    PostalCode       = postalCode,
                    ZoomLevel        = zoomLevel,
                });
                await ctx.SaveChangesAsync().ConfigureAwait(true);
            }

            using (var ctx = await testDb.CreateContextAsync().ConfigureAwait(true))
            {
                var task = new GeoMapImageCacheCleaningTask(
                    ctx,
                    optionsMock.Object,
                    LoggingTestHelper.CreateLogger <GeoMapImageCacheCleaningTask>(this.outputHelper));

                await task.RunAsync(default).ConfigureAwait(true);
예제 #4
0
        public void DoesNotProduceFaultsForValidOptions()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();
            var result    = validator.Validate(string.Empty, options);

            result.Failed.Should().BeFalse("because the provided options are valid");
        }
예제 #5
0
        public Task MapRetrievalTestDefaultSizeValuesReturnsDefaultSizeFromOptions()
        {
            var opt = OptionsTestHelper.CreateValidOptions();

            return(this.DoHappyFlowTest(
                       opt.Geo.DefaultResponseHeightForMapImage,
                       opt.Geo.DefaultResponseWidthForMapImage,
                       null,
                       null));
        }
예제 #6
0
        public void DoesProduceFaultForEmptyHereMapsApiKey()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();

            options.Geo.HereMapsAPIKey = string.Empty;

            var result = validator.Validate(string.Empty, options);

            result.Failed.Should().BeTrue("because the provided options are not valid.");
        }
예제 #7
0
        public void DoesProduceFaultForEmptySqlServerConnectionString()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();

            options.Database.SQLServerConnectionString = string.Empty;

            var result = validator.Validate(string.Empty, options);

            result.Failed.Should().BeTrue("because the provided options are not valid");
        }
예제 #8
0
        public void AlgorithmEqualsHmacSha512Signature()
        {
            var options = OptionsTestHelper.CreateBackendOptionsMock();

            var provider = new JwtCryptoProvider(options.Object);

            provider.Algorithm
            .Should()
            .Be(
                SecurityAlgorithms.HmacSha512Signature,
                because: "this is the chosen security algorithm");
        }
예제 #9
0
        private static (MapImageClient client, Mock <HttpMessageHandler> httpMock) CreateClientAndHandlerMock(
            Action <Mock <HttpMessageHandler> >?mockSetup = null)
        {
            var(httpMock, httpClient) = HttpTestHelper.CreateMockWithClient(mockSetup);
            var optionsMock = OptionsTestHelper.CreateBackendOptionsMock(
                x =>
            {
                x.Geo.HEREMapImageServiceBaseUri = BaseUri;
                x.Geo.HereMapsAPIKey             = ApiKey;
            });

            return(new MapImageClient(httpClient, optionsMock.Object), httpMock);
        }
예제 #10
0
        public void DoesProduceFaultForHEREMapImageServiceEndpointNull()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();

            options.Geo.HEREMapImageServiceBaseUri = null !;

            var result = validator.Validate(string.Empty, options);

            result.Failed.Should()
            .BeTrue(
                because: "the HERE Map Image service endpoint Uri is null.");
        }
예제 #11
0
        public void DoesProduceFaultForTooShortJwtSecret()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();

            options.AuthNR.JWTSigningKey = string.Concat(
                Enumerable.Range(0, 15).Select(n => "c"));

            var result = validator.Validate(string.Empty, options);

            result.Failed.Should()
            .BeTrue(
                because: "the JWT signing key was not at least 16 characters long.");
        }
예제 #12
0
        public void SecurityKeyIsSymmetricKeyProvidedInOptions()
        {
            var options = OptionsTestHelper.CreateBackendOptionsMock();

            var provider = new JwtCryptoProvider(options.Object);

            provider.SecurityKey
            .Should()
            .BeOfType <SymmetricSecurityKey>(because: "we use a symettric security key");

            var symmetricalKey = (SymmetricSecurityKey)provider.SecurityKey;

            symmetricalKey.Key.Should()
            .BeEquivalentTo(
                Encoding.UTF8.GetBytes(options.Object.CurrentValue.AuthNR.JWTSigningKey),
                because: "this is the key configured in the options");
        }
예제 #13
0
        public void DoesProduceFaultForHEREGeocodeServiceEndpointWithInvalidScheme()
        {
            var validator = new BackendOptionsValidator();
            var options   = OptionsTestHelper.CreateValidOptions();

            var uriBuilder = new UriBuilder("https://google.com/")
            {
                Scheme = Uri.UriSchemeFtp,
            };

            options.Geo.HEREGeocodeServiceBaseUri = uriBuilder.Uri;

            var result = validator.Validate(string.Empty, options);

            result.Failed.Should()
            .BeTrue(
                because: "the HERE Geocode Service Endpoint has an invalid URI.");
        }
        public async Task CachableImageWithinCacheRetrievesFromCache()
        {
            using var db = new TestDatabase(this.outputHelper);

            var zipCode           = "1234 AB";
            var zipCodeNormalized = "1234";
            var houseNumber       = 1;
            var zoomLevel         = ZoomLevel.CITY;
            var imageData         = new byte[] { 0, 1, 2, 3, };

            var optionsMock = OptionsTestHelper.CreateBackendOptionsMock(
                x => x.Geo.CacheTimesPerZoomLevel = ImmutableDictionary <ZoomLevel, TimeSpan> .Empty.Add(
                    zoomLevel,
                    TimeSpan.MaxValue));

            var innerMock = new Mock <IMapImageRetriever>();

            var logger = LoggingTestHelper.CreateLogger <CachedMapImageRetriever>(this.outputHelper);

            var imageInCache = new MapImage
            {
                PostalCode       = zipCodeNormalized,
                ImageData        = imageData,
                ZoomLevel        = zoomLevel,
                LastTimeAccessed = DateTimeOffset.UtcNow,
            };

            using (var ctx = await db.CreateContextAsync().ConfigureAwait(true))
            {
                ctx.MapImages.Add(imageInCache);
                await ctx.SaveChangesAsync().ConfigureAwait(true);
            }

            Stream?imageStream = default;

            using (var ctx = await db.CreateContextAsync().ConfigureAwait(true))
            {
                var retriever = new CachedMapImageRetriever(
                    ctx,
                    innerMock.Object,
                    optionsMock.Object,
                    logger);

                imageStream = await retriever.GetMapImageAsync(
                    zipCode,
                    houseNumber,
                    zoomLevel,
                    default)
                              .ConfigureAwait(true);
            }

            imageStream
            .Should()
            .NotBeNull(
                because: "the value should have been retrieved from the cache");

            using var ms           = new MemoryStream();
            imageStream !.Position = 0;
            await imageStream.CopyToAsync(ms).ConfigureAwait(true);

            ms.ToArray()
            .Should()
            .BeEquivalentTo(
                imageData,
                because: "the retrieved value should be equal to the data intially stored in the cache");

            innerMock.VerifyNoOtherCalls();
        }