1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Buffers; 6 using System.Runtime.InteropServices; 7 using System.Threading; 8 using System.Threading.Tasks; 9 using Xunit; 10 11 namespace System.IO.Tests 12 { 13 public class Stream_ReadWriteSpan 14 { 15 [Fact] ReadSpan_DelegatesToRead_Success()16 public void ReadSpan_DelegatesToRead_Success() 17 { 18 bool readInvoked = false; 19 var s = new DelegateStream( 20 canReadFunc: () => true, 21 readFunc: (array, offset, count) => 22 { 23 readInvoked = true; 24 Assert.NotNull(array); 25 Assert.Equal(0, offset); 26 Assert.Equal(20, count); 27 28 for (int i = 0; i < 10; i++) array[offset + i] = (byte)i; 29 return 10; 30 }); 31 32 Span<byte> totalSpan = new byte[30]; 33 Span<byte> targetSpan = totalSpan.Slice(5, 20); 34 35 Assert.Equal(10, s.Read(targetSpan)); 36 Assert.True(readInvoked); 37 for (int i = 0; i < 10; i++) Assert.Equal(i, targetSpan[i]); 38 for (int i = 10; i < 20; i++) Assert.Equal(0, targetSpan[i]); 39 readInvoked = false; 40 } 41 42 [Fact] WriteSpan_DelegatesToWrite_Success()43 public void WriteSpan_DelegatesToWrite_Success() 44 { 45 bool writeInvoked = false; 46 var s = new DelegateStream( 47 canWriteFunc: () => true, 48 writeFunc: (array, offset, count) => 49 { 50 writeInvoked = true; 51 Assert.NotNull(array); 52 Assert.Equal(0, offset); 53 Assert.Equal(3, count); 54 55 for (int i = 0; i < count; i++) Assert.Equal(i, array[offset + i]); 56 }); 57 58 Span<byte> span = new byte[10]; 59 span[3] = 1; 60 span[4] = 2; 61 s.Write(span.Slice(2, 3)); 62 Assert.True(writeInvoked); 63 writeInvoked = false; 64 } 65 66 [Fact] ReadAsyncMemory_WrapsArray_DelegatesToReadAsyncArray_Success()67 public async Task ReadAsyncMemory_WrapsArray_DelegatesToReadAsyncArray_Success() 68 { 69 bool readInvoked = false; 70 var s = new DelegateStream( 71 canReadFunc: () => true, 72 readAsyncFunc: (array, offset, count, cancellationToken) => 73 { 74 readInvoked = true; 75 Assert.NotNull(array); 76 Assert.Equal(5, offset); 77 Assert.Equal(20, count); 78 79 for (int i = 0; i < 10; i++) 80 { 81 array[offset + i] = (byte)i; 82 } 83 return Task.FromResult(10); 84 }); 85 86 Memory<byte> totalMemory = new byte[30]; 87 Memory<byte> targetMemory = totalMemory.Slice(5, 20); 88 89 Assert.Equal(10, await s.ReadAsync(targetMemory)); 90 Assert.True(readInvoked); 91 for (int i = 0; i < 10; i++) 92 Assert.Equal(i, targetMemory.Span[i]); 93 for (int i = 10; i < 20; i++) 94 Assert.Equal(0, targetMemory.Span[i]); 95 readInvoked = false; 96 } 97 98 [Fact] ReadAsyncMemory_WrapsNative_DelegatesToReadAsyncArrayWithPool_Success()99 public async Task ReadAsyncMemory_WrapsNative_DelegatesToReadAsyncArrayWithPool_Success() 100 { 101 bool readInvoked = false; 102 var s = new DelegateStream( 103 canReadFunc: () => true, 104 readAsyncFunc: (array, offset, count, cancellationToken) => 105 { 106 readInvoked = true; 107 Assert.NotNull(array); 108 Assert.Equal(0, offset); 109 Assert.Equal(20, count); 110 111 for (int i = 0; i < 10; i++) 112 { 113 array[offset + i] = (byte)i; 114 } 115 return Task.FromResult(10); 116 }); 117 118 using (var totalNativeMemory = new NativeOwnedMemory(30)) 119 { 120 Memory<byte> totalMemory = totalNativeMemory.Memory; 121 Memory<byte> targetMemory = totalMemory.Slice(5, 20); 122 123 Assert.Equal(10, await s.ReadAsync(targetMemory)); 124 Assert.True(readInvoked); 125 for (int i = 0; i < 10; i++) 126 Assert.Equal(i, targetMemory.Span[i]); 127 readInvoked = false; 128 } 129 } 130 131 [Fact] WriteAsyncMemory_WrapsArray_DelegatesToWrite_Success()132 public async Task WriteAsyncMemory_WrapsArray_DelegatesToWrite_Success() 133 { 134 bool writeInvoked = false; 135 var s = new DelegateStream( 136 canWriteFunc: () => true, 137 writeAsyncFunc: (array, offset, count, cancellationToken) => 138 { 139 writeInvoked = true; 140 Assert.NotNull(array); 141 Assert.Equal(2, offset); 142 Assert.Equal(3, count); 143 144 for (int i = 0; i < count; i++) 145 Assert.Equal(i, array[offset + i]); 146 147 return Task.CompletedTask; 148 }); 149 150 Memory<byte> memory = new byte[10]; 151 memory.Span[3] = 1; 152 memory.Span[4] = 2; 153 await s.WriteAsync(memory.Slice(2, 3)); 154 Assert.True(writeInvoked); 155 writeInvoked = false; 156 } 157 158 [Fact] WriteAsyncMemory_WrapsNative_DelegatesToWrite_Success()159 public async Task WriteAsyncMemory_WrapsNative_DelegatesToWrite_Success() 160 { 161 bool writeInvoked = false; 162 var s = new DelegateStream( 163 canWriteFunc: () => true, 164 writeAsyncFunc: (array, offset, count, cancellationToken) => 165 { 166 writeInvoked = true; 167 Assert.NotNull(array); 168 Assert.Equal(0, offset); 169 Assert.Equal(3, count); 170 171 for (int i = 0; i < count; i++) 172 Assert.Equal(i, array[i]); 173 174 return Task.CompletedTask; 175 }); 176 177 using (var nativeMemory = new NativeOwnedMemory(10)) 178 { 179 Memory<byte> memory = nativeMemory.Memory; 180 memory.Span[2] = 0; 181 memory.Span[3] = 1; 182 memory.Span[4] = 2; 183 await s.WriteAsync(memory.Slice(2, 3)); 184 Assert.True(writeInvoked); 185 writeInvoked = false; 186 } 187 } 188 } 189 } 190