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