diff --git a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs index 3c0de67ad5..2f1ec55297 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs @@ -183,8 +183,14 @@ private static Result ReadOperationResult(ref RowReader reader, out Transactiona return r; } - batchOperationResult.ResourceStream = new MemoryStream( - buffer: resourceBody, index: 0, count: resourceBody.Length, writable: false, publiclyVisible: true); + batchOperationResult.ResourceStream = new CloneableStream( + internalStream: new MemoryStream( + buffer: resourceBody, + index: 0, + count: resourceBody.Length, + writable: false, + publiclyVisible: true), + allowUnsafeDataAccess: true); break; case "requestCharge": diff --git a/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftReader.cs b/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftReader.cs index 1c2d149f79..78cd657735 100644 --- a/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftReader.cs +++ b/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftReader.cs @@ -182,7 +182,19 @@ public override bool Read() /// A [] or null if the next JSON token is null. This method will return null at the end of an array. public override byte[] ReadAsBytes() { - throw new NotImplementedException(); + this.Read(); + if (this.jsonReader.CurrentTokenType == JsonTokenType.Null) + { + return null; + } + + if (this.jsonReader.CurrentTokenType == JsonTokenType.EndArray) + { + return new byte[0]; + } + + string stringValue = this.jsonReader.GetStringValue(); + return Convert.FromBase64String(stringValue); } /// diff --git a/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftWriter.cs b/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftWriter.cs index 589040e6f4..f3b4c04681 100644 --- a/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/Interop/CosmosDBToNewtonsoftWriter.cs @@ -331,7 +331,7 @@ public override void WriteValue(DateTime value) /// The [] value to write. public override void WriteValue(byte[] value) { - throw new NotSupportedException("Can not write byte arrays"); + this.WriteValue(Convert.ToBase64String(value)); } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIntegrationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIntegrationTests.cs index e51b6a3fff..5d825d0948 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIntegrationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIntegrationTests.cs @@ -145,5 +145,93 @@ public async Task ReadMany2UnreachablePartitionsTest() fiClient.Dispose(); } } + + [TestMethod] + [Owner("dkunda")] + [TestCategory("MultiRegion")] + [DataRow(true, DisplayName = "Test scenario when binary encoding is enabled at client level.")] + [DataRow(false, DisplayName = "Test scenario when binary encoding is disabled at client level.")] + public async Task ExecuteTransactionalBatch_WhenBinaryEncodingEnabled_ShouldCompleteSuccessfully( + bool isBinaryEncodingEnabled) + { + Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, isBinaryEncodingEnabled.ToString()); + + Random random = new(); + CosmosIntegrationTestObject testItem = new() + { + Id = $"smTestId{random.Next()}", + Pk = $"smpk{random.Next()}", + }; + + try + { + CosmosClientOptions cosmosClientOptions = new() + { + ConsistencyLevel = ConsistencyLevel.Session, + RequestTimeout = TimeSpan.FromSeconds(10), + Serializer = new CosmosJsonDotNetSerializer( + cosmosSerializerOptions: new CosmosSerializationOptions() + { + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase + }, + binaryEncodingEnabled: isBinaryEncodingEnabled) + }; + + using CosmosClient cosmosClient = new( + connectionString: this.connectionString, + clientOptions: cosmosClientOptions); + + Database database = cosmosClient.GetDatabase(MultiRegionSetupHelpers.dbName); + Container container = database.GetContainer(MultiRegionSetupHelpers.containerName); + + // Create a transactional batch + TransactionalBatch transactionalBatch = container.CreateTransactionalBatch(new PartitionKey(testItem.Pk)); + + transactionalBatch.CreateItem( + testItem, + new TransactionalBatchItemRequestOptions + { + EnableContentResponseOnWrite = true, + }); + + transactionalBatch.ReadItem( + testItem.Id, + new TransactionalBatchItemRequestOptions + { + EnableContentResponseOnWrite = true, + }); + + // Execute the transactional batch + TransactionalBatchResponse transactionResponse = await transactionalBatch.ExecuteAsync( + new TransactionalBatchRequestOptions + { + }); + + Assert.AreEqual(HttpStatusCode.OK, transactionResponse.StatusCode); + Assert.AreEqual(2, transactionResponse.Count); + + TransactionalBatchOperationResult createOperationResult = transactionResponse.GetOperationResultAtIndex(0); + + Assert.IsNotNull(createOperationResult); + Assert.IsNotNull(createOperationResult.Resource); + Assert.AreEqual(testItem.Id, createOperationResult.Resource.Id); + Assert.AreEqual(testItem.Pk, createOperationResult.Resource.Pk); + + TransactionalBatchOperationResult readOperationResult = transactionResponse.GetOperationResultAtIndex(1); + + Assert.IsNotNull(readOperationResult); + Assert.IsNotNull(readOperationResult.Resource); + Assert.AreEqual(testItem.Id, readOperationResult.Resource.Id); + Assert.AreEqual(testItem.Pk, readOperationResult.Resource.Pk); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, null); + + await this.container.DeleteItemAsync( + testItem.Id, + new PartitionKey(testItem.Pk)); + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchSchemaTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchSchemaTests.cs index fd79de4762..f419974da9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchSchemaTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchSchemaTests.cs @@ -129,7 +129,9 @@ public async Task BatchResponseDeserializationAsync() new TransactionalBatchOperationResult(HttpStatusCode.Conflict), new TransactionalBatchOperationResult(HttpStatusCode.OK) { - ResourceStream = new MemoryStream(new byte[] { 0x41, 0x42 }, index: 0, count: 2, writable: false, publiclyVisible: true), + ResourceStream = new CloneableStream( + internalStream: new MemoryStream(new byte[] { 0x41, 0x42 }, index: 0, count: 2, writable: false, publiclyVisible: true), + allowUnsafeDataAccess: true), RequestCharge = 2.5, ETag = "1234", RetryAfter = TimeSpan.FromMilliseconds(360) @@ -250,7 +252,7 @@ private bool Equals(Stream x, Stream y) return false; } - return ((MemoryStream)x).GetBuffer().SequenceEqual(((MemoryStream)y).GetBuffer()); + return ((CloneableStream)x).GetBuffer().SequenceEqual(((CloneableStream)y).GetBuffer()); } return false; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchUnitTests.cs index 632c80ab77..baaf3771b3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchUnitTests.cs @@ -116,174 +116,187 @@ await BatchUnitTests.VerifyExceptionThrownOnExecuteAsync( [TestMethod] [Owner("abpai")] - public async Task BatchCrudRequestAsync() + [DataRow(true, DisplayName = "Test scenario when binary encoding is disabled at client level.")] + [DataRow(false, DisplayName = "Test scenario when binary disabled is disabled at client level.")] + public async Task BatchCrudRequestAsync( + bool isBinaryEncodingEnabled) { - Random random = new Random(); - - TestItem createItem = new TestItem("create"); - byte[] createStreamContent = new byte[20]; - random.NextBytes(createStreamContent); - byte[] createStreamBinaryId = new byte[20]; - random.NextBytes(createStreamBinaryId); - int createTtl = 45; - TransactionalBatchItemRequestOptions createRequestOptions = new TransactionalBatchItemRequestOptions() + Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, isBinaryEncodingEnabled.ToString()); + try { - Properties = new Dictionary() + Random random = new Random(); + + TestItem createItem = new TestItem("create"); + byte[] createStreamContent = new byte[20]; + random.NextBytes(createStreamContent); + byte[] createStreamBinaryId = new byte[20]; + random.NextBytes(createStreamBinaryId); + int createTtl = 45; + TransactionalBatchItemRequestOptions createRequestOptions = new TransactionalBatchItemRequestOptions() + { + Properties = new Dictionary() { { WFConstants.BackendHeaders.BinaryId, createStreamBinaryId }, { WFConstants.BackendHeaders.TimeToLiveInSeconds, createTtl.ToString() }, }, - IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude - }; + IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude + }; - string readId = Guid.NewGuid().ToString(); - byte[] readStreamBinaryId = new byte[20]; - random.NextBytes(readStreamBinaryId); - TransactionalBatchItemRequestOptions readRequestOptions = new TransactionalBatchItemRequestOptions() - { - Properties = new Dictionary() + string readId = Guid.NewGuid().ToString(); + byte[] readStreamBinaryId = new byte[20]; + random.NextBytes(readStreamBinaryId); + TransactionalBatchItemRequestOptions readRequestOptions = new TransactionalBatchItemRequestOptions() + { + Properties = new Dictionary() { { WFConstants.BackendHeaders.BinaryId, readStreamBinaryId } }, - IfNoneMatchEtag = "readCondition" - }; + IfNoneMatchEtag = "readCondition" + }; - TestItem replaceItem = new TestItem("repl"); - byte[] replaceStreamContent = new byte[20]; - random.NextBytes(replaceStreamContent); - const string replaceStreamId = "replStream"; - byte[] replaceStreamBinaryId = new byte[20]; - random.NextBytes(replaceStreamBinaryId); - TransactionalBatchItemRequestOptions replaceRequestOptions = new TransactionalBatchItemRequestOptions() - { - Properties = new Dictionary() + TestItem replaceItem = new TestItem("repl"); + byte[] replaceStreamContent = new byte[20]; + random.NextBytes(replaceStreamContent); + const string replaceStreamId = "replStream"; + byte[] replaceStreamBinaryId = new byte[20]; + random.NextBytes(replaceStreamBinaryId); + TransactionalBatchItemRequestOptions replaceRequestOptions = new TransactionalBatchItemRequestOptions() + { + Properties = new Dictionary() { { WFConstants.BackendHeaders.BinaryId, replaceStreamBinaryId } }, - IfMatchEtag = "replCondition", - IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude - }; + IfMatchEtag = "replCondition", + IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude + }; - TestItem upsertItem = new TestItem("upsert"); - byte[] upsertStreamContent = new byte[20]; - random.NextBytes(upsertStreamContent); - byte[] upsertStreamBinaryId = new byte[20]; - random.NextBytes(upsertStreamBinaryId); - TransactionalBatchItemRequestOptions upsertRequestOptions = new TransactionalBatchItemRequestOptions() - { - Properties = new Dictionary() + TestItem upsertItem = new TestItem("upsert"); + byte[] upsertStreamContent = new byte[20]; + random.NextBytes(upsertStreamContent); + byte[] upsertStreamBinaryId = new byte[20]; + random.NextBytes(upsertStreamBinaryId); + TransactionalBatchItemRequestOptions upsertRequestOptions = new TransactionalBatchItemRequestOptions() + { + Properties = new Dictionary() { { WFConstants.BackendHeaders.BinaryId, upsertStreamBinaryId } }, - IfMatchEtag = "upsertCondition", - IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude - }; + IfMatchEtag = "upsertCondition", + IndexingDirective = Microsoft.Azure.Cosmos.IndexingDirective.Exclude + }; - string deleteId = Guid.NewGuid().ToString(); - byte[] deleteStreamBinaryId = new byte[20]; - random.NextBytes(deleteStreamBinaryId); - TransactionalBatchItemRequestOptions deleteRequestOptions = new TransactionalBatchItemRequestOptions() - { - Properties = new Dictionary() + string deleteId = Guid.NewGuid().ToString(); + byte[] deleteStreamBinaryId = new byte[20]; + random.NextBytes(deleteStreamBinaryId); + TransactionalBatchItemRequestOptions deleteRequestOptions = new TransactionalBatchItemRequestOptions() + { + Properties = new Dictionary() { { WFConstants.BackendHeaders.BinaryId, deleteStreamBinaryId } }, - IfNoneMatchEtag = "delCondition" - }; - - CosmosJsonDotNetSerializer jsonSerializer = new CosmosJsonDotNetSerializer(); - BatchTestHandler testHandler = new BatchTestHandler((request, operations) => - { - Assert.AreEqual(new Cosmos.PartitionKey(BatchUnitTests.PartitionKey1).ToString(), request.Headers.PartitionKey); - Assert.AreEqual(bool.TrueString, request.Headers[HttpConstants.HttpHeaders.IsBatchAtomic]); - Assert.AreEqual(bool.TrueString, request.Headers[HttpConstants.HttpHeaders.IsBatchOrdered]); - Assert.IsFalse(request.Headers.TryGetValue(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, out string unused)); + IfNoneMatchEtag = "delCondition" + }; - Assert.AreEqual(16, operations.Count); + CosmosJsonDotNetSerializer jsonSerializer = new CosmosJsonDotNetSerializer(isBinaryEncodingEnabled); + BatchTestHandler testHandler = new BatchTestHandler((request, operations) => + { + Assert.AreEqual(new Cosmos.PartitionKey(BatchUnitTests.PartitionKey1).ToString(), request.Headers.PartitionKey); + Assert.AreEqual(bool.TrueString, request.Headers[HttpConstants.HttpHeaders.IsBatchAtomic]); + Assert.AreEqual(bool.TrueString, request.Headers[HttpConstants.HttpHeaders.IsBatchOrdered]); + Assert.IsFalse(request.Headers.TryGetValue(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, out string unused)); - int operationIndex = 0; + Assert.AreEqual(16, operations.Count); - // run the loop twice, once for operations without item request options, and one for with item request options - for (int loopCount = 0; loopCount < 2; loopCount++) - { - bool hasItemRequestOptions = loopCount == 1; - - ItemBatchOperation operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Create, operation.OperationType); - Assert.IsNull(operation.Id); - Assert.AreEqual(createItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? createRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Read, operation.OperationType); - Assert.AreEqual(readId, operation.Id); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? readRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Replace, operation.OperationType); - Assert.AreEqual(replaceItem.Id, operation.Id); - Assert.AreEqual(replaceItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? replaceRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Upsert, operation.OperationType); - Assert.IsNull(operation.Id); - Assert.AreEqual(upsertItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? upsertRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Delete, operation.OperationType); - Assert.AreEqual(deleteId, operation.Id); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? deleteRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Create, operation.OperationType); - Assert.IsNull(operation.Id); - Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(createStreamContent)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? createRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Replace, operation.OperationType); - Assert.AreEqual(replaceStreamId, operation.Id); - Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(replaceStreamContent)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? replaceRequestOptions : null, operation.RequestOptions); - - operation = operations[operationIndex++]; - Assert.AreEqual(OperationType.Upsert, operation.OperationType); - Assert.IsNull(operation.Id); - Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(upsertStreamContent)); - BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? upsertRequestOptions : null, operation.RequestOptions); - } + int operationIndex = 0; - return Task.FromResult(new ResponseMessage(HttpStatusCode.OK)); - }); + // run the loop twice, once for operations without item request options, and one for with item request options + for (int loopCount = 0; loopCount < 2; loopCount++) + { + bool hasItemRequestOptions = loopCount == 1; + + ItemBatchOperation operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Create, operation.OperationType); + Assert.IsNull(operation.Id); + Assert.AreEqual(createItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? createRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Read, operation.OperationType); + Assert.AreEqual(readId, operation.Id); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? readRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Replace, operation.OperationType); + Assert.AreEqual(replaceItem.Id, operation.Id); + Assert.AreEqual(replaceItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? replaceRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Upsert, operation.OperationType); + Assert.IsNull(operation.Id); + Assert.AreEqual(upsertItem, BatchUnitTests.Deserialize(operation.ResourceBody, jsonSerializer)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? upsertRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Delete, operation.OperationType); + Assert.AreEqual(deleteId, operation.Id); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? deleteRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Create, operation.OperationType); + Assert.IsNull(operation.Id); + Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(createStreamContent)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? createRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Replace, operation.OperationType); + Assert.AreEqual(replaceStreamId, operation.Id); + Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(replaceStreamContent)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? replaceRequestOptions : null, operation.RequestOptions); + + operation = operations[operationIndex++]; + Assert.AreEqual(OperationType.Upsert, operation.OperationType); + Assert.IsNull(operation.Id); + Assert.IsTrue(operation.ResourceBody.Span.SequenceEqual(upsertStreamContent)); + BatchUnitTests.VerifyBatchItemRequestOptionsAreEqual(hasItemRequestOptions ? upsertRequestOptions : null, operation.RequestOptions); + } - Container container = BatchUnitTests.GetContainer(testHandler); + return Task.FromResult(new ResponseMessage(HttpStatusCode.OK)); + }); - TransactionalBatchResponse batchResponse = await new BatchCore((ContainerInternal)container, new Cosmos.PartitionKey(BatchUnitTests.PartitionKey1)) - .CreateItem(createItem) - .ReadItem(readId) - .ReplaceItem(replaceItem.Id, replaceItem) - .UpsertItem(upsertItem) - .DeleteItem(deleteId) - - // stream - .CreateItemStream(new MemoryStream(createStreamContent)) - .ReplaceItemStream(replaceStreamId, new MemoryStream(replaceStreamContent)) - .UpsertItemStream(new MemoryStream(upsertStreamContent)) - - // regular with options - .CreateItem(createItem, createRequestOptions) - .ReadItem(readId, readRequestOptions) - .ReplaceItem(replaceItem.Id, replaceItem, replaceRequestOptions) - .UpsertItem(upsertItem, upsertRequestOptions) - .DeleteItem(deleteId, deleteRequestOptions) - - // stream with options - .CreateItemStream(new MemoryStream(createStreamContent), createRequestOptions) - .ReplaceItemStream(replaceStreamId, new MemoryStream(replaceStreamContent), replaceRequestOptions) - .UpsertItemStream(new MemoryStream(upsertStreamContent), upsertRequestOptions) - .ExecuteAsync(); + Container container = BatchUnitTests.GetContainer(testHandler); + + TransactionalBatchResponse batchResponse = await new BatchCore((ContainerInternal)container, new Cosmos.PartitionKey(BatchUnitTests.PartitionKey1)) + .CreateItem(createItem) + .ReadItem(readId) + .ReplaceItem(replaceItem.Id, replaceItem) + .UpsertItem(upsertItem) + .DeleteItem(deleteId) + + // stream + .CreateItemStream(new MemoryStream(createStreamContent)) + .ReplaceItemStream(replaceStreamId, new MemoryStream(replaceStreamContent)) + .UpsertItemStream(new MemoryStream(upsertStreamContent)) + + // regular with options + .CreateItem(createItem, createRequestOptions) + .ReadItem(readId, readRequestOptions) + .ReplaceItem(replaceItem.Id, replaceItem, replaceRequestOptions) + .UpsertItem(upsertItem, upsertRequestOptions) + .DeleteItem(deleteId, deleteRequestOptions) + + // stream with options + .CreateItemStream(new MemoryStream(createStreamContent), createRequestOptions) + .ReplaceItemStream(replaceStreamId, new MemoryStream(replaceStreamContent), replaceRequestOptions) + .UpsertItemStream(new MemoryStream(upsertStreamContent), upsertRequestOptions) + .ExecuteAsync(); + + TransactionalBatchOperationResult productResponse = batchResponse.GetOperationResultAtIndex(0); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, null); + } } [TestMethod] @@ -521,7 +534,9 @@ private static Container GetContainer(TestHandler testHandler = null) private static TestItem Deserialize(Memory body, CosmosSerializer serializer) { - return serializer.FromStream(new MemoryStream(body.Span.ToArray())); + return serializer.FromStream( + stream: new CloneableStream(new MemoryStream(body.Span.ToArray()), + allowUnsafeDataAccess: true)); } private class BatchTestHandler : TestHandler diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/NewtonsoftInteropTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/NewtonsoftInteropTests.cs index c7c58f3b7f..177da4f929 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/NewtonsoftInteropTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/NewtonsoftInteropTests.cs @@ -154,6 +154,17 @@ public void ObjectArrayTest() NewtonsoftInteropTests.VerifyNewtonsoftInterop(value); } + [TestMethod] + [Owner("dkunda")] + [DataRow(null, DisplayName = "Case when the byte array is null.")] + [DataRow(new byte[] { }, DisplayName = "Case when the byte array is empty.")] + [DataRow(new byte[] { 1, 2, 3, 4, 5 }, DisplayName = "Case when the byte array has valid elements.")] + public void ByteArrayTest( + byte[] byteArray) + { + NewtonsoftInteropTests.VerifyNewtonsoftInterop(byteArray); + } + [TestMethod] [Owner("brchon")] public void NestedArrayTest()