Skip to content

Commit c523742

Browse files
committed
Added unit tests for slices and MemoryManager<T>
1 parent ba514b0 commit c523742

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

UnitTests/UnitTests.HighPerformance.Shared/Extensions/Test_MemoryExtensions.cs

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Buffers;
67
using System.IO;
78
using System.Runtime.CompilerServices;
89
using System.Runtime.InteropServices;
@@ -142,6 +143,260 @@ public void Test_MemoryExtensions_FromArray_CastFromByteAndBack()
142143
Assert.IsTrue(span1 == span2);
143144
}
144145

146+
[TestCategory("MemoryExtensions")]
147+
[TestMethod]
148+
public void Test_MemoryExtensions_Cast_TooShort_WithSlice()
149+
{
150+
Memory<byte> m1 = new byte[8].AsMemory().Slice(4, 3);
151+
Memory<int> mc1 = m1.Cast<byte, int>();
152+
153+
Assert.IsTrue(mc1.IsEmpty);
154+
155+
Memory<byte> m2 = new byte[20].AsMemory().Slice(4, 13);
156+
Memory<float> mc2 = m2.Cast<byte, float>();
157+
158+
Assert.AreEqual(mc2.Length, 3);
159+
160+
Memory<byte> m3 = new byte[16].AsMemory().Slice(5);
161+
Memory<float> mc3 = m3.Cast<byte, float>();
162+
163+
Assert.AreEqual(mc3.Length, 2);
164+
}
165+
166+
[TestCategory("MemoryExtensions")]
167+
[TestMethod]
168+
public void Test_MemoryExtensions_FromArray_CastFromByte_WithSlice()
169+
{
170+
Memory<byte> memoryOfBytes = new byte[512].AsMemory().Slice(128, 128);
171+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
172+
173+
Assert.AreEqual(memoryOfFloats.Length, 128 / sizeof(float));
174+
175+
Span<byte> spanOfBytes = memoryOfBytes.Span;
176+
Span<float> spanOfFloats = memoryOfFloats.Span;
177+
178+
Assert.AreEqual(memoryOfFloats.Length, spanOfFloats.Length);
179+
Assert.IsTrue(Unsafe.AreSame(
180+
ref spanOfBytes[0],
181+
ref Unsafe.As<float, byte>(ref spanOfFloats[0])));
182+
}
183+
184+
[TestCategory("MemoryExtensions")]
185+
[TestMethod]
186+
public void Test_MemoryExtensions_FromArray_CastToByte_WithSlice()
187+
{
188+
Memory<float> memoryOfFloats = new float[512].AsMemory().Slice(128, 128);
189+
Memory<byte> memoryOfBytes = memoryOfFloats.Cast<float, byte>();
190+
191+
Assert.AreEqual(memoryOfBytes.Length, 128 * sizeof(float));
192+
193+
Span<float> spanOfFloats = memoryOfFloats.Span;
194+
Span<byte> spanOfBytes = memoryOfBytes.Span;
195+
196+
Assert.AreEqual(memoryOfBytes.Length, spanOfBytes.Length);
197+
Assert.IsTrue(Unsafe.AreSame(
198+
ref spanOfFloats[0],
199+
ref Unsafe.As<byte, float>(ref spanOfBytes[0])));
200+
}
201+
202+
[TestCategory("MemoryExtensions")]
203+
[TestMethod]
204+
public void Test_MemoryExtensions_FromArray_CastToShort_WithSlice()
205+
{
206+
Memory<float> memoryOfFloats = new float[512].AsMemory().Slice(128, 128);
207+
Memory<short> memoryOfShorts = memoryOfFloats.Cast<float, short>();
208+
209+
Assert.AreEqual(memoryOfShorts.Length, 128 * sizeof(float) / sizeof(short));
210+
211+
Span<float> spanOfFloats = memoryOfFloats.Span;
212+
Span<short> spanOfShorts = memoryOfShorts.Span;
213+
214+
Assert.AreEqual(memoryOfShorts.Length, spanOfShorts.Length);
215+
Assert.IsTrue(Unsafe.AreSame(
216+
ref spanOfFloats[0],
217+
ref Unsafe.As<short, float>(ref spanOfShorts[0])));
218+
}
219+
220+
[TestCategory("MemoryExtensions")]
221+
[TestMethod]
222+
public void Test_MemoryExtensions_FromArray_CastFromByteAndBack_WithSlice()
223+
{
224+
var data = new byte[512];
225+
Memory<byte> memoryOfBytes = data.AsMemory().Slice(128, 128);
226+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
227+
Memory<byte> memoryBack = memoryOfFloats.Cast<float, byte>();
228+
229+
Assert.AreEqual(memoryOfBytes.Length, memoryBack.Length);
230+
231+
Assert.IsTrue(MemoryMarshal.TryGetArray<byte>(memoryBack, out var segment));
232+
Assert.AreSame(segment.Array!, data);
233+
Assert.AreEqual(segment.Offset, 128);
234+
Assert.AreEqual(segment.Count, 128);
235+
236+
Assert.IsTrue(memoryOfBytes.Equals(memoryBack));
237+
238+
Span<byte> span1 = memoryOfBytes.Span;
239+
Span<byte> span2 = memoryBack.Span;
240+
241+
Assert.IsTrue(span1 == span2);
242+
}
243+
244+
[TestCategory("MemoryExtensions")]
245+
[TestMethod]
246+
public void Test_MemoryExtensions_FromMemoryManager_CastFromByte()
247+
{
248+
Memory<byte> memoryOfBytes = new ArrayMemoryManager<byte>(128);
249+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
250+
251+
Assert.AreEqual(memoryOfFloats.Length, 128 / sizeof(float));
252+
253+
Span<byte> spanOfBytes = memoryOfBytes.Span;
254+
Span<float> spanOfFloats = memoryOfFloats.Span;
255+
256+
Assert.AreEqual(memoryOfFloats.Length, spanOfFloats.Length);
257+
Assert.IsTrue(Unsafe.AreSame(
258+
ref spanOfBytes[0],
259+
ref Unsafe.As<float, byte>(ref spanOfFloats[0])));
260+
}
261+
262+
[TestCategory("MemoryExtensions")]
263+
[TestMethod]
264+
public void Test_MemoryExtensions_FromMemoryManager_CastToByte()
265+
{
266+
Memory<float> memoryOfFloats = new ArrayMemoryManager<float>(128);
267+
Memory<byte> memoryOfBytes = memoryOfFloats.Cast<float, byte>();
268+
269+
Assert.AreEqual(memoryOfBytes.Length, 128 * sizeof(float));
270+
271+
Span<float> spanOfFloats = memoryOfFloats.Span;
272+
Span<byte> spanOfBytes = memoryOfBytes.Span;
273+
274+
Assert.AreEqual(memoryOfBytes.Length, spanOfBytes.Length);
275+
Assert.IsTrue(Unsafe.AreSame(
276+
ref spanOfFloats[0],
277+
ref Unsafe.As<byte, float>(ref spanOfBytes[0])));
278+
}
279+
280+
[TestCategory("MemoryExtensions")]
281+
[TestMethod]
282+
public void Test_MemoryExtensions_FromMemoryManager_CastToShort()
283+
{
284+
Memory<float> memoryOfFloats = new ArrayMemoryManager<float>(128);
285+
Memory<short> memoryOfShorts = memoryOfFloats.Cast<float, short>();
286+
287+
Assert.AreEqual(memoryOfShorts.Length, 128 * sizeof(float) / sizeof(short));
288+
289+
Span<float> spanOfFloats = memoryOfFloats.Span;
290+
Span<short> spanOfShorts = memoryOfShorts.Span;
291+
292+
Assert.AreEqual(memoryOfShorts.Length, spanOfShorts.Length);
293+
Assert.IsTrue(Unsafe.AreSame(
294+
ref spanOfFloats[0],
295+
ref Unsafe.As<short, float>(ref spanOfShorts[0])));
296+
}
297+
298+
[TestCategory("MemoryExtensions")]
299+
[TestMethod]
300+
public void Test_MemoryExtensions_FromMemoryManager_CastFromByteAndBack()
301+
{
302+
var data = new ArrayMemoryManager<byte>(128);
303+
Memory<byte> memoryOfBytes = data;
304+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
305+
Memory<byte> memoryBack = memoryOfFloats.Cast<float, byte>();
306+
307+
Assert.AreEqual(memoryOfBytes.Length, memoryBack.Length);
308+
309+
Assert.IsTrue(MemoryMarshal.TryGetMemoryManager<byte, ArrayMemoryManager<byte>>(memoryBack, out var manager, out var start, out var length));
310+
Assert.AreSame(manager!, data);
311+
Assert.AreEqual(start, 0);
312+
Assert.AreEqual(length, 128);
313+
314+
Assert.IsTrue(memoryOfBytes.Equals(memoryBack));
315+
316+
Span<byte> span1 = memoryOfBytes.Span;
317+
Span<byte> span2 = memoryBack.Span;
318+
319+
Assert.IsTrue(span1 == span2);
320+
}
321+
322+
[TestCategory("MemoryExtensions")]
323+
[TestMethod]
324+
public void Test_MemoryExtensions_FromMemoryManager_CastFromByte_WithSlice()
325+
{
326+
Memory<byte> memoryOfBytes = new ArrayMemoryManager<byte>(512).Memory.Slice(128, 128);
327+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
328+
329+
Assert.AreEqual(memoryOfFloats.Length, 128 / sizeof(float));
330+
331+
Span<byte> spanOfBytes = memoryOfBytes.Span;
332+
Span<float> spanOfFloats = memoryOfFloats.Span;
333+
334+
Assert.AreEqual(memoryOfFloats.Length, spanOfFloats.Length);
335+
Assert.IsTrue(Unsafe.AreSame(
336+
ref spanOfBytes[0],
337+
ref Unsafe.As<float, byte>(ref spanOfFloats[0])));
338+
}
339+
340+
[TestCategory("MemoryExtensions")]
341+
[TestMethod]
342+
public void Test_MemoryExtensions_FromMemoryManager_CastToByte_WithSlice()
343+
{
344+
Memory<float> memoryOfFloats = new ArrayMemoryManager<float>(512).Memory.Slice(128, 128);
345+
Memory<byte> memoryOfBytes = memoryOfFloats.Cast<float, byte>();
346+
347+
Assert.AreEqual(memoryOfBytes.Length, 128 * sizeof(float));
348+
349+
Span<float> spanOfFloats = memoryOfFloats.Span;
350+
Span<byte> spanOfBytes = memoryOfBytes.Span;
351+
352+
Assert.AreEqual(memoryOfBytes.Length, spanOfBytes.Length);
353+
Assert.IsTrue(Unsafe.AreSame(
354+
ref spanOfFloats[0],
355+
ref Unsafe.As<byte, float>(ref spanOfBytes[0])));
356+
}
357+
358+
[TestCategory("MemoryExtensions")]
359+
[TestMethod]
360+
public void Test_MemoryExtensions_FromMemoryManager_CastToShort_WithSlice()
361+
{
362+
Memory<float> memoryOfFloats = new ArrayMemoryManager<float>(512).Memory.Slice(128, 128);
363+
Memory<short> memoryOfShorts = memoryOfFloats.Cast<float, short>();
364+
365+
Assert.AreEqual(memoryOfShorts.Length, 128 * sizeof(float) / sizeof(short));
366+
367+
Span<float> spanOfFloats = memoryOfFloats.Span;
368+
Span<short> spanOfShorts = memoryOfShorts.Span;
369+
370+
Assert.AreEqual(memoryOfShorts.Length, spanOfShorts.Length);
371+
Assert.IsTrue(Unsafe.AreSame(
372+
ref spanOfFloats[0],
373+
ref Unsafe.As<short, float>(ref spanOfShorts[0])));
374+
}
375+
376+
[TestCategory("MemoryExtensions")]
377+
[TestMethod]
378+
public void Test_MemoryExtensions_FromMemoryManager_CastFromByteAndBack_WithSlice()
379+
{
380+
var data = new ArrayMemoryManager<byte>(512);
381+
Memory<byte> memoryOfBytes = data.Memory.Slice(128, 128);
382+
Memory<float> memoryOfFloats = memoryOfBytes.Cast<byte, float>();
383+
Memory<byte> memoryBack = memoryOfFloats.Cast<float, byte>();
384+
385+
Assert.AreEqual(memoryOfBytes.Length, memoryBack.Length);
386+
387+
Assert.IsTrue(MemoryMarshal.TryGetMemoryManager<byte, ArrayMemoryManager<byte>>(memoryBack, out var manager, out var start, out var length));
388+
Assert.AreSame(manager!, data);
389+
Assert.AreEqual(start, 128);
390+
Assert.AreEqual(length, 128);
391+
392+
Assert.IsTrue(memoryOfBytes.Equals(memoryBack));
393+
394+
Span<byte> span1 = memoryOfBytes.Span;
395+
Span<byte> span2 = memoryBack.Span;
396+
397+
Assert.IsTrue(span1 == span2);
398+
}
399+
145400
[TestCategory("MemoryExtensions")]
146401
[TestMethod]
147402
public void Test_MemoryExtensions_EmptyMemoryStream()
@@ -167,5 +422,43 @@ public void Test_MemoryExtensions_MemoryStream()
167422
Assert.AreEqual(stream.Length, memory.Length);
168423
Assert.IsTrue(stream.CanWrite);
169424
}
425+
426+
private sealed class ArrayMemoryManager<T> : MemoryManager<T>
427+
where T : unmanaged
428+
{
429+
private readonly T[] array;
430+
431+
public ArrayMemoryManager(int size)
432+
{
433+
this.array = new T[size];
434+
}
435+
436+
public override Span<T> GetSpan()
437+
{
438+
return this.array;
439+
}
440+
441+
public override unsafe MemoryHandle Pin(int elementIndex = 0)
442+
{
443+
GCHandle handle = GCHandle.Alloc(this.array, GCHandleType.Pinned);
444+
ref T r0 = ref this.array[elementIndex];
445+
void* p = Unsafe.AsPointer(ref r0);
446+
447+
return new MemoryHandle(p, handle);
448+
}
449+
450+
public override void Unpin()
451+
{
452+
}
453+
454+
protected override void Dispose(bool disposing)
455+
{
456+
}
457+
458+
public static implicit operator Memory<T>(ArrayMemoryManager<T> memoryManager)
459+
{
460+
return memoryManager.Memory;
461+
}
462+
}
170463
}
171464
}

0 commit comments

Comments
 (0)