1 #region Copyright notice and license 2 3 // Copyright 2019 The gRPC Authors 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using Grpc.Core; 21 using Grpc.Core.Internal; 22 using Grpc.Core.Utils; 23 using NUnit.Framework; 24 25 namespace Grpc.Core.Internal.Tests 26 { 27 public class DefaultSerializationContextTest 28 { 29 [TestCase] CompleteAllowedOnlyOnce()30 public void CompleteAllowedOnlyOnce() 31 { 32 using (var scope = NewDefaultSerializationContextScope()) 33 { 34 var context = scope.Context; 35 var buffer = GetTestBuffer(10); 36 37 context.Complete(buffer); 38 Assert.Throws(typeof(InvalidOperationException), () => context.Complete(buffer)); 39 Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); 40 } 41 } 42 43 [TestCase] CompleteAllowedOnlyOnce2()44 public void CompleteAllowedOnlyOnce2() 45 { 46 using (var scope = NewDefaultSerializationContextScope()) 47 { 48 var context = scope.Context; 49 50 context.Complete(); 51 Assert.Throws(typeof(InvalidOperationException), () => context.Complete(GetTestBuffer(10))); 52 Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); 53 } 54 } 55 56 [TestCase(0)] 57 [TestCase(1)] 58 [TestCase(10)] 59 [TestCase(100)] 60 [TestCase(1000)] ByteArrayPayload(int payloadSize)61 public void ByteArrayPayload(int payloadSize) 62 { 63 using (var scope = NewDefaultSerializationContextScope()) 64 { 65 var context = scope.Context; 66 var origPayload = GetTestBuffer(payloadSize); 67 68 context.Complete(origPayload); 69 70 var nativePayload = context.GetPayload().ToByteArray(); 71 CollectionAssert.AreEqual(origPayload, nativePayload); 72 } 73 } 74 75 [TestCase(0)] 76 [TestCase(1)] 77 [TestCase(10)] 78 [TestCase(100)] 79 [TestCase(1000)] BufferWriter_OneSegment(int payloadSize)80 public void BufferWriter_OneSegment(int payloadSize) 81 { 82 using (var scope = NewDefaultSerializationContextScope()) 83 { 84 var context = scope.Context; 85 var origPayload = GetTestBuffer(payloadSize); 86 87 var bufferWriter = context.GetBufferWriter(); 88 origPayload.AsSpan().CopyTo(bufferWriter.GetSpan(payloadSize)); 89 bufferWriter.Advance(payloadSize); 90 context.Complete(); 91 92 var nativePayload = context.GetPayload().ToByteArray(); 93 CollectionAssert.AreEqual(origPayload, nativePayload); 94 } 95 } 96 97 [TestCase(0)] 98 [TestCase(1)] 99 [TestCase(10)] 100 [TestCase(100)] 101 [TestCase(1000)] BufferWriter_OneSegment_GetMemory(int payloadSize)102 public void BufferWriter_OneSegment_GetMemory(int payloadSize) 103 { 104 using (var scope = NewDefaultSerializationContextScope()) 105 { 106 var context = scope.Context; 107 var origPayload = GetTestBuffer(payloadSize); 108 109 var bufferWriter = context.GetBufferWriter(); 110 origPayload.AsSpan().CopyTo(bufferWriter.GetMemory(payloadSize).Span); 111 bufferWriter.Advance(payloadSize); 112 context.Complete(); 113 114 var nativePayload = context.GetPayload().ToByteArray(); 115 CollectionAssert.AreEqual(origPayload, nativePayload); 116 } 117 } 118 119 [TestCase(1, 4)] // small slice size tests grpc_slice with inline data 120 [TestCase(10, 4)] 121 [TestCase(100, 4)] 122 [TestCase(1000, 4)] 123 [TestCase(1, 64)] // larger slice size tests allocated grpc_slices 124 [TestCase(10, 64)] 125 [TestCase(1000, 50)] 126 [TestCase(1000, 64)] BufferWriter_MultipleSegments(int payloadSize, int maxSliceSize)127 public void BufferWriter_MultipleSegments(int payloadSize, int maxSliceSize) 128 { 129 using (var scope = NewDefaultSerializationContextScope()) 130 { 131 var context = scope.Context; 132 var origPayload = GetTestBuffer(payloadSize); 133 134 var bufferWriter = context.GetBufferWriter(); 135 for (int offset = 0; offset < payloadSize; offset += maxSliceSize) 136 { 137 var sliceSize = Math.Min(maxSliceSize, payloadSize - offset); 138 // we allocate last slice as too big intentionally to test that shrinking works 139 var dest = bufferWriter.GetSpan(maxSliceSize); 140 141 origPayload.AsSpan(offset, sliceSize).CopyTo(dest); 142 bufferWriter.Advance(sliceSize); 143 } 144 context.Complete(); 145 146 var nativePayload = context.GetPayload().ToByteArray(); 147 CollectionAssert.AreEqual(origPayload, nativePayload); 148 } 149 } 150 151 [TestCase] ContextIsReusable()152 public void ContextIsReusable() 153 { 154 using (var scope = NewDefaultSerializationContextScope()) 155 { 156 var context = scope.Context; 157 158 Assert.Throws(typeof(NullReferenceException), () => context.GetPayload()); 159 160 var origPayload1 = GetTestBuffer(10); 161 context.Complete(origPayload1); 162 CollectionAssert.AreEqual(origPayload1, context.GetPayload().ToByteArray()); 163 164 context.Reset(); 165 166 var origPayload2 = GetTestBuffer(20); 167 168 var bufferWriter = context.GetBufferWriter(); 169 origPayload2.AsSpan().CopyTo(bufferWriter.GetMemory(origPayload2.Length).Span); 170 bufferWriter.Advance(origPayload2.Length); 171 context.Complete(); 172 CollectionAssert.AreEqual(origPayload2, context.GetPayload().ToByteArray()); 173 174 context.Reset(); 175 176 Assert.Throws(typeof(NullReferenceException), () => context.GetPayload()); 177 } 178 } 179 180 [TestCase] GetBufferWriterThrowsForCompletedContext()181 public void GetBufferWriterThrowsForCompletedContext() 182 { 183 using (var scope = NewDefaultSerializationContextScope()) 184 { 185 var context = scope.Context; 186 context.Complete(GetTestBuffer(10)); 187 188 Assert.Throws(typeof(InvalidOperationException), () => context.GetBufferWriter()); 189 } 190 } 191 NewDefaultSerializationContextScope()192 private DefaultSerializationContext.UsageScope NewDefaultSerializationContextScope() 193 { 194 return new DefaultSerializationContext.UsageScope(new DefaultSerializationContext()); 195 } 196 GetTestBuffer(int length)197 private byte[] GetTestBuffer(int length) 198 { 199 var testBuffer = new byte[length]; 200 for (int i = 0; i < testBuffer.Length; i++) 201 { 202 testBuffer[i] = (byte) i; 203 } 204 return testBuffer; 205 } 206 } 207 } 208