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 SliceBufferSafeHandleTest 28 { 29 [TestCase] Complete_EmptyBuffer()30 public void Complete_EmptyBuffer() 31 { 32 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 33 { 34 sliceBuffer.Complete(); 35 CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray()); 36 } 37 } 38 39 [TestCase] Complete_TailSizeZero()40 public void Complete_TailSizeZero() 41 { 42 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 43 { 44 var origPayload = GetTestBuffer(10); 45 origPayload.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload.Length)); 46 sliceBuffer.Advance(origPayload.Length); 47 // call complete where tail space size == 0 48 sliceBuffer.Complete(); 49 CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); 50 } 51 } 52 53 [TestCase] Complete_TruncateTailSpace()54 public void Complete_TruncateTailSpace() 55 { 56 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 57 { 58 var origPayload = GetTestBuffer(10); 59 var dest = sliceBuffer.GetSpan(origPayload.Length + 10); 60 origPayload.AsSpan().CopyTo(dest); 61 sliceBuffer.Advance(origPayload.Length); 62 // call complete where tail space needs to be truncated 63 sliceBuffer.Complete(); 64 CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); 65 } 66 } 67 68 [TestCase] SliceBufferIsReusable()69 public void SliceBufferIsReusable() 70 { 71 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 72 { 73 var origPayload = GetTestBuffer(10); 74 origPayload.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload.Length)); 75 sliceBuffer.Advance(origPayload.Length); 76 sliceBuffer.Complete(); 77 CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); 78 79 sliceBuffer.Reset(); 80 81 var origPayload2 = GetTestBuffer(20); 82 origPayload2.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload2.Length)); 83 sliceBuffer.Advance(origPayload2.Length); 84 sliceBuffer.Complete(); 85 CollectionAssert.AreEqual(origPayload2, sliceBuffer.ToByteArray()); 86 87 sliceBuffer.Reset(); 88 89 CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray()); 90 } 91 } 92 93 [TestCase] SliceBuffer_SizeHintZero()94 public void SliceBuffer_SizeHintZero() 95 { 96 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 97 { 98 var destSpan = sliceBuffer.GetSpan(0); 99 Assert.IsTrue(destSpan.Length > 0); // some non-zero size memory is made available 100 101 sliceBuffer.Reset(); 102 103 var destMemory = sliceBuffer.GetMemory(0); 104 Assert.IsTrue(destMemory.Length > 0); 105 } 106 } 107 108 [TestCase(0)] 109 [TestCase(1000)] SliceBuffer_BigPayload(int sizeHint)110 public void SliceBuffer_BigPayload(int sizeHint) 111 { 112 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 113 { 114 var bigPayload = GetTestBuffer(4 * 1024 * 1024); 115 116 int offset = 0; 117 while (offset < bigPayload.Length) 118 { 119 var destSpan = sliceBuffer.GetSpan(sizeHint); 120 int copySize = Math.Min(destSpan.Length, bigPayload.Length - offset); 121 bigPayload.AsSpan(offset, copySize).CopyTo(destSpan); 122 sliceBuffer.Advance(copySize); 123 offset += copySize; 124 } 125 126 sliceBuffer.Complete(); 127 CollectionAssert.AreEqual(bigPayload, sliceBuffer.ToByteArray()); 128 } 129 } 130 131 [TestCase] SliceBuffer_NegativeSizeHint()132 public void SliceBuffer_NegativeSizeHint() 133 { 134 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 135 { 136 Assert.Throws(typeof(ArgumentException), () => sliceBuffer.GetSpan(-1)); 137 Assert.Throws(typeof(ArgumentException), () => sliceBuffer.GetMemory(-1)); 138 } 139 } 140 141 [TestCase] SliceBuffer_AdvanceBadArg()142 public void SliceBuffer_AdvanceBadArg() 143 { 144 using (var sliceBuffer = SliceBufferSafeHandle.Create()) 145 { 146 int size = 10; 147 var destSpan = sliceBuffer.GetSpan(size); 148 Assert.Throws(typeof(ArgumentException), () => sliceBuffer.Advance(size + 1)); 149 Assert.Throws(typeof(ArgumentException), () => sliceBuffer.Advance(-1)); 150 } 151 } 152 GetTestBuffer(int length)153 private byte[] GetTestBuffer(int length) 154 { 155 var testBuffer = new byte[length]; 156 for (int i = 0; i < testBuffer.Length; i++) 157 { 158 testBuffer[i] = (byte) i; 159 } 160 return testBuffer; 161 } 162 } 163 } 164