From d57dec1c7dc19a245ddc74971781b53610bda4cc Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 9 Aug 2019 14:03:18 -0700 Subject: [PATCH] improve DefaultSerializationContextTest --- .../DefaultSerializationContextTest.cs | 151 ++++++++++++------ 1 file changed, 104 insertions(+), 47 deletions(-) diff --git a/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs b/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs index 4d09d80bb72..aa7631587be 100644 --- a/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs +++ b/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs @@ -17,9 +17,6 @@ #endregion using System; -using System.Buffers; -using System.Collections.Generic; -using System.Runtime.InteropServices; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; @@ -32,22 +29,28 @@ namespace Grpc.Core.Internal.Tests [TestCase] public void CompleteAllowedOnlyOnce() { - var context = new DefaultSerializationContext(); - var buffer = GetTestBuffer(10); + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var buffer = GetTestBuffer(10); - context.Complete(buffer); - Assert.Throws(typeof(InvalidOperationException), () => context.Complete(buffer)); - Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + context.Complete(buffer); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete(buffer)); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + } } [TestCase] public void CompleteAllowedOnlyOnce2() { - var context = new DefaultSerializationContext(); + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; - context.Complete(); - Assert.Throws(typeof(InvalidOperationException), () => context.Complete(GetTestBuffer(10))); - Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + context.Complete(); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete(GetTestBuffer(10))); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + } } [TestCase(0)] @@ -57,13 +60,16 @@ namespace Grpc.Core.Internal.Tests [TestCase(1000)] public void ByteArrayPayload(int payloadSize) { - var context = new DefaultSerializationContext(); - var origPayload = GetTestBuffer(payloadSize); + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); - context.Complete(origPayload); + context.Complete(origPayload); - var nativePayload = context.GetPayload().ToByteArray(); - CollectionAssert.AreEqual(origPayload, nativePayload); + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } } [TestCase(0)] @@ -73,16 +79,40 @@ namespace Grpc.Core.Internal.Tests [TestCase(1000)] public void BufferWriter_OneSegment(int payloadSize) { - var context = new DefaultSerializationContext(); - var origPayload = GetTestBuffer(payloadSize); + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); - var bufferWriter = context.GetBufferWriter(); - origPayload.AsSpan().CopyTo(bufferWriter.GetSpan(payloadSize)); - bufferWriter.Advance(payloadSize); - // TODO: test that call to Complete() is required. + var bufferWriter = context.GetBufferWriter(); + origPayload.AsSpan().CopyTo(bufferWriter.GetSpan(payloadSize)); + bufferWriter.Advance(payloadSize); + // TODO: test that call to Complete() is required. - var nativePayload = context.GetPayload().ToByteArray(); - CollectionAssert.AreEqual(origPayload, nativePayload); + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void BufferWriter_OneSegment_GetMemory(int payloadSize) + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + var bufferWriter = context.GetBufferWriter(); + origPayload.AsSpan().CopyTo(bufferWriter.GetMemory(payloadSize).Span); + bufferWriter.Advance(payloadSize); + + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } } [TestCase(1, 4)] // small slice size tests grpc_slice with inline data @@ -95,41 +125,68 @@ namespace Grpc.Core.Internal.Tests [TestCase(1000, 64)] public void BufferWriter_MultipleSegments(int payloadSize, int maxSliceSize) { - var context = new DefaultSerializationContext(); - var origPayload = GetTestBuffer(payloadSize); - - var bufferWriter = context.GetBufferWriter(); - for (int offset = 0; offset < payloadSize; offset += maxSliceSize) + using (var scope = NewDefaultSerializationContextScope()) { - var sliceSize = Math.Min(maxSliceSize, payloadSize - offset); - // we allocate last slice as too big intentionally to test that shrinking works - var dest = bufferWriter.GetSpan(maxSliceSize); + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + var bufferWriter = context.GetBufferWriter(); + for (int offset = 0; offset < payloadSize; offset += maxSliceSize) + { + var sliceSize = Math.Min(maxSliceSize, payloadSize - offset); + // we allocate last slice as too big intentionally to test that shrinking works + var dest = bufferWriter.GetSpan(maxSliceSize); + + origPayload.AsSpan(offset, sliceSize).CopyTo(dest); + bufferWriter.Advance(sliceSize); + } + context.Complete(); - origPayload.AsSpan(offset, sliceSize).CopyTo(dest); - bufferWriter.Advance(sliceSize); + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); } - context.Complete(); - - var nativePayload = context.GetPayload().ToByteArray(); - CollectionAssert.AreEqual(origPayload, nativePayload); - - context.GetPayload().Dispose(); // TODO: do it better.. (use the scope...) } - // AdjustTailSpace(0) if previous tail size is 0.... + [TestCase] + public void ContextIsReusable() + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + + var origPayload1 = GetTestBuffer(10); + context.Complete(origPayload1); + CollectionAssert.AreEqual(origPayload1, context.GetPayload().ToByteArray()); - // test that context.Complete() call is required... + context.Reset(); - // BufferWriter.GetMemory... (add refs to the original memory?) + var origPayload2 = GetTestBuffer(20); + + var bufferWriter = context.GetBufferWriter(); + origPayload2.AsSpan().CopyTo(bufferWriter.GetMemory(origPayload2.Length).Span); + bufferWriter.Advance(origPayload2.Length); + CollectionAssert.AreEqual(origPayload2, context.GetPayload().ToByteArray()); - // TODO: set payload and then get IBufferWriter should throw? + context.Reset(); + + // TODO: that's should be a null payload... + CollectionAssert.AreEqual(new byte[0], context.GetPayload().ToByteArray()); + } + } - // TODO: test Reset()... + //test ideas: - // TODO: destroy SliceBufferSafeHandles... (use usagescope...) + // test that context.Complete() call is required... + // set payload with Complete([]) and then get IBufferWriter should throw (because it's been completed already?) + // other ideas: + // AdjustTailSpace(0) if previous tail size is 0... (better for SliceBufferSafeHandle) + private DefaultSerializationContext.UsageScope NewDefaultSerializationContextScope() + { + return new DefaultSerializationContext.UsageScope(new DefaultSerializationContext()); + } private byte[] GetTestBuffer(int length) {