Ejemplo n.º 1
0
        public async Task SharedThroughputTests()
        {
            string           databaseId     = Guid.NewGuid().ToString();
            int              throughput     = 10000;
            DatabaseResponse createResponse = await this.CreateDatabaseHelper(databaseId, databaseExists : false, throughput : throughput);

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);

            Cosmos.Database cosmosDatabase = createResponse;
            int?            readThroughput = await cosmosDatabase.ReadThroughputAsync();

            Assert.AreEqual(throughput, readThroughput);

            string            containerId       = Guid.NewGuid().ToString();
            string            partitionPath     = "/users";
            ContainerResponse containerResponse = await cosmosDatabase.CreateContainerAsync(containerId, partitionPath);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);

            Container container = containerResponse;

            try
            {
                readThroughput = await((ContainerCore)container).ReadThroughputAsync();
                Assert.Fail("Should through not found exception as throughput is not configured");
            } catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            await container.DeleteContainerAsync();

            await cosmosDatabase.DeleteAsync();
        }
        public async Task ValidateCurrentWriteQuorumAndReplicaSetHeader()
        {
            CosmosClient client = TestCommon.CreateCosmosClient(false);

            Cosmos.Database db = null;
            try
            {
                db = await client.CreateDatabaseAsync(Guid.NewGuid().ToString());

                PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                    Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash
                };
                ContainerProperties containerSetting = new ContainerProperties()
                {
                    Id           = Guid.NewGuid().ToString(),
                    PartitionKey = partitionKeyDefinition
                };
                Container coll = await db.CreateContainerAsync(containerSetting);

                Document documentDefinition = new Document {
                    Id = Guid.NewGuid().ToString()
                };
                ItemResponse <Document> docResult = await coll.CreateItemAsync <Document>(documentDefinition);

                Assert.IsTrue(int.Parse(docResult.Headers[WFConstants.BackendHeaders.CurrentWriteQuorum], CultureInfo.InvariantCulture) > 0);
                Assert.IsTrue(int.Parse(docResult.Headers[WFConstants.BackendHeaders.CurrentReplicaSetSize], CultureInfo.InvariantCulture) > 0);
            }
            finally
            {
                await db.DeleteAsync();
            }
        }
Ejemplo n.º 3
0
        private static void InitializeSharedThroughputContainer()
        {
            CosmosClient client = TestCommon.CreateCosmosClient();

            Cosmos.Database db = client.CreateDatabaseAsync(string.Format("Shared_{0}", Guid.NewGuid().ToString("N")), throughput: 20000).GetAwaiter().GetResult().Database;

            for (int index = 0; index < 5; index++)
            {
                ContainerResponse containerResponse = db.CreateContainerAsync(
                    new ContainerProperties
                {
                    Id           = Guid.NewGuid().ToString(),
                    PartitionKey = BatchTestBase.PartitionKeyDefinition
                })
                                                      .GetAwaiter().GetResult();

                Assert.AreEqual(true, bool.Parse(containerResponse.Headers.Get(WFConstants.BackendHeaders.ShareThroughput)));

                if (index == 2)
                {
                    BatchTestBase.SharedThroughputContainer = containerResponse.Container;
                }
            }

            BatchTestBase.SharedThroughputDatabase = db;
        }
        public async Task SharedThroughputTests()
        {
            string           databaseId     = Guid.NewGuid().ToString();
            int              throughput     = 10000;
            DatabaseResponse createResponse = await this.CreateDatabaseHelper(databaseId, databaseExists : false, throughput : throughput);

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);

            Cosmos.Database cosmosDatabase = createResponse;
            int?            readThroughput = await((DatabaseCore)cosmosDatabase).ReadProvisionedThroughputAsync();

            Assert.AreEqual(throughput, readThroughput);

            string            containerId       = Guid.NewGuid().ToString();
            string            partitionPath     = "/users";
            ContainerResponse containerResponse = await cosmosDatabase.CreateContainerAsync(containerId, partitionPath);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);

            Container container = containerResponse;

            readThroughput = await((ContainerCore)container).ReadProvisionedThroughputAsync();
            Assert.IsNull(readThroughput);

            await container.DeleteContainerAsync();

            await cosmosDatabase.DeleteAsync();
        }
Ejemplo n.º 5
0
        public async Task ReadReplaceThroughputResponseTests()
        {
            string           databaseId     = Guid.NewGuid().ToString();
            int              throughput     = 10000;
            DatabaseResponse createResponse = await this.CreateDatabaseHelper(databaseId, databaseExists : false, throughput : throughput);

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);

            Cosmos.Database    cosmosDatabase         = createResponse;
            ThroughputResponse readThroughputResponse = await cosmosDatabase.ReadThroughputAsync(new RequestOptions());

            Assert.IsNotNull(readThroughputResponse);
            Assert.IsNotNull(readThroughputResponse.Resource);
            Assert.IsNotNull(readThroughputResponse.MinThroughput);
            Assert.IsNotNull(readThroughputResponse.Resource.Throughput);
            Assert.AreEqual(throughput, readThroughputResponse.Resource.Throughput.Value);

            // Implicit
            ThroughputProperties throughputProperties = await cosmosDatabase.ReadThroughputAsync(new RequestOptions());

            Assert.IsNotNull(throughputProperties);
            Assert.AreEqual(throughput, throughputProperties.Throughput);

            // Simple API
            int?readThroughput = await cosmosDatabase.ReadThroughputAsync();

            Assert.AreEqual(throughput, readThroughput);

            string            containerId       = Guid.NewGuid().ToString();
            string            partitionPath     = "/users";
            ContainerResponse containerResponse = await cosmosDatabase.CreateContainerAsync(containerId, partitionPath);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);

            ThroughputResponse replaceThroughputResponse = await cosmosDatabase.ReplaceThroughputAsync(readThroughputResponse.Resource.Throughput.Value + 1000);

            Assert.IsNotNull(replaceThroughputResponse);
            Assert.IsNotNull(replaceThroughputResponse.Resource);
            Assert.AreEqual(readThroughputResponse.Resource.Throughput.Value + 1000, replaceThroughputResponse.Resource.Throughput.Value);

            Container container = containerResponse;

            try
            {
                readThroughputResponse = await container.ReadThroughputAsync(new RequestOptions());

                Assert.Fail("Should through not found exception as throughput is not configured");
            }
            catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            await container.DeleteContainerAsync();

            await cosmosDatabase.DeleteAsync();
        }
        public async Task TransportExceptionValidationTest(bool injectCpuMonitor)
        {
            CosmosClient cosmosClient = TestCommon.CreateCosmosClient(
                builder =>
            {
                builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper(
                                                              transportClient,
                                                              TransportWrapperTests.ThrowTransportExceptionOnItemOperation,
                                                              injectCpuMonitor));
            });

            Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

            Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id");

            try
            {
                TestPayload payload1 = await container.CreateItemAsync <TestPayload>(new TestPayload { id = "bad" }, new Cosmos.PartitionKey("bad"));

                Assert.Fail("Create item should fail with TransportException");
            }
            catch (CosmosException ce)
            {
                this.ValidateTransportException(ce, injectCpuMonitor);
            }

            try
            {
                FeedIterator <TestPayload> feedIterator = container.GetItemQueryIterator <TestPayload>("select * from T where T.Random = 19827 ");
                await feedIterator.ReadNextAsync();

                Assert.Fail("Create item should fail with TransportException");
            }
            catch (CosmosException ce)
            {
                this.ValidateTransportException(ce, injectCpuMonitor);
            }

            using (ResponseMessage responseMessage = await container.CreateItemStreamAsync(
                       TestCommon.SerializerCore.ToStream(new TestPayload {
                id = "bad"
            }),
                       new Cosmos.PartitionKey("bad")))
            {
                this.ValidateTransportException(responseMessage);
            }

            FeedIterator streamIterator = container.GetItemQueryStreamIterator("select * from T where T.Random = 19827 ");

            using (ResponseMessage responseMessage = await streamIterator.ReadNextAsync())
            {
                this.ValidateTransportException(responseMessage);
            }
        }
Ejemplo n.º 7
0
        public async Task HttpClientConnectionLimitTest()
        {
            int gatewayConnectionLimit = 1;

            IReadOnlyList <string> excludeConnections = GetActiveConnections();
            CosmosClient           cosmosClient       = new CosmosClient(
                ConfigurationManager.AppSettings["GatewayEndpoint"],
                ConfigurationManager.AppSettings["MasterKey"],
                new CosmosClientOptions
            {
                ApplicationName = "test",
                GatewayModeMaxConnectionLimit = gatewayConnectionLimit,
                ConnectionMode     = ConnectionMode.Gateway,
                ConnectionProtocol = Protocol.Https
            }
                );

            FieldInfo         httpClient        = cosmosClient.DocumentClient.GetType().GetField("httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
            CosmosHttpClient  cosmosHttpClient  = (CosmosHttpClient)httpClient.GetValue(cosmosClient.DocumentClient);
            HttpClientHandler httpClientHandler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler;

            Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);

            Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

            Container container = await database.CreateContainerAsync(
                "TestConnections",
                "/pk",
                throughput : 20000);

            List <Task> creates = new List <Task>();

            for (int i = 0; i < 100; i++)
            {
                creates.Add(container.CreateItemAsync <dynamic>(new { id = Guid.NewGuid().ToString(), pk = Guid.NewGuid().ToString() }));
            }

            await Task.WhenAll(creates);

            // Verify the handler still exists after client warm up
            //Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);
            IReadOnlyList <string> afterConnections = GetActiveConnections();

            // Clean up the database and container
            await database.DeleteAsync();

            int connectionDiff = afterConnections.Count - excludeConnections.Count;

            Assert.IsTrue(connectionDiff <= gatewayConnectionLimit, $"Connection before : {excludeConnections.Count}, after {afterConnections.Count}");
        }
Ejemplo n.º 8
0
        public async Task HttpClientConnectionLimitTest()
        {
            int gatewayConnectionLimit = 1;

            IReadOnlyList <string> excludeConnections = GetActiveConnections();

            using (CosmosClient cosmosClient = new CosmosClient(
                       ConfigurationManager.AppSettings["GatewayEndpoint"],
                       ConfigurationManager.AppSettings["MasterKey"],
                       new CosmosClientOptions
            {
                ApplicationName = "test",
                GatewayModeMaxConnectionLimit = gatewayConnectionLimit,
                ConnectionMode = ConnectionMode.Gateway,
                ConnectionProtocol = Protocol.Https
            }
                       ))
            {
                CosmosHttpClient  cosmosHttpClient  = cosmosClient.DocumentClient.httpClient;
                HttpClientHandler httpClientHandler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler;
                Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);

                Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

                Container container = await database.CreateContainerAsync(
                    "TestConnections",
                    "/pk",
                    throughput : 20000);

                List <Task> creates = new List <Task>();
                for (int i = 0; i < 100; i++)
                {
                    creates.Add(container.CreateItemAsync <dynamic>(new { id = Guid.NewGuid().ToString(), pk = Guid.NewGuid().ToString() }));
                }

                await Task.WhenAll(creates);

                // Clean up the database and container
                await database.DeleteAsync();
            }


            IReadOnlyList <string> afterConnections = GetActiveConnections();

            int connectionDiff = afterConnections.Count - excludeConnections.Count;

            Assert.IsTrue(connectionDiff <= gatewayConnectionLimit, $"Connection before : {excludeConnections.Count}, after {afterConnections.Count};" +
                          $"Before connections: {JsonConvert.SerializeObject(excludeConnections)}; After connections: {JsonConvert.SerializeObject(afterConnections)}");
        }
        public static Func <bool, IQueryable <Data> > GenerateSimpleCosmosData(
            Cosmos.Database cosmosDatabase
            )
        {
            const int DocumentCount = 10;
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/Pk" }), Kind = PartitionKind.Hash
            };
            Container container = cosmosDatabase.CreateContainerAsync(new ContainerProperties {
                Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
            }).Result;

            int    seed   = DateTime.Now.Millisecond;
            Random random = new Random(seed);

            Debug.WriteLine("Random seed: {0}", seed);
            List <Data> testData = new List <Data>();

            for (int index = 0; index < DocumentCount; index++)
            {
                Data dataEntry = new Data()
                {
                    Id        = Guid.NewGuid().ToString(),
                    Number    = random.Next(-10000, 10000),
                    Flag      = index % 2 == 0 ? true : false,
                    Multiples = new int[] { index, index * 2, index * 3, index * 4 },
                    Pk        = "Test"
                };

                Data response = container.CreateItemAsync <Data>(dataEntry, new Cosmos.PartitionKey(dataEntry.Pk)).Result;
                testData.Add(dataEntry);
            }

            FeedOptions feedOptions = new FeedOptions()
            {
                EnableScanInQuery = true, EnableCrossPartitionQuery = true
            };
            var query = container.GetItemLinqQueryable <Data>(allowSynchronousQueryExecution: true);

            // To cover both query against backend and queries on the original data using LINQ nicely,
            // the LINQ expression should be written once and they should be compiled and executed against the two sources.
            // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query
            // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values
            // to this getQuery method.
            IQueryable <Data> getQuery(bool useQuery) => useQuery ? query : testData.AsQueryable();

            return(getQuery);
        }
        public async Task TransportInterceptorContractTest()
        {
            CosmosClient cosmosClient = TestCommon.CreateCosmosClient(
                builder =>
            {
                builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper(transportClient, TransportWrapperTests.Interceptor));
            });

            Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

            Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id");

            string      id1      = Guid.NewGuid().ToString();
            TestPayload payload1 = await container.CreateItemAsync <TestPayload>(new TestPayload { id = id1 });

            payload1 = await container.ReadItemAsync <TestPayload>(id1, new Cosmos.PartitionKey(id1));
        }
        public async Task TestInitialize()
        {
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/Pk" }), Kind = PartitionKind.Hash
            };
            // The test collection should have range index on string properties
            // for the orderby tests
            var newCol = new ContainerProperties()
            {
                Id             = Guid.NewGuid().ToString(),
                PartitionKey   = partitionKeyDefinition,
                IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy()
                {
                    IncludedPaths = new System.Collections.ObjectModel.Collection <Microsoft.Azure.Cosmos.IncludedPath>()
                    {
                        new Microsoft.Azure.Cosmos.IncludedPath()
                        {
                            Path    = "/*",
                            Indexes = new System.Collections.ObjectModel.Collection <Microsoft.Azure.Cosmos.Index>()
                            {
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1),
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1)
                            }
                        }
                    }
                }
            };

            testCollection = await testDb.CreateContainerAsync(newCol);

            const int            Records         = 100;
            const int            MaxStringLength = 100;
            Func <Random, Datum> createDataFunc  = random =>
            {
                var obj = new Datum();
                obj.Id           = Guid.NewGuid().ToString();
                obj.Pk           = "Test";
                obj.JsonProperty = random.NextDouble() < 0.3 ? "Hello" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength));
                obj.JsonPropertyAndDataMember = random.NextDouble() < 0.3 ? "Hello" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength));
                obj.DataMember = random.NextDouble() < 0.3 ? "Hello" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength));
                obj.Default    = random.NextDouble() < 0.3 ? "Hello" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength));
                return(obj);
            };

            getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataFunc, Records, testCollection);
        }
Ejemplo n.º 12
0
        public async Task HttpClientFactorySmokeTest()
        {
            HttpClient client = new HttpClient();
            Mock <Func <HttpClient> > factory = new Mock <Func <HttpClient> >();

            factory.Setup(f => f()).Returns(client);
            CosmosClient cosmosClient = new CosmosClient(
                ConfigurationManager.AppSettings["GatewayEndpoint"],
                ConfigurationManager.AppSettings["MasterKey"],
                new CosmosClientOptions
            {
                ApplicationName    = "test",
                ConnectionMode     = ConnectionMode.Gateway,
                ConnectionProtocol = Protocol.Https,
                HttpClientFactory  = factory.Object
            }
                );

            string someId = Guid.NewGuid().ToString();

            Cosmos.Database database = null;
            try
            {
                database = await cosmosClient.CreateDatabaseAsync(someId);

                Cosmos.Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id");

                await container.CreateItemAsync <dynamic>(new { id = someId });

                await container.ReadItemAsync <dynamic>(someId, new Cosmos.PartitionKey(someId));

                await container.DeleteItemAsync <dynamic>(someId, new Cosmos.PartitionKey(someId));

                await container.DeleteContainerAsync();

                Mock.Get(factory.Object).Verify(f => f(), Times.Once);
            }
            finally
            {
                if (database != null)
                {
                    await database.DeleteAsync();
                }
            }
        }
Ejemplo n.º 13
0
        public async Task QueryPlanRetryTimeoutTestAsync()
        {
            HttpClientHandlerHelper httpClientHandler = new HttpClientHandlerHelper();

            using (CosmosClient client = TestCommon.CreateCosmosClient(builder => builder
                                                                       .WithConnectionModeGateway()
                                                                       .WithHttpClientFactory(() => new HttpClient(httpClientHandler))))
            {
                Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString());

                ContainerInternal container = (ContainerInternal)await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk");

                Container gatewayQueryPlanContainer = new ContainerInlineCore(
                    client.ClientContext,
                    (DatabaseInternal)database,
                    container.Id,
                    new DisableServiceInterop(client.ClientContext, container));

                bool isQueryRequestFound = false;
                httpClientHandler.RequestCallBack = (request, cancellationToken) =>
                {
                    if (request.Headers.TryGetValues(HttpConstants.HttpHeaders.IsQueryPlanRequest, out IEnumerable <string> isQueryPlan) &&
                        isQueryPlan.FirstOrDefault() == bool.TrueString)
                    {
                        Assert.IsFalse(isQueryRequestFound, "Should only call get query plan once.");
                        Assert.AreNotEqual(cancellationToken, default);
                        isQueryRequestFound = true;
                    }
                };

                using FeedIterator <JObject> iterator = gatewayQueryPlanContainer.GetItemQueryIterator <JObject>("select * From T order by T.status");
                FeedResponse <JObject> response       = await iterator.ReadNextAsync();

                Assert.IsTrue(isQueryRequestFound, "Query plan call back was not called.");

                string  diagnostics       = response.Diagnostics.ToString();
                JObject parsedDiagnostics = JObject.Parse(diagnostics);
                JToken  contextList       = parsedDiagnostics["Context"];

                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "CreateQueryPipeline"));
                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "Microsoft.Azure.Cosmos.GatewayStoreModel"));
                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "SendHttpHelperAsync:" + nameof(HttpTimeoutPolicyControlPlaneRetriableHotPath)));
                await database.DeleteStreamAsync();
            }
        }
Ejemplo n.º 14
0
        private static async Task RoundTripWithLocal(Cosmos.IndexingPolicy indexingPolicy)
        {
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash
            };
            ContainerProperties containerSetting = new ContainerProperties()
            {
                Id             = Guid.NewGuid().ToString(),
                IndexingPolicy = indexingPolicy,
                PartitionKey   = partitionKeyDefinition
            };

            Cosmos.Database cosmosDatabase = await cosmosClient.CreateDatabaseIfNotExistsAsync(IndexingPolicyTests.database.Id);

            ContainerResponse cosmosContainerResponse = await cosmosDatabase.CreateContainerAsync(containerSetting);

            Assert.IsTrue(IndexingPolicyTests.indexingPolicyEqualityComparer.Equals(indexingPolicy, containerSetting.IndexingPolicy));
        }
        public async Task ReadReplaceThroughputResponseTests()
        {
            string           databaseId     = Guid.NewGuid().ToString();
            int              throughput     = 10000;
            DatabaseResponse createResponse = await this.CreateDatabaseHelper(databaseId, databaseExists : false, throughput : throughput);

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);

            Cosmos.Database    cosmosDatabase         = createResponse;
            ThroughputResponse readThroughputResponse = await cosmosDatabase.ReadThroughputAsync();

            Assert.IsNotNull(readThroughputResponse);
            Assert.IsNotNull(readThroughputResponse.Resource);
            Assert.IsNotNull(readThroughputResponse.MinThroughput);
            Assert.IsNotNull(readThroughputResponse.Resource.Throughput);
            Assert.AreEqual(throughput, readThroughputResponse.Resource.Throughput.Value);

            string            containerId       = Guid.NewGuid().ToString();
            string            partitionPath     = "/users";
            ContainerResponse containerResponse = await cosmosDatabase.CreateContainerAsync(containerId, partitionPath);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);

            ThroughputResponse replaceThroughputResponse = await cosmosDatabase.ReplaceThroughputAsync(readThroughputResponse.Resource.Throughput.Value + 1000);

            Assert.IsNotNull(replaceThroughputResponse);
            Assert.IsNotNull(replaceThroughputResponse.Resource);
            Assert.AreEqual(readThroughputResponse.Resource.Throughput.Value + 1000, replaceThroughputResponse.Resource.Throughput.Value);

            Container container = containerResponse;

            readThroughputResponse = await container.ReadThroughputAsync();

            Assert.IsNull(readThroughputResponse.Resource);

            await container.DeleteContainerAsync();

            await cosmosDatabase.DeleteAsync();
        }
        public async Task ReadReplaceThroughputResponseTests()
        {
            int toStreamCount   = 0;
            int fromStreamCount = 0;

            CosmosSerializerHelper mockJsonSerializer = new CosmosSerializerHelper(
                null,
                (x) => fromStreamCount++,
                (x) => toStreamCount++);

            //Create a new cosmos client with the mocked cosmos json serializer
            CosmosClient client = TestCommon.CreateCosmosClient(
                (cosmosClientBuilder) => cosmosClientBuilder.WithCustomSerializer(mockJsonSerializer));

            int databaseThroughput = 10000;

            Cosmos.Database databaseNoThroughput = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), null);

            Cosmos.Database databaseWithThroughput = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), databaseThroughput, null);


            string    containerId           = Guid.NewGuid().ToString();
            string    partitionPath         = "/users";
            Container containerNoThroughput = await databaseWithThroughput.CreateContainerAsync(containerId, partitionPath, throughput : null);

            try
            {
                await containerNoThroughput.ReadThroughputAsync(new RequestOptions());

                Assert.Fail("Should through not found exception as throughput is not configured");
            }
            catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            try
            {
                await containerNoThroughput.ReplaceThroughputAsync(2000, new RequestOptions());

                Assert.Fail("Should through not found exception as throughput is not configured");
            }
            catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            int       containerThroughput = 1000;
            Container container           = await databaseNoThroughput.CreateContainerAsync(Guid.NewGuid().ToString(), "/id", throughput : containerThroughput);

            int?containerResponseThroughput = await container.ReadThroughputAsync();

            Assert.AreEqual(containerThroughput, containerResponseThroughput);

            ThroughputResponse containerThroughputResponse = await container.ReadThroughputAsync(new RequestOptions());

            Assert.IsNotNull(containerThroughputResponse);
            Assert.IsNotNull(containerThroughputResponse.Resource);
            Assert.IsNotNull(containerThroughputResponse.MinThroughput);
            Assert.IsNotNull(containerThroughputResponse.Resource.Throughput);
            Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value);

            containerThroughput        += 500;
            containerThroughputResponse = await container.ReplaceThroughputAsync(containerThroughput, new RequestOptions());

            Assert.IsNotNull(containerThroughputResponse);
            Assert.IsNotNull(containerThroughputResponse.Resource);
            Assert.IsNotNull(containerThroughputResponse.Resource.Throughput);
            Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value);

            Assert.AreEqual(0, toStreamCount, "Custom serializer to stream should not be used for offer operations");
            Assert.AreEqual(0, fromStreamCount, "Custom serializer from stream should not be used for offer operations");
            await databaseNoThroughput.DeleteAsync();
        }
Ejemplo n.º 17
0
        public async Task ValidateAzureKeyCredentialDirectModeUpdateAsync()
        {
            string authKey  = ConfigurationManager.AppSettings["MasterKey"];
            string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"];

            AzureKeyCredential masterKeyCredential = new AzureKeyCredential(authKey);

            using (CosmosClient client = new CosmosClient(
                       endpoint,
                       masterKeyCredential))
            {
                string databaseName = Guid.NewGuid().ToString();

                try
                {
                    Cosmos.Database database        = client.GetDatabase(databaseName);
                    ResponseMessage responseMessage = await database.ReadStreamAsync();

                    Assert.AreEqual(HttpStatusCode.NotFound, responseMessage.StatusCode);

                    {
                        // Random key: Next set of actions are expected to fail => 401 (UnAuthorized)
                        masterKeyCredential.Update(Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())));

                        responseMessage = await database.ReadStreamAsync();

                        Assert.AreEqual(HttpStatusCode.Unauthorized, responseMessage.StatusCode);

                        string diagnostics = responseMessage.Diagnostics.ToString();
                        Assert.IsTrue(diagnostics.Contains("AuthProvider LifeSpan InSec"), diagnostics.ToString());
                    }

                    {
                        // Resetting back to master key => 404 (NotFound)
                        masterKeyCredential.Update(authKey);
                        responseMessage = await database.ReadStreamAsync();

                        Assert.AreEqual(HttpStatusCode.NotFound, responseMessage.StatusCode);
                    }


                    // Test with resource token interchageability
                    masterKeyCredential.Update(authKey);
                    database = await client.CreateDatabaseAsync(databaseName);

                    string            containerId       = Guid.NewGuid().ToString();
                    ContainerResponse containerResponse = await database.CreateContainerAsync(containerId, "/id");

                    Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);


                    {
                        // Resource token with ALL permissoin's
                        string       userId       = Guid.NewGuid().ToString();
                        UserResponse userResponse = await database.CreateUserAsync(userId);

                        Cosmos.User user = userResponse.User;
                        Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode);
                        Assert.AreEqual(userId, user.Id);

                        string permissionId = Guid.NewGuid().ToString();
                        PermissionProperties permissionProperties = new PermissionProperties(permissionId, Cosmos.PermissionMode.All, client.GetContainer(databaseName, containerId));
                        PermissionResponse   permissionResponse   = await database.GetUser(userId).CreatePermissionAsync(permissionProperties);

                        Assert.AreEqual(HttpStatusCode.Created, permissionResponse.StatusCode);
                        Assert.AreEqual(permissionId, permissionResponse.Resource.Id);
                        Assert.AreEqual(Cosmos.PermissionMode.All, permissionResponse.Resource.PermissionMode);
                        Assert.IsNotNull(permissionResponse.Resource.Token);
                        SelflinkValidator.ValidatePermissionSelfLink(permissionResponse.Resource.SelfLink);

                        // Valdiate ALL on contianer
                        masterKeyCredential.Update(permissionResponse.Resource.Token);
                        ToDoActivity item = ToDoActivity.CreateRandomToDoActivity();

                        Cosmos.Container container = client.GetContainer(databaseName, containerId);

                        responseMessage = await container.ReadContainerStreamAsync();

                        Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode);

                        responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id));

                        Assert.AreEqual(HttpStatusCode.Created, responseMessage.StatusCode); // Read Only resorce token
                    }

                    // Reset to master key for new permission creation
                    masterKeyCredential.Update(authKey);

                    {
                        // Resource token with Read-ONLY permissoin's
                        string       userId       = Guid.NewGuid().ToString();
                        UserResponse userResponse = await database.CreateUserAsync(userId);

                        Cosmos.User user = userResponse.User;
                        Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode);
                        Assert.AreEqual(userId, user.Id);

                        string permissionId = Guid.NewGuid().ToString();
                        PermissionProperties permissionProperties = new PermissionProperties(permissionId, Cosmos.PermissionMode.Read, client.GetContainer(databaseName, containerId));
                        PermissionResponse   permissionResponse   = await database.GetUser(userId).CreatePermissionAsync(permissionProperties);

                        //Backend returns Created instead of OK
                        Assert.AreEqual(HttpStatusCode.Created, permissionResponse.StatusCode);
                        Assert.AreEqual(permissionId, permissionResponse.Resource.Id);
                        Assert.AreEqual(Cosmos.PermissionMode.Read, permissionResponse.Resource.PermissionMode);

                        // Valdiate read on contianer
                        masterKeyCredential.Update(permissionResponse.Resource.Token);
                        ToDoActivity item = ToDoActivity.CreateRandomToDoActivity();

                        Cosmos.Container container = client.GetContainer(databaseName, containerId);

                        responseMessage = await container.ReadContainerStreamAsync();

                        Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode);

                        responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id));

                        Assert.AreEqual(HttpStatusCode.Forbidden, responseMessage.StatusCode); // Read Only resorce token
                    }

                    {
                        // Reset to master key for new permission creation
                        masterKeyCredential.Update(Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())));

                        ToDoActivity     item      = ToDoActivity.CreateRandomToDoActivity();
                        Cosmos.Container container = client.GetContainer(databaseName, containerId);

                        responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id));

                        Assert.AreEqual(HttpStatusCode.Unauthorized, responseMessage.StatusCode); // Read Only resorce token

                        string diagnostics = responseMessage.Diagnostics.ToString();
                        Assert.IsTrue(diagnostics.Contains("AuthProvider LifeSpan InSec"), diagnostics.ToString());
                    }
                }
                finally
                {
                    // Reset to master key for clean-up
                    masterKeyCredential.Update(authKey);
                    await TestCommon.DeleteDatabaseAsync(client, client.GetDatabase(databaseName));
                }
            }
        }
Ejemplo n.º 18
0
        public async Task ReadReplaceThroughputResponseTests()
        {
            int toStreamCount   = 0;
            int fromStreamCount = 0;

            CosmosSerializerHelper mockJsonSerializer = new CosmosSerializerHelper(
                null,
                (x) => fromStreamCount++,
                (x) => toStreamCount++);

            //Create a new cosmos client with the mocked cosmos json serializer
            CosmosClient client = TestCommon.CreateCosmosClient(
                (cosmosClientBuilder) => cosmosClientBuilder.WithCustomSerializer(mockJsonSerializer));

            string           databaseId     = Guid.NewGuid().ToString();
            int              throughput     = 10000;
            DatabaseResponse createResponse = await client.CreateDatabaseAsync(databaseId, throughput, null);

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);

            Cosmos.Database    cosmosDatabase         = createResponse;
            ThroughputResponse readThroughputResponse = await cosmosDatabase.ReadThroughputAsync(new RequestOptions());

            Assert.IsNotNull(readThroughputResponse);
            Assert.IsNotNull(readThroughputResponse.Resource);
            Assert.IsNotNull(readThroughputResponse.MinThroughput);
            Assert.IsNotNull(readThroughputResponse.Resource.Throughput);
            Assert.AreEqual(throughput, readThroughputResponse.Resource.Throughput.Value);

            // Implicit
            ThroughputProperties throughputProperties = await cosmosDatabase.ReadThroughputAsync(new RequestOptions());

            Assert.IsNotNull(throughputProperties);
            Assert.AreEqual(throughput, throughputProperties.Throughput);

            // Simple API
            int?readThroughput = await cosmosDatabase.ReadThroughputAsync();

            Assert.AreEqual(throughput, readThroughput);

            // Database must have a container before it can be scaled
            string            containerId       = Guid.NewGuid().ToString();
            string            partitionPath     = "/users";
            ContainerResponse containerResponse = await cosmosDatabase.CreateContainerAsync(containerId, partitionPath, throughput : null);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);

            ThroughputResponse replaceThroughputResponse = await cosmosDatabase.ReplaceThroughputAsync(readThroughputResponse.Resource.Throughput.Value + 1000);

            Assert.IsNotNull(replaceThroughputResponse);
            Assert.IsNotNull(replaceThroughputResponse.Resource);
            Assert.AreEqual(readThroughputResponse.Resource.Throughput.Value + 1000, replaceThroughputResponse.Resource.Throughput.Value);

            await cosmosDatabase.DeleteAsync();

            Database databaseNoThroughput = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), throughput : null);

            try
            {
                ThroughputResponse throughputResponse = await databaseNoThroughput.ReadThroughputAsync(new RequestOptions());

                Assert.Fail("Should through not found exception as throughput is not configured");
            }
            catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            try
            {
                ThroughputResponse throughputResponse = await databaseNoThroughput.ReplaceThroughputAsync(2000, new RequestOptions());

                Assert.Fail("Should through not found exception as throughput is not configured");
            }
            catch (CosmosException exception)
            {
                Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
            }

            int?dbThroughput = await databaseNoThroughput.ReadThroughputAsync();

            Assert.IsNull(dbThroughput);

            Assert.AreEqual(0, toStreamCount, "Custom serializer to stream should not be used for offer operations");
            Assert.AreEqual(0, fromStreamCount, "Custom serializer from stream should not be used for offer operations");
            await databaseNoThroughput.DeleteAsync();
        }
Ejemplo n.º 19
0
        public void VerifySynchronizationContextDoesNotLock()
        {
            string databaseId = Guid.NewGuid().ToString();
            SynchronizationContext prevContext = SynchronizationContext.Current;

            try
            {
                TestSynchronizationContext syncContext = new TestSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(syncContext);
                syncContext.Post(_ =>
                {
                    using (CosmosClient client = TestCommon.CreateCosmosClient())
                    {
                        Cosmos.Database database = client.CreateDatabaseAsync(databaseId).GetAwaiter().GetResult();
                        database = client.CreateDatabaseIfNotExistsAsync(databaseId).GetAwaiter().GetResult();

                        database.ReadStreamAsync().ConfigureAwait(false).GetAwaiter().GetResult();
                        database.ReadAsync().ConfigureAwait(false).GetAwaiter().GetResult();

                        QueryDefinition databaseQuery = new QueryDefinition("select * from T where T.id = @id").WithParameter("@id", databaseId);
                        FeedIterator <DatabaseProperties> databaseIterator = client.GetDatabaseQueryIterator <DatabaseProperties>(databaseQuery);
                        while (databaseIterator.HasMoreResults)
                        {
                            databaseIterator.ReadNextAsync().GetAwaiter().GetResult();
                        }

                        Container container = database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk").GetAwaiter().GetResult();
                        container           = database.CreateContainerIfNotExistsAsync(container.Id, "/pk").GetAwaiter().GetResult();

                        ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity();
                        ItemResponse <ToDoActivity> response = container.CreateItemAsync <ToDoActivity>(item: testItem).ConfigureAwait(false).GetAwaiter().GetResult();
                        Assert.IsNotNull(response);
                        string diagnostics = response.Diagnostics.ToString();
                        Assert.IsTrue(diagnostics.Contains("SynchronizationContext"));

                        using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

                        try
                        {
                            ToDoActivity tempItem = ToDoActivity.CreateRandomToDoActivity();
                            CancellationToken cancellationToken = cancellationTokenSource.Token;
                            cancellationTokenSource.Cancel();
                            container.CreateItemAsync <ToDoActivity>(item: tempItem, cancellationToken: cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
                            Assert.Fail("Should have thrown a cancellation token");
                        }catch (CosmosOperationCanceledException oe)
                        {
                            string exception = oe.ToString();
                            Assert.IsTrue(exception.Contains("SynchronizationContext"));
                        }

                        // Test read feed
                        container.GetItemLinqQueryable <ToDoActivity>(
                            allowSynchronousQueryExecution: true,
                            requestOptions: new QueryRequestOptions()
                        {
                        }).ToList();

                        FeedIterator feedIterator = container.GetItemLinqQueryable <ToDoActivity>()
                                                    .ToStreamIterator();

                        while (feedIterator.HasMoreResults)
                        {
                            feedIterator.ReadNextAsync().GetAwaiter().GetResult();
                        }

                        FeedIterator <ToDoActivity> feedIteratorTyped = container.GetItemLinqQueryable <ToDoActivity>()
                                                                        .ToFeedIterator <ToDoActivity>();

                        while (feedIteratorTyped.HasMoreResults)
                        {
                            feedIteratorTyped.ReadNextAsync().GetAwaiter().GetResult();
                        }

                        // Test query
                        container.GetItemLinqQueryable <ToDoActivity>(
                            allowSynchronousQueryExecution: true,
                            requestOptions: new QueryRequestOptions()
                        {
                        }).Where(item => item.id != "").ToList();

                        FeedIterator queryIterator = container.GetItemLinqQueryable <ToDoActivity>()
                                                     .Where(item => item.id != "").ToStreamIterator();

                        while (queryIterator.HasMoreResults)
                        {
                            queryIterator.ReadNextAsync().GetAwaiter().GetResult();
                        }

                        FeedIterator <ToDoActivity> queryIteratorTyped = container.GetItemLinqQueryable <ToDoActivity>()
                                                                         .Where(item => item.id != "").ToFeedIterator <ToDoActivity>();

                        while (queryIteratorTyped.HasMoreResults)
                        {
                            queryIteratorTyped.ReadNextAsync().GetAwaiter().GetResult();
                        }

                        double costAsync = container.GetItemLinqQueryable <ToDoActivity>()
                                           .Select(x => x.cost).SumAsync().GetAwaiter().GetResult();

                        double cost = container.GetItemLinqQueryable <ToDoActivity>(
                            allowSynchronousQueryExecution: true).Select(x => x.cost).Sum();

                        ItemResponse <ToDoActivity> deleteResponse = container.DeleteItemAsync <ToDoActivity>(partitionKey: new Cosmos.PartitionKey(testItem.pk), id: testItem.id).ConfigureAwait(false).GetAwaiter().GetResult();
                        Assert.IsNotNull(deleteResponse);
                    }
                }, state: null);
            }
            finally
            {
                SynchronizationContext.SetSynchronizationContext(prevContext);
                using (CosmosClient client = TestCommon.CreateCosmosClient())
                {
                    client.GetDatabase(databaseId).DeleteAsync().GetAwaiter().GetResult();
                }
            }
        }
        public static Func <bool, IQueryable <Family> > GenerateFamilyCosmosData(
            Cosmos.Database cosmosDatabase, out Container container)
        {
            // The test collection should have range index on string properties
            // for the orderby tests
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/Pk" }), Kind = PartitionKind.Hash
            };
            var newCol = new ContainerProperties()
            {
                Id             = Guid.NewGuid().ToString(),
                PartitionKey   = partitionKeyDefinition,
                IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy()
                {
                    IncludedPaths = new Collection <Cosmos.IncludedPath>()
                    {
                        new Cosmos.IncludedPath()
                        {
                            Path    = "/*",
                            Indexes = new System.Collections.ObjectModel.Collection <Microsoft.Azure.Cosmos.Index>()
                            {
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1),
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1)
                            }
                        }
                    },
                    CompositeIndexes = new Collection <Collection <Cosmos.CompositePath> >()
                    {
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        }
                    }
                }
            };

            container = cosmosDatabase.CreateContainerAsync(newCol).Result;
            const int Records                   = 100;
            const int MaxNameLength             = 100;
            const int MaxThingStringLength      = 50;
            const int MaxChild                  = 5;
            const int MaxPets                   = MaxChild;
            const int MaxThings                 = MaxChild;
            const int MaxGrade                  = 101;
            const int MaxTransaction            = 20;
            const int MaxTransactionMinuteRange = 200;
            int       MaxTransactionType        = Enum.GetValues(typeof(TransactionType)).Length;

            Family createDataObj(Random random)
            {
                var obj = new Family
                {
                    FamilyId     = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(),
                    IsRegistered = random.NextDouble() < 0.5,
                    NullableInt  = random.NextDouble() < 0.5 ? (int?)random.Next() : null,
                    Int          = random.NextDouble() < 0.5 ? 5 : random.Next(),
                    Id           = Guid.NewGuid().ToString(),
                    Pk           = "Test",
                    Parents      = new Parent[random.Next(2) + 1]
                };

                for (int i = 0; i < obj.Parents.Length; ++i)
                {
                    obj.Parents[i] = new Parent()
                    {
                        FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength))
                    };
                }

                obj.Tags = new string[random.Next(MaxChild)];
                for (int i = 0; i < obj.Tags.Length; ++i)
                {
                    obj.Tags[i] = (i + random.Next(30, 36)).ToString();
                }

                obj.Children = new Child[random.Next(MaxChild)];
                for (int i = 0; i < obj.Children.Length; ++i)
                {
                    obj.Children[i] = new Child()
                    {
                        Gender     = random.NextDouble() < 0.5 ? "male" : "female",
                        FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName,
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        Grade      = random.Next(MaxGrade)
                    };

                    obj.Children[i].Pets = new List <Pet>();
                    for (int j = 0; j < random.Next(MaxPets); ++j)
                    {
                        obj.Children[i].Pets.Add(new Pet()
                        {
                            GivenName = random.NextDouble() < 0.5 ?
                                        LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) :
                                        "Fluffy"
                        });
                    }

                    obj.Children[i].Things = new Dictionary <string, string>();
                    for (int j = 0; j < random.Next(MaxThings) + 1; ++j)
                    {
                        obj.Children[i].Things.Add(
                            j == 0 ? "A" : $"{j}-{random.Next().ToString()}",
                            LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength)));
                    }
                }

                obj.Records = new Logs
                {
                    LogId        = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                    Transactions = new Transaction[random.Next(MaxTransaction)]
                };
                for (int i = 0; i < obj.Records.Transactions.Length; ++i)
                {
                    var transaction = new Transaction()
                    {
                        Amount = random.Next(),
                        Date   = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)),
                        Type   = (TransactionType)(random.Next(MaxTransactionType))
                    };
                    obj.Records.Transactions[i] = transaction;
                }

                return(obj);
            }

            Func <bool, IQueryable <Family> > getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container);

            return(getQuery);
        }
        public async Task InvalidSessionTokenAfterContainerRecreationAndCollectionCacheRefreshReproTest()
        {
            // ingestionClinet is dedicated client simulating the writes / container recreation in
            // the separate process - like Spark job
            using CosmosClient ingestionClient = TestCommon.CreateCosmosClient();
            Cosmos.Database ingestionDatabase = ingestionClient.GetDatabase(this.database.Id);

            ContainerProperties multiPartitionContainerSettings =
                new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk");
            Container ingestionContainer =
                await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings);

            const int itemCountToBeIngested = 10;
            string    pk        = Guid.NewGuid().ToString("N");
            long?     latestLsn = null;

            Console.WriteLine("INGEST DOCUMENTS");
            for (int i = 0; i < itemCountToBeIngested; i++)
            {
                ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity();
                testItem.pk = pk;

                ItemResponse <ToDoActivity> response =
                    await ingestionContainer.CreateItemAsync <ToDoActivity>(item : testItem);

                Assert.IsNotNull(response);
                Assert.IsNotNull(response.Resource);
                Assert.IsNotNull(response.Diagnostics);
                long?lsnAfterCreate = await GetLSNFromSessionContainer(
                    ingestionContainer, multiPartitionContainerSettings, new PartitionKey(pk));

                Assert.IsNotNull(lsnAfterCreate);
                Assert.IsTrue(latestLsn == null || lsnAfterCreate.Value > latestLsn.Value);
                latestLsn = lsnAfterCreate;
                CosmosTraceDiagnostics diagnostics = (CosmosTraceDiagnostics)response.Diagnostics;
                Assert.IsFalse(diagnostics.IsGoneExceptionHit());
                Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString()));
                Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero);
            }

            // Dedciated query client used only for queries simulating the customer's app
            string    lastRequestedSessionToken = null;
            Container queryContainer            = TransportClientHelper.GetContainerWithIntercepter(
                this.database.Id,
                ingestionContainer.Id,
                (uri, operation, request) =>
            {
                if (request.ResourceType == ResourceType.Document &&
                    request.OperationType == OperationType.Query)
                {
                    lastRequestedSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken];
                }
            },
                false,
                null);

            long?lsnAfterQueryOnOldContainer = null;

            // Issueing two queries - first won't use session tokens yet
            // second will provide session tokens captured from first request in the request to the backend
            for (int i = 0; i < 2; i++)
            {
                Console.WriteLine("RUN QUERY ON OLD CONTAINER ({0})", i);
                using FeedIterator <JObject> queryIteratorOldContainer = queryContainer.GetItemQueryIterator <JObject>(
                          new QueryDefinition("Select c.id FROM c"),
                          continuationToken: null,
                          new QueryRequestOptions
                {
                    ConsistencyLevel = Cosmos.ConsistencyLevel.Session,
                    PartitionKey     = new Cosmos.PartitionKey(pk)
                });
                int itemCountOldContainer = 0;
                while (queryIteratorOldContainer.HasMoreResults)
                {
                    FeedResponse <JObject> response = await queryIteratorOldContainer.ReadNextAsync();

                    if (i == 0)
                    {
                        string diagnosticString = response.Diagnostics.ToString();
                        Assert.IsTrue(diagnosticString.Contains("PKRangeCache Info("));
                        JObject diagnosticJobject = JObject.Parse(diagnosticString);
                        JToken  actualToken       = diagnosticJobject.SelectToken("$.children[0].children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data");
                        JToken  actualNode        = actualToken.Children().First().First();

                        Assert.IsTrue(actualNode["Previous Continuation Token"].ToString().Length == 0);
                        Assert.IsTrue(actualNode["Continuation Token"].ToString().Length > 0);
                    }

                    itemCountOldContainer += response.Count;
                }

                Assert.AreEqual(itemCountToBeIngested, itemCountOldContainer);
                lsnAfterQueryOnOldContainer = await GetLSNFromSessionContainer(
                    queryContainer, multiPartitionContainerSettings, new PartitionKey(pk));

                Assert.IsNotNull(lsnAfterQueryOnOldContainer);
                Assert.AreEqual(latestLsn.Value, lsnAfterQueryOnOldContainer.Value);
                if (i == 0)
                {
                    Assert.IsNull(lastRequestedSessionToken);
                }
                else
                {
                    Assert.IsNotNull(lastRequestedSessionToken);
                    Assert.AreEqual(latestLsn.Value, SessionTokenHelper.Parse(lastRequestedSessionToken).LSN);
                }
            }

            Console.WriteLine(
                "DELETE CONTAINER {0}",
                (await queryContainer.ReadContainerAsync()).Resource.ResourceId);
            await ingestionContainer.DeleteContainerAsync();

            Console.WriteLine("RECREATING CONTAINER...");
            ContainerResponse ingestionContainerResponse =
                await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings);

            ingestionContainer = ingestionContainerResponse.Container;

            string responseSessionTokenValue =
                ingestionContainerResponse.Headers[HttpConstants.HttpHeaders.SessionToken];
            long?lsnAfterRecreatingContainerFromIngestionClient = responseSessionTokenValue != null?
                                                                  SessionTokenHelper.Parse(responseSessionTokenValue).LSN : null;

            Console.WriteLine(
                "RECREATED CONTAINER with new CollectionRid: {0} - LSN: {1}",
                ingestionContainerResponse.Resource.ResourceId,
                lsnAfterRecreatingContainerFromIngestionClient);

            // validates that the query container still uses the LSN captured from the old LSN
            long?lsnAfterCreatingNewContainerFromQueryClient = await GetLSNFromSessionContainer(
                queryContainer, multiPartitionContainerSettings, new PartitionKey(pk));

            Assert.IsNotNull(lsnAfterCreatingNewContainerFromQueryClient);
            Assert.AreEqual(latestLsn.Value, lsnAfterCreatingNewContainerFromQueryClient.Value);

            Console.WriteLine("GET FEED RANGES");
            // this will force a CollectionCache refresh - because no pk ranegs can be identified
            // for the old container anymore
            _ = await queryContainer.GetFeedRangesAsync();


            Console.WriteLine("RUN QUERY ON NEW CONTAINER");
            int itemCountNewContainer = 0;

            using FeedIterator <JObject> queryIteratorNewContainer = queryContainer.GetItemQueryIterator <JObject>(
                      new QueryDefinition("Select c.id FROM c"),
                      continuationToken: null,
                      new QueryRequestOptions
            {
                ConsistencyLevel = Cosmos.ConsistencyLevel.Session,
                PartitionKey     = new Cosmos.PartitionKey(pk),
            });
            Console.WriteLine("Query iterator created");
            while (queryIteratorNewContainer.HasMoreResults)
            {
                Console.WriteLine("Retrieving first page");
                try
                {
                    FeedResponse <JObject> response = await queryIteratorNewContainer.ReadNextAsync();

                    Console.WriteLine("Request Diagnostics for query against new container: {0}",
                                      response.Diagnostics.ToString());
                    itemCountNewContainer += response.Count;
                }
                catch (CosmosException cosmosException)
                {
                    Console.WriteLine("COSMOS EXCEPTION: {0}", cosmosException);
                    throw;
                }
            }

            Assert.AreEqual(0, itemCountNewContainer);
            long?lsnAfterQueryOnNewContainer = await GetLSNFromSessionContainer(
                queryContainer, multiPartitionContainerSettings, new PartitionKey(pk));

            Assert.IsNotNull(lsnAfterQueryOnNewContainer);
            Assert.IsTrue(
                lastRequestedSessionToken == null ||
                SessionTokenHelper.Parse(lastRequestedSessionToken).LSN ==
                lsnAfterRecreatingContainerFromIngestionClient,
                $"The requested session token {lastRequestedSessionToken} on the last query request should be null " +
                $"or have LSN '{lsnAfterRecreatingContainerFromIngestionClient}' (which is the LSN after " +
                "re-creating the container) if the session cache or the new CollectionName to Rid mapping was " +
                "correctly populated in the SessionCache.");
        }
        private async Task ValidateCollectionIndexProgressHeaders(CosmosClient client)
        {
            Cosmos.Database db = await client.CreateDatabaseAsync(Guid.NewGuid().ToString());

            try
            {
                PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                    Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash
                };
                var lazyCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                lazyCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.Lazy;
                Container lazyContainer = await db.CreateContainerAsync(lazyCollection);

                var consistentCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                consistentCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.Consistent;
                Container consistentContainer = await db.CreateContainerAsync(consistentCollection);

                var noneIndexCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                noneIndexCollection.IndexingPolicy.Automatic    = false;
                noneIndexCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.None;
                Container noneIndexContainer = await db.CreateContainerAsync(noneIndexCollection);

                var doc = new Document()
                {
                    Id = Guid.NewGuid().ToString()
                };
                await lazyContainer.CreateItemAsync <Document>(doc);

                await consistentContainer.CreateItemAsync <Document>(doc);

                await noneIndexContainer.CreateItemAsync <Document>(doc);


                // Lazy-indexing collection.
                {
                    ContainerResponse collectionResponse = await lazyContainer.ReadContainerAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsTrue(int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionLazyIndexingProgress], CultureInfo.InvariantCulture) >= 0,
                                  "Expect lazy indexer progress when reading lazy collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading lazy collection.");
                }

                // Consistent-indexing collection.
                {
                    ContainerResponse collectionResponse = await consistentContainer.ReadContainerAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsFalse(collectionResponse.Headers.AllKeys().Contains(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress),
                                   "No lazy indexer progress when reading consistent collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading consistent collection.");
                }

                // None-indexing collection.
                {
                    ContainerResponse collectionResponse = await noneIndexContainer.ReadContainerAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsFalse(collectionResponse.Headers.AllKeys().Contains(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress),
                                   "No lazy indexer progress when reading none-index collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading none-index collection.");
                }
            }
            finally
            {
                await db.DeleteAsync();
            }
        }