public void HiddenFilesAreReturned() { // Note that APIs that take EnumerationOptions do NOT find hidden files by default DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath()); FileInfo fileOne = new FileInfo(Path.Combine(testDirectory.FullName, GetTestFileName())); // Put a period in front to make it hidden on Unix FileInfo fileTwo = new FileInfo(Path.Combine(testDirectory.FullName, "." + GetTestFileName())); fileOne.Create().Dispose(); fileTwo.Create().Dispose(); if (PlatformDetection.IsWindows) { fileTwo.Attributes = fileTwo.Attributes | FileAttributes.Hidden; } if (TestFiles) { FSAssert.EqualWhenOrdered(new string[] { fileOne.FullName, fileTwo.FullName }, GetEntries(testDirectory.FullName)); } else { Assert.Empty(GetEntries(testDirectory.FullName)); } }
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 <ArgumentOutOfRangeException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2, cancelledToken))); } }
public async Task ReadAsyncBufferedCompletesSynchronously() { string fileName = GetTestFilePath(); using (var fs = new FileStream(fileName, FileMode.Create)) { fs.Write(TestBuffer, 0, TestBuffer.Length); fs.Write(TestBuffer, 0, TestBuffer.Length); } using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete, TestBuffer.Length * 2, useAsync: true)) { byte[] buffer = new byte[TestBuffer.Length]; // prime the internal buffer Assert.Equal(TestBuffer.Length, await ReadAsync(fs, 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(ReadAsync(fs, buffer, 0, buffer.Length))); Assert.Equal(TestBuffer, buffer); } }
public void BufferOutOfBoundsThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { // offset out of bounds Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 1, 1))); // offset out of bounds for 0 count ReadAsync Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 2, 0))); // offset out of bounds even for 0 length buffer Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], 1, 0))); // combination offset and count out of bounds Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); // edges Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], int.MaxValue, 0))); Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], int.MaxValue, int.MaxValue))); } }
public void DirectoryWithTrailingSeparators(string trailing) { // When getting strings back we should retain the root path as specified for Directory. // DirectoryInfo returns the normalized full path in all cases. // Add the trailing separator up front for Directory as we want to validate against // the path _with_ the separator on it. Creation doesn't care about trailing, and // Path.Combine doesn't change the existing separators, it just adds the canonical // separator if needed. string root = GetTestFilePath() + (IsDirectoryInfo ? "" : trailing); string rootFile = Path.Combine(root, GetTestFileName()); string subDirectory = Path.Combine(root, GetTestFileName()); string nestedFile = Path.Combine(subDirectory, GetTestFileName()); Directory.CreateDirectory(subDirectory); File.Create(rootFile).Dispose(); File.Create(nestedFile).Dispose(); // Add the trailing separator if we haven't (for DI) so we can validate that we // either retain (D) or don't retain (DI) the separators as we specified them. // Note that some of the cases actually match canonical (one standard separator) // so they never change. string[] files = GetEntries(root + (IsDirectoryInfo ? trailing : ""), "*", SearchOption.AllDirectories); FSAssert.EqualWhenOrdered(new string[] { rootFile, nestedFile }, files); }
public void ReadAsyncDisposedThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { fs.Dispose(); Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); // even for noop ReadAsync Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 0))); // out of bounds checking happens first Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); // count is checked prior AssertExtensions.Throws <ArgumentOutOfRangeException>(CountParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1))); // offset is checked prior AssertExtensions.Throws <ArgumentOutOfRangeException>(OffsetParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1))); // buffer is checked first AssertExtensions.Throws <ArgumentNullException>(BufferParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1))); } }
public void ReadOnlyThrows() { string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create)) { } using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { Assert.Throws <NotSupportedException>(() => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 1))); fs.Dispose(); // Disposed checking happens first Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 1))); // out of bounds checking happens first Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2))); // count is checked prior Assert.Throws <ArgumentOutOfRangeException>("count", () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1))); // offset is checked prior Assert.Throws <ArgumentOutOfRangeException>("offset", () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1))); // buffer is checked first Assert.Throws <ArgumentNullException>("buffer", () => FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1))); } }
public void NullBufferThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { Assert.Throws <ArgumentNullException>("buffer", () => FSAssert.CompletesSynchronously(fs.WriteAsync(null, 0, 1))); } }
public void NullBufferThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { AssertExtensions.Throws <ArgumentNullException>(BufferParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, null, 0, 1))); } }
public void EnumerateDirectories_NonBreakingSpace() { DirectoryInfo rootDirectory = Directory.CreateDirectory(GetTestFilePath()); DirectoryInfo subDirectory1 = rootDirectory.CreateSubdirectory("\u00A0"); DirectoryInfo subDirectory2 = subDirectory1.CreateSubdirectory(GetTestFileName()); FSAssert.EqualWhenOrdered(new string[] { subDirectory1.FullName, subDirectory2.FullName }, Directory.EnumerateDirectories(rootDirectory.FullName, string.Empty, SearchOption.AllDirectories)); }
public void WriteAsyncBufferedCompletesSynchronously() { using (FileStream fs = new FileStream( GetTestFilePath(), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, TestBuffer.Length * 2, useAsync: true)) { FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[TestBuffer.Length], 0, TestBuffer.Length)); } }
[PlatformSpecific(PlatformID.Windows)] // file sharing restriction limitations on Unix public void FileShareWithoutReadThrows() { string fileName = GetTestFilePath(); // Open without read sharing using (FileStream fs = CreateFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Write | FileShare.Delete)) { FSAssert.ThrowsSharingViolation(() => CreateFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)); } }
public void NegativeOffsetThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { AssertExtensions.Throws <ArgumentOutOfRangeException>(OffsetParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, 1))); // buffer is checked first AssertExtensions.Throws <ArgumentNullException>(BufferParamName, () => FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, 1))); } }
public void NegativeOffsetThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { Assert.Throws <ArgumentOutOfRangeException>("offset", () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, 1))); // buffer is checked first Assert.Throws <ArgumentNullException>("buffer", () => FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, 1))); } }
[PlatformSpecific(XunitPlatformID.Windows)] // file sharing restriction limitations on Unix public void FileShareWithoutDeleteThrows() { string fileName = GetTestFilePath(); string newFileName = GetTestFilePath(); // Create without delete sharing using (FileStream fs = CreateFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { FSAssert.ThrowsSharingViolation(() => File.Delete(fileName)); FSAssert.ThrowsSharingViolation(() => File.Move(fileName, newFileName)); } Assert.True(File.Exists(fileName)); }
public void WriteAsyncDisposedThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { fs.Dispose(); Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 1))); // even for noop WriteAsync Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 0))); // out of bounds checking happens first Assert.Throws <ArgumentOutOfRangeException>(() => FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[2], 1, 2))); } }
public void FileShareWithoutWriteThrows() { string fileName = GetTestFilePath(); // Open without write sharing using (FileStream fs = CreateFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { FSAssert.ThrowsSharingViolation(() => CreateFileStream(fileName, FileMode.Open, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete)); } // Then try the other way around using (FileStream fs = CreateFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) { FSAssert.ThrowsSharingViolation(() => CreateFileStream(fileName, FileMode.Open, FileAccess.Write, FileShare.None)); } }
public void NegativeCountThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { AssertExtensions.Throws <ArgumentOutOfRangeException>("count", () => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, -1))); // offset is checked before count AssertExtensions.Throws <ArgumentOutOfRangeException>("offset", () => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, -1))); // buffer is checked first AssertExtensions.Throws <ArgumentNullException>("buffer", () => FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, -1))); } }
public void NoTruncateOnFileShareViolation(FileMode fileMode) { string fileName = GetTestFilePath(); using (FileStream fs = CreateFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { fs.Write(new byte[] { 42 }, 0, 1); fs.Flush(); FSAssert.ThrowsSharingViolation(() => CreateFileStream(fileName, fileMode, FileAccess.Write, FileShare.None).Dispose()); } using (FileStream reader = CreateFileStream(fileName, FileMode.Open, FileAccess.Read)) { byte[] buf = new byte[1]; Assert.Equal(1, reader.Read(buf, 0, 1)); Assert.Equal(42, buf[0]); } }
public void WriteOnlyThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) { Assert.Throws <NotSupportedException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); fs.Dispose(); // Disposed checking happens first Assert.Throws <ObjectDisposedException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); // out of bounds checking happens first Assert.Throws <ArgumentOutOfRangeException>(() => FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); } }
public void CancelledTokenFastPath() { CancellationTokenSource cts = new CancellationTokenSource(); cts.Cancel(); CancellationToken cancelledToken = cts.Token; string fileName = GetTestFilePath(); using (FileStream fs = new FileStream(fileName, FileMode.Create)) { FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); } using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { // before read only check FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); fs.Dispose(); // before disposed check FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); // out of bounds checking happens first Assert.Throws <ArgumentException>(null, () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2, cancelledToken))); // count is checked prior Assert.Throws <ArgumentOutOfRangeException>("count", () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1, cancelledToken))); // offset is checked prior Assert.Throws <ArgumentOutOfRangeException>("offset", () => FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1, cancelledToken))); // buffer is checked first Assert.Throws <ArgumentNullException>("buffer", () => FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1, cancelledToken))); } }
public void WriteAsyncBufferedCompletesSynchronously() { // It doesn't make sense to spin up a background thread just to do a memcpy. // This isn't working now for useAsync:true since we always have a usercallback // that get's run on the threadpool (see Win32FileStream.EndWriteTask) // This isn't working now for useAsync:false since we always call // Stream.WriteAsync that queues Read on a background thread foreach (bool useAsync in new[] { true, false }) { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, TestBuffer.Length * 2, useAsync)) { byte[] buffer = new byte[TestBuffer.Length]; // Existing issue: FileStreamAsyncResult doesn't set CompletedSynchronously correctly. // write should now complete synchronously since it is just copying to the write buffer FSAssert.CompletesSynchronously(fs.WriteAsync(buffer, 0, buffer.Length)); } } }
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); } } }
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()); } } }
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()); } } }
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()); } } }