public async Task FeedToken_PKRangeId_Serialization()
        {
            string continuationToken = "TBD";
            DocumentFeedResponse <Documents.PartitionKeyRange> ranges = await this.Container.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(this.Container.LinkUri);

            Documents.PartitionKeyRange oneRange = ranges.First();

            FeedTokenPartitionKeyRange original = new FeedTokenPartitionKeyRange(oneRange.Id);

            original.UpdateContinuation(continuationToken);
            string    serialized   = original.ToString();
            FeedToken deserialized = FeedToken.FromString(serialized);
            FeedTokenPartitionKeyRange deserializedFeedToken = deserialized as FeedTokenPartitionKeyRange;

            Assert.IsNotNull(deserialized, "Error deserializing to FeedTokenPartitionKeyRange");
            Assert.AreEqual(original.PartitionKeyRangeId, deserializedFeedToken.PartitionKeyRangeId);
            Assert.AreEqual(continuationToken, deserializedFeedToken.GetContinuation());

            // Verify that the backward compatible way works too
            FeedToken deserializedFromBackwardcompatible = FeedToken.FromString(oneRange.Id);
            FeedTokenPartitionKeyRange deserializedFromBackwardcompatibleToken = deserializedFromBackwardcompatible as FeedTokenPartitionKeyRange;

            Assert.IsNotNull(deserializedFromBackwardcompatibleToken, "Error deserializing to FeedTokenPartitionKeyRange");
            Assert.AreEqual(deserializedFromBackwardcompatibleToken.PartitionKeyRangeId, deserializedFeedToken.PartitionKeyRangeId);
        }
        public async Task FeedToken_PartitionKeyRange_HandleSplits()
        {
            string containerRid = Guid.NewGuid().ToString();
            string continuation = Guid.NewGuid().ToString();

            FeedTokenPartitionKeyRange feedTokenPartitionKeyRange = new FeedTokenPartitionKeyRange("0");

            feedTokenPartitionKeyRange.UpdateContinuation(continuation);
            PKRangeSplitMockDocumentClient documentClient = new PKRangeSplitMockDocumentClient();

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

            cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions());
            cosmosClientContext.Setup(c => c.DocumentClient).Returns(documentClient);

            Mock <ContainerCore> containerCore = new Mock <ContainerCore>();

            containerCore
            .Setup(c => c.ClientContext).Returns(cosmosClientContext.Object);

            containerCore
            .Setup(c => c.GetRIDAsync(It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(containerRid));

            ResponseMessage split = new ResponseMessage(HttpStatusCode.Gone);

            split.Headers.SubStatusCode = Documents.SubStatusCodes.PartitionKeyRangeGone;
            Assert.IsTrue(await feedTokenPartitionKeyRange.ShouldRetryAsync(containerCore.Object, split));

            // FeedToken should have converted to EPKRange token

            string            serialization     = feedTokenPartitionKeyRange.ToString();
            FeedTokenEPKRange feedTokenEPKRange = FeedToken.FromString(serialization) as FeedTokenEPKRange;

            Assert.IsNotNull(feedTokenEPKRange, "FeedTokenPartitionKeyRange did not convert to FeedTokenEPKRange after split");
            Assert.AreEqual(containerRid, feedTokenEPKRange.ContainerRid);

            // Split should only capture the sons of the original PKRangeId
            Assert.AreEqual(2, feedTokenEPKRange.CompositeContinuationTokens.Count);
            CompositeContinuationToken[] continuationTokens = feedTokenEPKRange.CompositeContinuationTokens.ToArray();
            // First token is split
            Assert.AreEqual(continuation, continuationTokens[0].Token);
            Assert.AreEqual(documentClient.AvailablePartitionKeyRanges[0].MinInclusive, continuationTokens[0].Range.Min);
            Assert.AreEqual(documentClient.AvailablePartitionKeyRanges[0].MaxExclusive, continuationTokens[0].Range.Max);

            // Second token remains the same
            Assert.AreEqual(continuation, continuationTokens[1].Token);
            Assert.AreEqual(documentClient.AvailablePartitionKeyRanges[1].MinInclusive, continuationTokens[1].Range.Min);
            Assert.AreEqual(documentClient.AvailablePartitionKeyRanges[1].MaxExclusive, continuationTokens[1].Range.Max);
        }
        private void FeedToken_PartitionKey_Validate(PartitionKey partitionKey)
        {
            string continuationToken = "TBD";
            FeedTokenPartitionKey feedTokenPartitionKey = new FeedTokenPartitionKey(partitionKey);

            feedTokenPartitionKey.UpdateContinuation(continuationToken);
            string                serialized            = feedTokenPartitionKey.ToString();
            FeedToken             deserialized          = FeedToken.FromString(serialized);
            FeedTokenPartitionKey deserializedFeedToken = deserialized as FeedTokenPartitionKey;

            Assert.IsNotNull(deserialized, "Error deserializing to FeedTokenPartitionKey");
            Assert.AreEqual(feedTokenPartitionKey.PartitionKey.ToJsonString(), deserializedFeedToken.PartitionKey.ToJsonString());
            Assert.AreEqual(continuationToken, deserializedFeedToken.GetContinuation());
        }
        public async Task FeedToken_EPKRange_Serialization()
        {
            string           continuation   = "TBD";
            List <FeedToken> tokens         = (await this.Container.GetFeedTokensAsync()).ToList();
            List <string>    serializations = new List <string>();

            foreach (FeedToken token in tokens)
            {
                (token as FeedTokenInternal).UpdateContinuation(continuation);
                serializations.Add(token.ToString());
            }

            List <FeedToken> deserialized = new List <FeedToken>();

            foreach (string serialized in serializations)
            {
                FeedToken token = FeedToken.FromString(serialized);
                deserialized.Add(token);
            }

            Assert.AreEqual(tokens.Count, deserialized.Count);

            for (int i = 0; i < tokens.Count; i++)
            {
                FeedTokenEPKRange originalToken     = tokens[i] as FeedTokenEPKRange;
                FeedTokenEPKRange deserializedToken = deserialized[i] as FeedTokenEPKRange;
                Assert.AreEqual(originalToken.GetContinuation(), deserializedToken.GetContinuation());
                Assert.AreEqual(originalToken.ContainerRid, deserializedToken.ContainerRid);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Count, deserializedToken.CompositeContinuationTokens.Count);
                Assert.AreEqual(originalToken.CompleteRange.Min, deserializedToken.CompleteRange.Min);
                Assert.AreEqual(originalToken.CompleteRange.Max, deserializedToken.CompleteRange.Max);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Peek().Token, deserializedToken.CompositeContinuationTokens.Peek().Token);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Peek().Range.Min, deserializedToken.CompositeContinuationTokens.Peek().Range.Min);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Peek().Range.Max, deserializedToken.CompositeContinuationTokens.Peek().Range.Max);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Peek().Range.IsMinInclusive, deserializedToken.CompositeContinuationTokens.Peek().Range.IsMinInclusive);
                Assert.AreEqual(originalToken.CompositeContinuationTokens.Peek().Range.IsMaxInclusive, deserializedToken.CompositeContinuationTokens.Peek().Range.IsMaxInclusive);
            }
        }