Exemplo n.º 1
0
        public async Task QueryPublishedFundingDelegatesToQueryBuilderAndExecutesCosmosDbQueryItCreates()
        {
            IEnumerable <string> fundingStreamIds = EnumerableFor(NewRandomString(), NewRandomString());
            IEnumerable <string> fundingPeriodIds = EnumerableFor(NewRandomString(), NewRandomString(), NewRandomString());
            IEnumerable <string> groupingReasons  = EnumerableFor(NewRandomString());
            IEnumerable <string> variationReasons = EnumerableFor(NewRandomString());
            int top     = NewRandomNumber();
            int pageRef = NewRandomNumber();


            IEnumerable <PublishedFundingIndex> expectedResults = new PublishedFundingIndex[0];
            CosmosDbQuery query = new CosmosDbQuery();

            GivenTheCosmosDbQuery(fundingStreamIds,
                                  fundingPeriodIds,
                                  groupingReasons,
                                  variationReasons,
                                  top,
                                  pageRef,
                                  query);
            AndTheDynamicResultsForTheQuery(query, expectedResults);

            IEnumerable <PublishedFundingIndex> actualResults = await _repository.QueryPublishedFunding(fundingStreamIds,
                                                                                                        fundingPeriodIds,
                                                                                                        groupingReasons,
                                                                                                        variationReasons,
                                                                                                        top,
                                                                                                        pageRef,
                                                                                                        0);

            actualResults
            .Should()
            .BeEquivalentTo(expectedResults);
        }
Exemplo n.º 2
0
 private async Task CachePublishedFundingDocument(PublishedFundingIndex publishedFundingIndex, SemaphoreSlim cacheThrottle)
 {
     try
     {
         await _retrievalService.GetFundingFeedDocument(publishedFundingIndex.DocumentPath, true);
     }
     finally
     {
         cacheThrottle.Release();
     }
 }
        public async Task GetFundingByFundingResultId_GivenResultFound_ReturnsContentResult()
        {
            //Arrange
            string resultId        = "12345";
            string documentPath    = "Round the ragged rocks the ragged rascal ran";
            string fundingDocument = "Now is the time for all good men to come to the aid of the party.";

            PublishedFundingIndex publishedFundingIndex = CreatePublishedFundingResult();

            publishedFundingIndex.DocumentPath = documentPath;

            ISearchRepository <PublishedFundingIndex> searchRepository = CreateSearchRepository();

            searchRepository
            .SearchById(Arg.Is(resultId))
            .Returns(publishedFundingIndex);

            IPublishedFundingRetrievalService publishedFundingRetrievalService = Substitute.For <IPublishedFundingRetrievalService>();

            publishedFundingRetrievalService
            .GetFundingFeedDocument(documentPath)
            .Returns(fundingDocument);

            FundingFeedItemByIdService service = CreateService(searchRepository: searchRepository,
                                                               publishedFundingRetrievalService: publishedFundingRetrievalService);

            //Act
            IActionResult result = await service.GetFundingByFundingResultId(resultId);

            //Assert
            result
            .Should().BeOfType <ContentResult>()
            .Which
            .StatusCode
            .Should().Be((int)HttpStatusCode.OK);

            await searchRepository
            .Received(1)
            .SearchById(resultId);

            await publishedFundingRetrievalService
            .Received(1)
            .GetFundingFeedDocument(documentPath);

            ContentResult contentResult = result as ContentResult;

            contentResult.Content
            .Should().Be(fundingDocument);
            contentResult.ContentType
            .Should().Be("application/json");
        }
        private void AddAtomEntry(HttpRequest request,
                                  string fundingTrimmedRequestPath,
                                  PublishedFundingIndex feedIndex,
                                  ConcurrentDictionary <string, object> feedContentResults,
                                  AtomFeed <AtomEntry> atomFeed)
        {
            string link = $"{request.Scheme}://{request.Host.Value}{fundingTrimmedRequestPath}/byId/{feedIndex.Id}";

            feedContentResults.TryGetValue(feedIndex.Id, out object contentsObject);

            atomFeed.AtomEntry.Add(new AtomEntry
            {
                Id        = link,
                Title     = feedIndex.Id,
                Summary   = feedIndex.Id,
                Published = feedIndex.StatusChangedDate,
                Updated   = feedIndex.StatusChangedDate.Value,
                Version   = feedIndex.Version,
                Link      = new CalculateFunding.Models.External.AtomItems.AtomLink(link, "Funding"),
                Content   = contentsObject,
            });
        }
        public async Task <IActionResult> GetFundingByFundingResultId(string id)
        {
            Guard.IsNullOrWhiteSpace(id, nameof(id));

            PublishedFundingIndex fundingIndexedDocument = await _fundingSearchRepositoryPolicy.ExecuteAsync(() => _fundingSearchRepository.SearchById(id));

            if (fundingIndexedDocument == null)
            {
                return(new NotFoundResult());
            }

            string fundingDocument = await _publishedFundingRetrievalService.GetFundingFeedDocument(fundingIndexedDocument.DocumentPath);

            if (string.IsNullOrWhiteSpace(fundingDocument))
            {
                _logger.Error("Failed to find blob with id {id} and document path: {documentPath}", id, fundingIndexedDocument.DocumentPath);
                return(new NotFoundResult());
            }

            return(new ContentResult()
            {
                Content = fundingDocument, ContentType = "application/json", StatusCode = (int)HttpStatusCode.OK
            });
        }
        public async Task GetFundingByFundingResultId_GivenEmptyResultFound_ReturnsNotFoundResult(string document)
        {
            //Arrange
            string resultId     = "12345";
            string documentPath = "Round the ragged rocks the ragged rascal ran";

            PublishedFundingIndex publishedFundingIndex = CreatePublishedFundingResult();

            publishedFundingIndex.DocumentPath = documentPath;

            ISearchRepository <PublishedFundingIndex> searchRepository = CreateSearchRepository();

            searchRepository
            .SearchById(Arg.Is(resultId))
            .Returns(publishedFundingIndex);

            IPublishedFundingRetrievalService publishedFundingRetrievalService = Substitute.For <IPublishedFundingRetrievalService>();

            publishedFundingRetrievalService
            .GetFundingFeedDocument(documentPath)
            .Returns(document);

            FundingFeedItemByIdService service = CreateService(searchRepository: searchRepository,
                                                               publishedFundingRetrievalService: publishedFundingRetrievalService);

            //Act
            IActionResult result = await service.GetFundingByFundingResultId(resultId);

            //Assert
            result
            .Should().BeOfType <NotFoundResult>();

            await searchRepository
            .Received(1)
            .SearchById(resultId);
        }
        public async Task GetNotifications_GivenAQueryStringForWhichThereAreResults_ReturnsAtomFeedWithCorrectLinks()
        {
            //Arrange
            string fundingFeedDocument = JsonConvert.SerializeObject(new
            {
                FundingStreamId = "PES"
            });

            int pageRef  = 2;
            int pageSize = 3;

            List <PublishedFundingIndex>         searchFeedEntries = CreateFeedIndexes().ToList();
            SearchFeedV3 <PublishedFundingIndex> feeds             = new SearchFeedV3 <PublishedFundingIndex>
            {
                PageRef    = pageRef,
                Top        = 2,
                TotalCount = 8,
                Entries    = searchFeedEntries
            };
            PublishedFundingIndex firstFeedItem = feeds.Entries.ElementAt(0);

            IFundingFeedSearchService feedsSearchService = CreateSearchService();

            feedsSearchService
            .GetFeedsV3(Arg.Is(pageRef), Arg.Is(pageSize))
            .ReturnsForAnyArgs(feeds);

            IPublishedFundingRetrievalService publishedFundingRetrievalService = Substitute.For <IPublishedFundingRetrievalService>();

            publishedFundingRetrievalService
            .GetFundingFeedDocument(Arg.Any <string>())
            .Returns(fundingFeedDocument);

            Mock <IExternalEngineOptions> externalEngineOptions = new Mock <IExternalEngineOptions>();

            externalEngineOptions
            .Setup(_ => _.BlobLookupConcurrencyCount)
            .Returns(10);

            FundingFeedService service = CreateService(
                searchService: feedsSearchService,
                publishedFundingRetrievalService: publishedFundingRetrievalService,
                externalEngineOptions.Object);

            IHeaderDictionary headerDictionary = new HeaderDictionary
            {
                { "Accept", new StringValues("application/json") }
            };

            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "pageRef", new StringValues(pageRef.ToString()) },
                { "allocationStatuses", new StringValues("Published,Approved") },
                { "pageSize", new StringValues(pageSize.ToString()) }
            });

            string scheme      = "https";
            string path        = "/api/v3/fundings/notifications";
            string host        = "wherever.naf:12345";
            string queryString = "?pageSize=2";

            HttpRequest request = Substitute.For <HttpRequest>();

            request.Scheme.Returns(scheme);
            request.Path.Returns(new PathString(path));
            request.Host.Returns(new HostString(host));
            request.QueryString.Returns(new QueryString(queryString));
            request.Headers.Returns(headerDictionary);
            request.Query.Returns(queryStringValues);

            //Act
            IActionResult result = await service.GetFunding(request, pageRef : pageRef, pageSize : pageSize);

            //Assert
            result
            .Should()
            .BeOfType <OkObjectResult>();

            OkObjectResult contentResult = result as OkObjectResult;

            Models.External.V3.AtomItems.AtomFeed <AtomEntry> atomFeed = contentResult.Value as Models.External.V3.AtomItems.AtomFeed <AtomEntry>;

            atomFeed
            .Should()
            .NotBeNull();

            atomFeed.Id.Should().NotBeEmpty();
            atomFeed.Title.Should().Be("Calculate Funding Service Funding Feed");
            atomFeed.Author.Name.Should().Be("Calculate Funding Service");
            atomFeed.Link.First(m => m.Rel == "next-archive").Href.Should().Be($"{scheme}://{host}{path}/3{queryString}");
            atomFeed.Link.First(m => m.Rel == "prev-archive").Href.Should().Be($"{scheme}://{host}{path}/1{queryString}");
            atomFeed.Link.First(m => m.Rel == "self").Href.Should().Be($"{scheme}://{host}{path}{queryString}");
            atomFeed.Link.First(m => m.Rel == "current").Href.Should().Be($"{scheme}://{host}{path}/2{queryString}");

            atomFeed.AtomEntry.Count.Should().Be(3);

            for (int i = 0; i < 3; i++)
            {
                string text = $"id-{i + 1}";
                atomFeed.AtomEntry.ElementAt(i).Id.Should().Be($"{scheme}://{host}/api/v3/fundings/byId/{text}");
                atomFeed.AtomEntry.ElementAt(i).Title.Should().Be(text);
                atomFeed.AtomEntry.ElementAt(i).Summary.Should().Be(text);
                atomFeed.AtomEntry.ElementAt(i).Content.Should().NotBeNull();
            }

            JObject content = atomFeed.AtomEntry.ElementAt(0).Content as JObject;

            content.TryGetValue("FundingStreamId", out JToken token);
            ((JValue)token).Value <string>().Should().Be("PES");

            await feedsSearchService
            .Received(1)
            .GetFeedsV3(pageRef, pageSize, null, null, null);

            await publishedFundingRetrievalService
            .Received(searchFeedEntries.Count)
            .GetFundingFeedDocument(Arg.Any <string>());

            foreach (PublishedFundingIndex index in searchFeedEntries)
            {
                await publishedFundingRetrievalService
                .Received(1)
                .GetFundingFeedDocument(index.DocumentPath);
            }
        }
Exemplo n.º 8
0
        public void SearchIndexTest_GivenSearchSchemasAndModels_EnsureFieldsMatch()
        {
            // Arrange
            IList <string>         ErrorLog = new List <string>();
            DatasetDefinitionIndex datasetDefinitionIndex = new DatasetDefinitionIndex();
            ProvidersIndex         providersIndex         = new ProvidersIndex();
            PublishedFundingIndex  publishedfundingindex  = new PublishedFundingIndex();
            PublishedProviderIndex publishedProviderIndex = new PublishedProviderIndex();
            SpecificationIndex     specificationindex     = new SpecificationIndex();
            TemplateIndex          templateIndex          = new TemplateIndex();

            IEnumerable <Type> searchIndexTypes = GetTypesWithSearchIndexAttribute();

            IEnumerable <string> indexNames = Directory
                                              .GetDirectories(searchIndexDirectoryPath, "*index", SearchOption.TopDirectoryOnly)
                                              .Select(m => new DirectoryInfo(m).Name);

            //Act
            foreach (string indexName in indexNames)
            {
                try
                {
                    string jsonFilePath = $@"{searchIndexDirectoryPath}\{indexName}\{indexName}.json";

                    string            jsonText          = File.ReadAllText(jsonFilePath, Encoding.UTF8);
                    SearchIndexSchema searchIndexSchema = JsonConvert.DeserializeObject <SearchIndexSchema>(jsonText);
                    if (searchIndexSchema?.Name == null)
                    {
                        ErrorLog.Add(string.IsNullOrWhiteSpace(jsonText)
                            ? $"{indexName} json is blank"
                            : $"{indexName} json name is not available");
                    }
                    else if (searchIndexSchema.Name != indexName)
                    {
                        ErrorLog.Add($"Expected to find index { indexName }, but found { searchIndexSchema.Name }");
                    }
                    else
                    {
                        Type searchIndexType = searchIndexTypes
                                               .FirstOrDefault(m => m.CustomAttributes
                                                               .FirstOrDefault(p => p.NamedArguments
                                                                               .Any(n => n.TypedValue.Value.ToString() == searchIndexSchema.Name)) != null);

                        IEnumerable <string> searchIndexProperties = searchIndexType.GetProperties()
                                                                     .Select(m => m.CustomAttributes
                                                                             .FirstOrDefault(a => a.AttributeType.Name == "JsonPropertyAttribute")
                                                                             ?.ConstructorArguments[0].Value.ToString().ToLower())
                                                                     .Where(p => p != null);

                        IEnumerable <string> searchIndexJsonProperties = searchIndexSchema.Fields
                                                                         .Select(m => m.Name.ToLower())
                                                                         .Where(p => p != null);

                        if (!searchIndexProperties.Any())
                        {
                            ErrorLog.Add($"Index {indexName}: The model contains no properties");
                        }
                        else if (!searchIndexJsonProperties.Any())
                        {
                            ErrorLog.Add($"Index {indexName}: The json contains no properties");
                        }
                        else
                        {
                            IEnumerable <string> notInJson = searchIndexProperties.Except(searchIndexJsonProperties);
                            if (notInJson.Any())
                            {
                                string properties = string.Join(",", notInJson);
                                ErrorLog.Add($"Index {indexName}: The model contains the following properties not found in the json schema ({properties})");
                            }

                            IEnumerable <string> notInModel = searchIndexJsonProperties.Except(searchIndexProperties);
                            if (notInModel.Any())
                            {
                                string properties = string.Join(",", notInModel);
                                ErrorLog.Add($"Index {indexName}: The json schema contains the following properties not found in the model ({properties})");
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    ErrorLog.Add($"Unexpected error checking '{indexName}': {e.Message}{Environment.NewLine}{ e.StackTrace }");
                }
            }

            //Assert
            if (ErrorLog.Any())
            {
                Assert.Fail(string.Join(Environment.NewLine, ErrorLog));
            }
        }
Exemplo n.º 9
0
        public void SearchIndexTest_GivenSearchSchemasAndModels_EnsuresAttributesMatch()
        {
            //Arrange
            IList <string>         ErrorLog = new List <string>();
            DatasetDefinitionIndex datasetDefinitionIndex = new DatasetDefinitionIndex();
            ProvidersIndex         providersIndex         = new ProvidersIndex();
            PublishedFundingIndex  publishedfundingindex  = new PublishedFundingIndex();
            PublishedProviderIndex publishedProviderIndex = new PublishedProviderIndex();
            SpecificationIndex     specificationindex     = new SpecificationIndex();
            TemplateIndex          templateIndex          = new TemplateIndex();

            IEnumerable <Type> searchIndexTypes = GetTypesWithSearchIndexAttribute();

            IEnumerable <string> indexNames = Directory
                                              .GetDirectories(searchIndexDirectoryPath, "*index", SearchOption.TopDirectoryOnly)
                                              .Select(m => new DirectoryInfo(m).Name);

            //Act
            foreach (string indexName in indexNames)
            {
                try
                {
                    string jsonFilePath = $@"{searchIndexDirectoryPath}\{indexName}\{indexName}.json";

                    string jsonText = File.ReadAllText(jsonFilePath, Encoding.UTF8);

                    SearchIndexSchema searchIndexSchema = JsonConvert.DeserializeObject <SearchIndexSchema>(jsonText);
                    if (searchIndexSchema?.Name == null)
                    {
                        ErrorLog.Add(string.IsNullOrWhiteSpace(jsonText)
                            ? $"{indexName} json is blank"
                            : $"{indexName} json name is not available");
                    }
                    else if (searchIndexSchema.Name != indexName)
                    {
                        ErrorLog.Add($"Expected to find index {indexName}, but found {searchIndexSchema.Name}");
                    }
                    else
                    {
                        Type searchIndexType = searchIndexTypes.FirstOrDefault(m =>
                                                                               m.CustomAttributes.FirstOrDefault(p =>
                                                                                                                 p.NamedArguments.Any(n =>
                                                                                                                                      n.TypedValue.Value.ToString() == searchIndexSchema.Name)) != null);

                        IEnumerable <PropertyInfo> searchIndexProperties = searchIndexType.GetProperties();

                        foreach (SearchIndexField searchIndexField in searchIndexSchema.Fields)
                        {
                            PropertyInfo matchedProperty = searchIndexProperties.FirstOrDefault(m =>
                                                                                                string.Equals(m.CustomAttributes
                                                                                                              .SingleOrDefault(x => x.AttributeType.Name == "JsonPropertyAttribute")
                                                                                                              ?.ConstructorArguments[0].ToString().Replace("\"", "")
                                                                                                              ?? m.Name,
                                                                                                              searchIndexField.Name,
                                                                                                              StringComparison.InvariantCultureIgnoreCase));

                            if (matchedProperty == null)
                            {
                                ErrorLog.Add($"{indexName}: {searchIndexField.Name} did not match any properties");
                            }
                            else
                            {
                                CheckIndexFieldTypes(matchedProperty, searchIndexField, ErrorLog, indexName);
                                CheckIndexAttributes(matchedProperty, searchIndexField, ErrorLog, indexName);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    ErrorLog.Add($"Unexpected error checking '{indexName}': {e.Message}{Environment.NewLine}{e.StackTrace}");
                }
            }

            //Assert
            if (ErrorLog.Any())
            {
                Assert.Fail(string.Join(Environment.NewLine, ErrorLog));
            }
        }