public void CancelledTokenFastPath() { var cts = new CancellationTokenSource(); cts.Cancel(); CancellationToken cancelledToken = cts.Token; using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); } using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) { // before write only check FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); fs.Dispose(); // before disposed check FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); // out of bounds checking happens first Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2, cancelledToken))); // count is checked prior AssertExtensions.Throws <ArgumentOutOfRangeException>(CountParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1, cancelledToken))); // offset is checked prior AssertExtensions.Throws <ArgumentOutOfRangeException>(OffsetParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1, cancelledToken))); // buffer is checked first AssertExtensions.Throws <ArgumentNullException>(BufferParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1, cancelledToken))); } }
public async Task ReadAsyncBufferedCompletesSynchronously() { // It doesn't make sense to spin up a background thread just to do a memcpy. string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create)) { fs.Write(TestBuffer, 0, TestBuffer.Length); fs.Write(TestBuffer, 0, TestBuffer.Length); } // This isn't working now for useAsync:true since we always have a usercallback // that get's run on the threadpool (see Win32FileStream.EndReadTask) // This isn't working now for useAsync:false since we always call // Stream.ReadAsync that queues Read on a background thread foreach (bool useAsync in new[] { true, false }) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete, TestBuffer.Length * 2, useAsync)) { byte[] buffer = new byte[TestBuffer.Length]; // Existing issue: FileStreamAsyncResult doesn't set CompletedSynchronously correctly. // prime the internal buffer Assert.Equal(TestBuffer.Length, await fs.ReadAsync(buffer, 0, buffer.Length)); Assert.Equal(TestBuffer, buffer); Array.Clear(buffer, 0, buffer.Length); // read should now complete synchronously since it is serviced by the read buffer filled in the first request Assert.Equal(TestBuffer.Length, FSAssert.CompletesSynchronously(fs.ReadAsync(buffer, 0, buffer.Length))); Assert.Equal(TestBuffer, buffer); } } }
private async Task ThrowWhenHandlePositionIsChanged(bool useAsync) { string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 0x100, useAsync)) { // write some data to move the position, flush to ensure OS position is updated fs.Write(TestBuffer, 0, TestBuffer.Length); fs.Flush(); if (fs.SafeFileHandle.IsInvalid) { // nothing to test return; } using (FileStream fsr = new FileStream(fs.SafeFileHandle, FileAccess.Read, TestBuffer.Length, useAsync)) { Assert.Equal(TestBuffer.Length, fs.Position); Assert.Equal(TestBuffer.Length, fsr.Position); // Operations on original filestream will fail if data is in buffer and position changes. // Put data in FS write buffer and update position from FSR fs.WriteByte(0); fsr.Position = 0; Assert.Throws <IOException>(() => fs.Position); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Read(new byte[1], 0, 1)); fs.WriteByte(0); fsr.Position++; if (useAsync && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // Async I/O behaviors differ due to kernel-based implementation on Windows { Assert.Throws <IOException>(() => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); } else { await Assert.ThrowsAsync <IOException>(() => fs.ReadAsync(new byte[1], 0, 1)); } fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.ReadByte()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Seek(0, SeekOrigin.End)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.SetLength(2)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Flush()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Dispose()); } } }
private async Task ThrowWhenHandlePositionIsChanged(bool useAsync) { string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 0x100, useAsync)) { // write some data to move the position, flush to ensure OS position is updated fs.Write(TestBuffer, 0, TestBuffer.Length); fs.Flush(); if (fs.SafeFileHandle.IsInvalid) { // nothing to test return; } using (FileStream fsr = new FileStream(fs.SafeFileHandle, FileAccess.Read, TestBuffer.Length, useAsync)) { Assert.Equal(TestBuffer.Length, fs.Position); Assert.Equal(TestBuffer.Length, fsr.Position); // Operations on original filestream will fail if data is in buffer and position changes. // Put data in FS write buffer and update position from FSR fs.WriteByte(0); fsr.Position = 0; if (useAsync // Async I/O behaviors differ due to kernel-based implementation on Windows && OperatingSystem.IsWindows() // ReadAsync which in this case (single byte written to buffer) calls FlushAsync is now 100% async // so it does not complete synchronously anymore && PlatformDetection.IsLegacyFileStreamEnabled) { Assert.Throws <IOException>(() => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); } else { await Assert.ThrowsAsync <IOException>(() => fs.ReadAsync(new byte[1], 0, 1)); } fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Read(new byte[1], 0, 1)); fs.WriteByte(0); fsr.Position++; await Assert.ThrowsAsync <IOException>(() => fs.ReadAsync(new byte[1], 0, 1)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.ReadByte()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Seek(0, SeekOrigin.End)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.SetLength(2)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Flush()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Dispose()); } } }
public async Task ThrowWhenHandlePositionIsChanged() { string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create)) { // write some data to move the position, flush to ensure OS position is updated fs.Write(TestBuffer, 0, TestBuffer.Length); fs.Flush(); if (fs.SafeFileHandle.IsInvalid) { // nothing to test return; } using (FileStream fsr = new FileStream(fs.SafeFileHandle, FileAccess.Read, TestBuffer.Length)) { Assert.Equal(TestBuffer.Length, fs.Position); Assert.Equal(TestBuffer.Length, fsr.Position); // Operations on original filestream will fail if data is in buffer and position changes. // Put data in FS write buffer and update position from FSR fs.WriteByte(0); fsr.Position = 0; Assert.Throws <IOException>(() => fs.Position); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Read(new byte[1], 0, 1)); fs.WriteByte(0); fsr.Position++; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // TODO: [ActiveIssue(812)]: Remove guard when async I/O is properly implemented on Unix { Assert.Throws <IOException>(() => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); } else { await Assert.ThrowsAsync <IOException>(() => fs.ReadAsync(new byte[1], 0, 1)); } fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.ReadByte()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Seek(0, SeekOrigin.End)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.SetLength(2)); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Flush()); fs.WriteByte(0); fsr.Position++; Assert.Throws <IOException>(() => fs.Dispose()); } } }