public async Task AzureTableDataManager_InsertTwoTableEntriesConditionallyAsync()
        {
            StorageEmulatorUtilities.EnsureEmulatorIsNotUsed();

            var data1 = GenerateNewData();
            var data2 = GenerateNewData();

            try
            {
                await manager.InsertTwoTableEntriesConditionallyAsync(data1, data2, AzureStorageUtils.ANY_ETAG);
            }
            catch (StorageException exc)
            {
                Assert.Equal((int)HttpStatusCode.NotFound, exc.RequestInformation.HttpStatusCode);  // "Upadte item 2 before created it."
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureStorageUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.NotFound, httpStatusCode);
                Assert.Equal(StorageErrorCodeStrings.ResourceNotFound, restStatus);
            }

            string etag = await manager.CreateTableEntryAsync(data2.Clone());

            var tuple = await manager.InsertTwoTableEntriesConditionallyAsync(data1, data2, etag);

            try
            {
                await manager.InsertTwoTableEntriesConditionallyAsync(data1.Clone(), data2.Clone(), tuple.Item2);

                Assert.True(false, "Should have thrown StorageException.");
            }
            catch (StorageException exc)
            {
                Assert.Equal((int)HttpStatusCode.Conflict, exc.RequestInformation.HttpStatusCode);  // "Inserting an already existing item 1."
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureStorageUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.Conflict, httpStatusCode);
                Assert.Equal("EntityAlreadyExists", restStatus);
            }

            try
            {
                await manager.InsertTwoTableEntriesConditionallyAsync(data1.Clone(), data2.Clone(), AzureStorageUtils.ANY_ETAG);

                Assert.True(false, "Should have thrown StorageException.");
            }
            catch (StorageException exc)
            {
                Assert.Equal((int)HttpStatusCode.Conflict, exc.RequestInformation.HttpStatusCode);  // "Inserting an already existing item 1 AND wring eTag"
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureStorageUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.Conflict, httpStatusCode);
                Assert.Equal("EntityAlreadyExists", restStatus);
            };
        }
        public async Task AzureTableDataManager_MergeTableAsync()
        {
            StorageEmulatorUtilities.EnsureEmulatorIsNotUsed();
            var data = GenerateNewData();

            try
            {
                await manager.MergeTableEntryAsync(data, AzureTableUtils.ANY_ETAG);

                Assert.True(false, "Should have thrown RequestFailedException.");
            }
            catch (RequestFailedException exc)
            {
                Assert.Equal((int)HttpStatusCode.NotFound, exc.Status);  // "Merge before create."
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureTableUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.NotFound, httpStatusCode);
                Assert.Equal(TableErrorCode.ResourceNotFound.ToString(), restStatus);
            }

            string eTag1 = await manager.UpsertTableEntryAsync(data);

            var data2 = data.Clone();

            data2.StringData = "NewData";
            await manager.MergeTableEntryAsync(data2, eTag1);

            try
            {
                await manager.MergeTableEntryAsync(data, eTag1);

                Assert.True(false, "Should have thrown RequestFailedException.");
            }
            catch (RequestFailedException exc)
            {
                Assert.Equal((int)HttpStatusCode.PreconditionFailed, exc.Status);  // "Wrong eTag."
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureTableUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.PreconditionFailed, httpStatusCode);
                Assert.True(restStatus == TableErrorCode.UpdateConditionNotSatisfied.ToString());
            }

            var tuple = await manager.ReadSingleTableEntryAsync(data.PartitionKey, data.RowKey);

            Assert.Equal("NewData", tuple.Entity.StringData);
        }
        public async Task AzureTableDataManager_UpdateTwoTableEntriesConditionallyAsync()
        {
            StorageEmulatorUtilities.EnsureEmulatorIsNotUsed();

            var data1 = GenerateNewData();
            var data2 = GenerateNewData();

            try
            {
                await manager.UpdateTwoTableEntriesConditionallyAsync(data1, AzureTableUtils.ANY_ETAG, data2, AzureTableUtils.ANY_ETAG);

                Assert.True(false, "Update should have failed since the data has not been created yet");
            }
            catch (RequestFailedException exc)
            {
                Assert.Equal((int)HttpStatusCode.NotFound, exc.Status);  // "Update before insert."
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureTableUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.NotFound, httpStatusCode);
                Assert.Equal(TableErrorCode.ResourceNotFound.ToString(), restStatus);
            }

            string etag = await manager.CreateTableEntryAsync(data2.Clone());

            var tuple1 = await manager.InsertTwoTableEntriesConditionallyAsync(data1, data2, etag);

            _ = await manager.UpdateTwoTableEntriesConditionallyAsync(data1, tuple1.Item1, data2, tuple1.Item2);

            try
            {
                await manager.UpdateTwoTableEntriesConditionallyAsync(data1, tuple1.Item1, data2, tuple1.Item2);

                Assert.True(false, "Should have thrown RequestFailedException.");
            }
            catch (RequestFailedException exc)
            {
                Assert.Equal((int)HttpStatusCode.PreconditionFailed, exc.Status);  // "Wrong eTag"
                HttpStatusCode httpStatusCode;
                string         restStatus;
                AzureTableUtils.EvaluateException(exc, out httpStatusCode, out restStatus, true);
                Assert.Equal(HttpStatusCode.PreconditionFailed, httpStatusCode);
                Assert.True(restStatus == TableErrorCode.UpdateConditionNotSatisfied.ToString());
            }
        }
        protected override AzureTableGrainDirectory GetGrainDirectory()
        {
            TestUtils.CheckForAzureStorage();
            StorageEmulatorUtilities.EnsureEmulatorIsNotUsed();

            var clusterOptions = new ClusterOptions
            {
                ClusterId = Guid.NewGuid().ToString("N"),
                ServiceId = Guid.NewGuid().ToString("N"),
            };

            var directoryOptions = new AzureTableGrainDirectoryOptions();

            directoryOptions.ConfigureTestDefaults();

            var loggerFactory = TestingUtils.CreateDefaultLoggerFactory("AzureGrainDirectoryTests.log");

            var directory = new AzureTableGrainDirectory(directoryOptions, Options.Create(clusterOptions), loggerFactory);

            directory.InitializeIfNeeded().GetAwaiter().GetResult();

            return(directory);
        }