[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);
    }
예제 #2
0
    public void Handle_AfterDisposed_DoesNotThrow()
    {
        using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite())
        {
            ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle(handle);
            boundHandle.Dispose();

            Assert.Same(boundHandle.Handle, handle);
        }
    }
예제 #3
0
 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);
        });
    }
예제 #6
0
    public void BindHandle_ClosedAsyncHandleAsHandle_ThrowsArgumentException()
    {
        using (Win32Handle handle = HandleFactory.CreateAsyncFileHandleForWrite())
        {
            handle.CloseWithoutDisposing();

            Assert.Throws <ArgumentException>("handle", () =>
            {
                ThreadPoolBoundHandle.BindHandle(handle);
            });
        }
    }
예제 #7
0
    [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);
            }
        }
    }
예제 #14
0
    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();
    }
예제 #16
0
    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));
    }