public void ReadFeedIteratorCore_FeedToken()
        {
            FeedTokenInternal feedToken         = Mock.Of <FeedTokenInternal>();
            FeedIteratorCore  feedTokenIterator = FeedIteratorCore.CreateForPartitionedResource(Mock.Of <ContainerCore>(), new Uri("http://localhost"), Documents.ResourceType.Document, null, null, feedToken, new QueryRequestOptions());

            Assert.AreEqual(feedToken, feedTokenIterator.FeedToken);
        }
        public void ChangeFeedIteratorCore_FeedToken()
        {
            FeedTokenInternal      feedToken = Mock.Of <FeedTokenInternal>();
            ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(Mock.Of <ContainerCore>(), feedToken, null);

            Assert.AreEqual(feedToken, changeFeedIteratorCore.FeedToken);
        }
        public async Task ChangeFeedIteratorCore_OfT_ReadNextAsync()
        {
            string          continuation    = "TBD";
            ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK);

            responseMessage.Headers.ETag = continuation;
            responseMessage.Headers[Documents.HttpConstants.HttpHeaders.ItemCount] = "1";

            Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>();

            cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions());
            cosmosClientContext
            .Setup(c => c.ProcessResourceOperationStreamAsync(
                       It.IsAny <Uri>(),
                       It.IsAny <Documents.ResourceType>(),
                       It.IsAny <Documents.OperationType>(),
                       It.IsAny <RequestOptions>(),
                       It.IsAny <ContainerCore>(),
                       It.IsAny <PartitionKey?>(),
                       It.IsAny <Stream>(),
                       It.IsAny <Action <RequestMessage> >(),
                       It.IsAny <CosmosDiagnosticsContext>(),
                       It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(responseMessage));

            ContainerCore containerCore = Mock.Of <ContainerCore>();

            Mock.Get(containerCore)
            .Setup(c => c.ClientContext)
            .Returns(cosmosClientContext.Object);
            FeedTokenInternal feedToken = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>()));
            Mock.Get(feedToken)
            .Setup(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(false));

            ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(containerCore, feedToken, null);

            bool creatorCalled = false;
            Func <ResponseMessage, FeedResponse <dynamic> > creator = (ResponseMessage r) =>
            {
                creatorCalled = true;
                return(Mock.Of <FeedResponse <dynamic> >());
            };

            FeedIteratorCore <dynamic> changeFeedIteratorCoreOfT = new FeedIteratorCore <dynamic>(changeFeedIteratorCore, creator);
            FeedResponse <dynamic>     response = await changeFeedIteratorCoreOfT.ReadNextAsync();

            Mock.Get(feedToken)
            .Verify(f => f.UpdateContinuation(It.Is <string>(ct => ct == continuation)), Times.Once);

            Mock.Get(feedToken)
            .Verify(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once);

            Assert.IsTrue(creatorCalled, "Response creator not called");
        }
        public async Task ReadFeedIteratorCore_ReadNextAsync()
        {
            string          continuation    = "TBD";
            ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK);

            responseMessage.Headers.ContinuationToken = continuation;
            responseMessage.Headers[Documents.HttpConstants.HttpHeaders.ItemCount] = "1";

            Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>();

            cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions());
            cosmosClientContext
            .Setup(c => c.ProcessResourceOperationStreamAsync(
                       It.IsAny <Uri>(),
                       It.IsAny <Documents.ResourceType>(),
                       It.IsAny <Documents.OperationType>(),
                       It.IsAny <RequestOptions>(),
                       It.IsAny <ContainerCore>(),
                       It.IsAny <PartitionKey?>(),
                       It.IsAny <Stream>(),
                       It.IsAny <Action <RequestMessage> >(),
                       It.IsAny <CosmosDiagnosticsContext>(),
                       It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(responseMessage));

            ContainerCore containerCore = Mock.Of <ContainerCore>();

            Mock.Get(containerCore)
            .Setup(c => c.ClientContext)
            .Returns(cosmosClientContext.Object);
            FeedTokenInternal feedToken = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>()));
            Mock.Get(feedToken)
            .Setup(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(false));
            Mock.Get(feedToken)
            .Setup(f => f.GetContinuation())
            .Returns(continuation);
            Mock.Get(feedToken)
            .Setup(f => f.IsDone)
            .Returns(true);

            FeedIteratorCore feedTokenIterator = FeedIteratorCore.CreateForPartitionedResource(containerCore, new Uri("http://localhost"), Documents.ResourceType.Document, null, null, feedToken, new QueryRequestOptions());
            ResponseMessage  response          = await feedTokenIterator.ReadNextAsync();

            Assert.AreEqual(feedToken, feedTokenIterator.FeedToken);
            Mock.Get(feedToken)
            .Verify(f => f.UpdateContinuation(It.Is <string>(ct => ct == continuation)), Times.Once);

            Mock.Get(feedToken)
            .Verify(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once);

            Mock.Get(feedToken)
            .Verify(f => f.IsDone, Times.Once);
        }
        public async Task ChangeFeedIteratorCore_Retries()
        {
            string          continuation    = "TBD";
            ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK);

            responseMessage.Headers.ETag = continuation;

            Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>();

            cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions());
            cosmosClientContext
            .Setup(c => c.ProcessResourceOperationStreamAsync(
                       It.IsAny <Uri>(),
                       It.IsAny <Documents.ResourceType>(),
                       It.IsAny <Documents.OperationType>(),
                       It.IsAny <RequestOptions>(),
                       It.IsAny <ContainerCore>(),
                       It.IsAny <PartitionKey?>(),
                       It.IsAny <Stream>(),
                       It.IsAny <Action <RequestMessage> >(),
                       It.IsAny <CosmosDiagnosticsContext>(),
                       It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(responseMessage));

            ContainerCore     containerCore = Mock.Of <ContainerCore>();
            FeedTokenInternal feedToken     = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>()));
            Mock.Get(feedToken)
            .SetupSequence(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(true))
            .Returns(Task.FromResult(false));

            ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(cosmosClientContext.Object, containerCore, feedToken, null);
            ResponseMessage        response = await changeFeedIteratorCore.ReadNextAsync();

            Mock.Get(feedToken)
            .Verify(f => f.UpdateContinuation(It.IsAny <string>()), Times.Exactly(2));

            Mock.Get(feedToken)
            .Verify(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Exactly(2));

            Mock.Get(cosmosClientContext.Object)
            .Verify(c => c.ProcessResourceOperationStreamAsync(
                        It.IsAny <Uri>(),
                        It.IsAny <Documents.ResourceType>(),
                        It.IsAny <Documents.OperationType>(),
                        It.IsAny <RequestOptions>(),
                        It.IsAny <ContainerCore>(),
                        It.IsAny <PartitionKey?>(),
                        It.IsAny <Stream>(),
                        It.IsAny <Action <RequestMessage> >(),
                        It.IsAny <CosmosDiagnosticsContext>(),
                        It.IsAny <CancellationToken>()), Times.Exactly(2));
        }
        public void ReadFeedIteratorCore_TryGetContinuation()
        {
            string            continuation = Guid.NewGuid().ToString();
            FeedTokenInternal feedToken    = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.GetContinuation()).Returns(continuation);
            FeedIteratorCore feedTokenIterator = FeedIteratorCore.CreateForPartitionedResource(Mock.Of <ContainerCore>(), new Uri("http://localhost"), Documents.ResourceType.Document, null, null, feedToken, new QueryRequestOptions());

            Assert.AreEqual(continuation, feedTokenIterator.ContinuationToken);
        }
        public void ChangeFeedIteratorCore_TryGetContinuation()
        {
            string            continuation = Guid.NewGuid().ToString();
            FeedTokenInternal feedToken    = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.GetContinuation()).Returns(continuation);
            ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(Mock.Of <CosmosClientContext>(), Mock.Of <ContainerCore>(), feedToken, null);

            Assert.IsTrue(changeFeedIteratorCore.TryGetContinuationToken(out string state));
            Assert.AreEqual(continuation, state);
        }
        public async Task ChangeFeedIteratorCore_HandlesSplitsThroughPipeline()
        {
            int executionCount = 0;
            CosmosClientContext cosmosClientContext = GetMockedClientContext((RequestMessage requestMessage, CancellationToken cancellationToken) =>
            {
                // Force OnBeforeRequestActions call
                requestMessage.ToDocumentServiceRequest();
                if (executionCount++ == 0)
                {
                    return(TestHandler.ReturnStatusCode(HttpStatusCode.Gone, Documents.SubStatusCodes.PartitionKeyRangeGone));
                }

                return(TestHandler.ReturnStatusCode(HttpStatusCode.OK));
            });

            ContainerCore containerCore = Mock.Of <ContainerCore>();

            Mock.Get(containerCore)
            .Setup(c => c.ClientContext)
            .Returns(cosmosClientContext);
            Mock.Get(containerCore)
            .Setup(c => c.LinkUri)
            .Returns(new Uri("https://dummy.documents.azure.com:443/dbs"));
            FeedTokenInternal feedToken = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>()));
            Mock.Get(feedToken)
            .Setup(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(false));

            ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(containerCore, feedToken, null);

            ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync();

            Assert.AreEqual(1, executionCount, "PartitionKeyRangeGoneRetryHandler handled the Split");
            Assert.AreEqual(HttpStatusCode.Gone, response.StatusCode);

            Mock.Get(feedToken)
            .Verify(f => f.UpdateContinuation(It.IsAny <string>()), Times.Never);

            Mock.Get(feedToken)
            .Verify(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once);
        }
        public async Task ReadFeedIteratorCore_HandlesSplitsThroughPipeline()
        {
            int executionCount = 0;
            CosmosClientContext cosmosClientContext = GetMockedClientContext((RequestMessage requestMessage, CancellationToken cancellationToken) =>
            {
                // Force OnBeforeRequestActions call
                requestMessage.ToDocumentServiceRequest();
                if (executionCount++ == 0)
                {
                    return(TestHandler.ReturnStatusCode(HttpStatusCode.Gone, Documents.SubStatusCodes.PartitionKeyRangeGone));
                }

                return(TestHandler.ReturnStatusCode(HttpStatusCode.OK));
            });

            ContainerCore containerCore = Mock.Of <ContainerCore>();

            Mock.Get(containerCore)
            .Setup(c => c.ClientContext)
            .Returns(cosmosClientContext);
            Mock.Get(containerCore)
            .Setup(c => c.LinkUri)
            .Returns(new Uri($"/dbs/db/colls/colls", UriKind.Relative));
            FeedTokenInternal feedToken = Mock.Of <FeedTokenInternal>();

            Mock.Get(feedToken)
            .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>()));
            Mock.Get(feedToken)
            .Setup(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(false));

            FeedIteratorCore changeFeedIteratorCore = FeedIteratorCore.CreateForPartitionedResource(containerCore, new Uri($"/dbs/db/colls/colls", UriKind.Relative), Documents.ResourceType.Document, null, null, feedToken, new QueryRequestOptions());

            ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync();

            Assert.AreEqual(1, executionCount, "Pipeline handled the Split");
            Assert.AreEqual(HttpStatusCode.Gone, response.StatusCode);
        }