[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void SingleOperationOverSingleHandle() { const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"SingleOverlappedOverSingleHandle.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext result = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; data[0] = (byte)'A'; data[1] = (byte)'B'; NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result, data); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operation to complete result.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(0, result.ErrorCode); Assert.Equal(DATA_SIZE, result.BytesWritten); }
public void Handle_AfterDisposed_DoesNotThrow() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle(handle); boundHandle.Dispose(); Assert.Same(boundHandle.Handle, handle); } }
public void Handle_ReturnsHandle() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { using (ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle(handle)) { Assert.Same(boundHandle.Handle, handle); } } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void MultipleOperationsOverSingleHandle() { const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverSingleHandle.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext result1 = new OverlappedContext(); OverlappedContext result2 = new OverlappedContext(); byte[] data1 = new byte[DATA_SIZE]; data1[0] = (byte)'A'; data1[1] = (byte)'B'; byte[] data2 = new byte[DATA_SIZE]; data2[0] = (byte)'C'; data2[1] = (byte)'D'; NativeOverlapped *overlapped1 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result1, data1); NativeOverlapped *overlapped2 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result2, data2); fixed(byte *p1 = data1, p2 = data2) { int retval = DllImport.WriteFile(boundHandle.Handle, p1, DATA_SIZE, IntPtr.Zero, overlapped1); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Start the offset after the above write, so that it doesn't overwrite the previous write overlapped2->OffsetLow = DATA_SIZE; retval = DllImport.WriteFile(boundHandle.Handle, p2, DATA_SIZE, IntPtr.Zero, overlapped2); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operations to complete WaitHandle.WaitAll(new WaitHandle[] { result1.Event, result2.Event }); } boundHandle.FreeNativeOverlapped(overlapped1); boundHandle.FreeNativeOverlapped(overlapped2); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(0, result1.ErrorCode); Assert.Equal(0, result2.ErrorCode); Assert.Equal(DATA_SIZE, result1.BytesWritten); Assert.Equal(DATA_SIZE, result2.BytesWritten); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public void BindHandle_DisposedAsyncHandleAsHandle_ThrowsArgumentException() { Win32Handle handle = HandleFactory.CreateAsyncFileHandleForWrite(); handle.Dispose(); AssertExtensions.Throws <ArgumentException>("handle", () => { ThreadPoolBoundHandle.BindHandle(handle); }); }
public void BindHandle_ClosedAsyncHandleAsHandle_ThrowsArgumentException() { using (Win32Handle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { handle.CloseWithoutDisposing(); Assert.Throws <ArgumentException>("handle", () => { ThreadPoolBoundHandle.BindHandle(handle); }); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FlowsAsyncLocalsToCallback_PreAllocatedOverlapped(bool shouldFlow) { // Makes sure that we flow async locals to callback const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"AsyncLocal.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext context = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; AsyncLocal <int> asyncLocal = new AsyncLocal <int>(); asyncLocal.Value = 10; int?result = null; IOCompletionCallback callback = (_, __, ___) => { result = asyncLocal.Value; OnOverlappedOperationCompleted(_, __, ___); }; using (PreAllocatedOverlapped preAlloc = shouldFlow ? new PreAllocatedOverlapped(callback, context, data) : PreAllocatedOverlapped.UnsafeCreate(callback, context, data)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(preAlloc); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastPInvokeError()); } // Wait for overlapped operation to complete context.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); } boundHandle.Dispose(); handle.Dispose(); Assert.Equal( shouldFlow ? 10 : 0, result); }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { if (handle == null) { handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); // ThreadPoolBoundHandle does not take ownership of the handle; // we must close it _handlesToDispose.Add(handle); } return(ThreadPoolBoundHandle.BindHandle(handle)); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public void BindHandle_AlreadyBoundHandleAsHandle_ThrowsArgumentException() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { // Once ThreadPoolBoundHandle.BindHandle(handle); AssertExtensions.Throws <ArgumentException>("handle", () => { // Twice ThreadPoolBoundHandle.BindHandle(handle); }); } }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); try { return(ThreadPoolBoundHandle.BindHandle(handle)); } catch (ArgumentException ex) when(ex.GetType() == typeof(ArgumentException)) { // TODO: Remove this try/catch, which is intended to help with debugging https://github.com/dotnet/corefx/issues/18058 throw new ArgumentException("Handle value: " + handle.DangerousGetHandle(), ex.ParamName, ex); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsNull_ReturnsNull() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Null(result); boundHandle.FreeNativeOverlapped(overlapped); } } }
public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsObject_ReturnsObject() { object context = new object(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsIAsyncResult_ReturnsIAsyncResult() { // CoreCLR/Desktop CLR version of overlapped sits on top of Overlapped class // and treats IAsyncResult specially, which is why we special case this case. AsyncResult context = new AsyncResult(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
private static ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(); return(ThreadPoolBoundHandle.BindHandle(handle)); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void MultipleOperationsOverMultipleHandles() { const int DATA_SIZE = 2; SafeHandle handle1 = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle1.tmp")); SafeHandle handle2 = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle2.tmp")); ThreadPoolBoundHandle boundHandle1 = ThreadPoolBoundHandle.BindHandle(handle1); ThreadPoolBoundHandle boundHandle2 = ThreadPoolBoundHandle.BindHandle(handle2); OverlappedContext result1 = new OverlappedContext(); OverlappedContext result2 = new OverlappedContext(); byte[] data1 = new byte[DATA_SIZE]; data1[0] = (byte)'A'; data1[1] = (byte)'B'; byte[] data2 = new byte[DATA_SIZE]; data2[0] = (byte)'C'; data2[1] = (byte)'D'; PreAllocatedOverlapped preAlloc1 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result1, data1); PreAllocatedOverlapped preAlloc2 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result2, data2); for (int i = 0; i < 10; i++) { NativeOverlapped *overlapped1 = boundHandle1.AllocateNativeOverlapped(preAlloc1); NativeOverlapped *overlapped2 = boundHandle2.AllocateNativeOverlapped(preAlloc2); fixed(byte *p1 = data1, p2 = data2) { int retval = DllImport.WriteFile(boundHandle1.Handle, p1, DATA_SIZE, IntPtr.Zero, overlapped1); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } retval = DllImport.WriteFile(boundHandle2.Handle, p2, DATA_SIZE, IntPtr.Zero, overlapped2); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operations to complete WaitHandle.WaitAll(new WaitHandle[] { result1.Event, result2.Event }); } boundHandle1.FreeNativeOverlapped(overlapped1); boundHandle2.FreeNativeOverlapped(overlapped2); result1.Event.Reset(); result2.Event.Reset(); Assert.Equal(0, result1.ErrorCode); Assert.Equal(0, result2.ErrorCode); Assert.Equal(DATA_SIZE, result1.BytesWritten); Assert.Equal(DATA_SIZE, result2.BytesWritten); } boundHandle1.Dispose(); boundHandle2.Dispose(); preAlloc1.Dispose(); preAlloc2.Dispose(); handle1.Dispose(); handle2.Dispose(); }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); return(ThreadPoolBoundHandle.BindHandle(handle)); }