From b269ffeb5a1f21166c362a3d22a230157e8a375a Mon Sep 17 00:00:00 2001 From: lateapexearlyspeed Date: Tue, 31 Aug 2021 19:59:38 +0800 Subject: [PATCH 1/7] lateapexearlyspeed-issue-58383 Support unseekable filestream when ReadAllBytes[Async]. --- .../System.Private.CoreLib/src/System/IO/File.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index ff2a7bd9ef628..8bd0c966d42f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -333,6 +333,11 @@ public static byte[] ReadAllBytes(string path) // bufferSize == 1 used to avoid unnecessary buffer in FileStream using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, FileOptions.SequentialScan)) { + if (!fs.CanSeek) + { + return ReadAllBytesUnknownLength(fs); + } + long fileLength = fs.Length; if (fileLength > int.MaxValue) { @@ -729,6 +734,12 @@ private static async Task InternalReadAllTextAsync(string path, Encoding bool returningInternalTask = false; try { + if (!fs.CanSeek) + { + returningInternalTask = true; + return InternalReadAllBytesUnknownLengthAsync(fs, cancellationToken); + } + long fileLength = fs.Length; if (fileLength > int.MaxValue) { From c50ab3de8797d11a48f74e27b9e41fc2b91438a6 Mon Sep 17 00:00:00 2001 From: lateapexearlyspeed Date: Fri, 10 Sep 2021 15:43:52 +0800 Subject: [PATCH 2/7] issue-58383 Refine code; Add test cases. --- .../tests/File/ReadWriteAllBytes.cs | 27 +++++++++++++++++++ .../tests/File/ReadWriteAllBytesAsync.cs | 27 +++++++++++++++++++ .../src/System/IO/File.cs | 27 +++++++------------ 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 54c7643766335..bc19c9a1fdbeb 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; namespace System.IO.Tests { @@ -172,5 +173,31 @@ public void ProcFs_NotEmpty(string path) { Assert.InRange(File.ReadAllBytes(path).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept + public async Task ReadAllBytes_NonSeekableFileStream() + { + string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); + string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); + + var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); + var contentBytes = new byte[] { 1, 2, 3 }; + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes); + + byte[] readBytes = File.ReadAllBytes(pipePath); + + await writingServerTask; + Assert.Equal(contentBytes, readBytes); + + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes) + { + await using (namedPipeWriterStream) + { + await namedPipeWriterStream.WaitForConnectionAsync(); + await namedPipeWriterStream.WriteAsync(contentBytes); + } + } + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index 748c01dbffb8f..5d103244ceded 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; namespace System.IO.Tests { @@ -186,5 +187,31 @@ public async Task ProcFs_NotEmpty(string path) { Assert.InRange((await File.ReadAllBytesAsync(path)).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept + public async Task ReadAllBytesAsync_NonSeekableFileStream() + { + string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); + string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); + + var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); + var contentBytes = new byte[] { 1, 2, 3 }; + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes); + + byte[] readBytes = await File.ReadAllBytesAsync(pipePath); + + await writingServerTask; + Assert.Equal(contentBytes, readBytes); + + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes) + { + await using (namedPipeWriterStream) + { + await namedPipeWriterStream.WaitForConnectionAsync(); + await namedPipeWriterStream.WriteAsync(contentBytes); + } + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 8bd0c966d42f2..af54d64ee5440 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -333,20 +333,17 @@ public static byte[] ReadAllBytes(string path) // bufferSize == 1 used to avoid unnecessary buffer in FileStream using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, FileOptions.SequentialScan)) { - if (!fs.CanSeek) - { - return ReadAllBytesUnknownLength(fs); - } - - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { throw new IOException(SR.IO_FileTooLong2GB); } - else if (fileLength == 0) + if (fileLength == 0) { -#if !MS_IO_REDIST - // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content. +#if MS_IO_REDIST + return Array.Empty(); +#else + // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content; also there is non-seekable file stream. // Thus we need to assume 0 doesn't mean empty. return ReadAllBytesUnknownLength(fs); #endif @@ -734,14 +731,8 @@ private static async Task InternalReadAllTextAsync(string path, Encoding bool returningInternalTask = false; try { - if (!fs.CanSeek) - { - returningInternalTask = true; - return InternalReadAllBytesUnknownLengthAsync(fs, cancellationToken); - } - - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0L; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { var e = new IOException(SR.IO_FileTooLong2GB); #if !MS_IO_REDIST From d4cf11eeb980d77a890cbdb24b45b10d08222817 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Mon, 13 Sep 2021 17:29:21 +0200 Subject: [PATCH 3/7] the docs were wrong, offsets are not ignored for non-seekable files --- ...leHandle.OverlappedValueTaskSource.Windows.cs | 7 +++++-- .../src/System/IO/RandomAccess.Windows.cs | 16 +++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs index 9f689b161bbd0..c2eab851bd60e 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs @@ -86,8 +86,11 @@ internal static Exception GetIOError(int errorCode, string? path) _bufferSize = memory.Length; _memoryHandle = memory.Pin(); _overlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_preallocatedOverlapped); - _overlapped->OffsetLow = (int)fileOffset; - _overlapped->OffsetHigh = (int)(fileOffset >> 32); + if (_fileHandle.CanSeek) + { + _overlapped->OffsetLow = (int)fileOffset; + _overlapped->OffsetHigh = (int)(fileOffset >> 32); + } return _overlapped; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index d367abb8fb973..9aeb7ecafeb60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -69,7 +69,7 @@ private static unsafe int ReadSyncUsingAsyncHandle(SafeFileHandle handle, SpanOffsetLow = unchecked((int)fileOffset); - result->OffsetHigh = (int)(fileOffset >> 32); + if (handle.CanSeek) + { + result->OffsetLow = unchecked((int)fileOffset); + result->OffsetHigh = (int)(fileOffset >> 32); + } // From https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresult: // "If the hEvent member of the OVERLAPPED structure is NULL, the system uses the state of the hFile handle to signal when the operation has been completed. From b47fd7fd3343d4593c70f44b68129a8af69bfe93 Mon Sep 17 00:00:00 2001 From: lateapexearlyspeed Date: Wed, 29 Sep 2021 15:39:36 +0800 Subject: [PATCH 4/7] issue-58383 Fix comment: add linux side test cases. --- .../tests/File/ReadWriteAllBytes.cs | 41 +++++++++++++++---- .../tests/File/ReadWriteAllBytesAsync.cs | 38 +++++++++++++---- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index bc19c9a1fdbeb..1b49581c15c34 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Threading; using System.Threading.Tasks; using Xunit; using System.IO.Pipes; @@ -176,28 +177,52 @@ public void ProcFs_NotEmpty(string path) [Fact] [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept - public async Task ReadAllBytes_NonSeekableFileStream() + public async Task ReadAllBytes_NonSeekableFileStream_InWindows() { string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); var contentBytes = new byte[] { 1, 2, 3 }; - Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes); - byte[] readBytes = File.ReadAllBytes(pipePath); + using (var cts = new CancellationTokenSource()) + { + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); + Task readTask = Task.Run(() => File.ReadAllBytes(pipePath), cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(10)); - await writingServerTask; - Assert.Equal(contentBytes, readBytes); + await writingServerTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } - static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes) + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes, CancellationToken cancellationToken) { await using (namedPipeWriterStream) { - await namedPipeWriterStream.WaitForConnectionAsync(); - await namedPipeWriterStream.WriteAsync(contentBytes); + await namedPipeWriterStream.WaitForConnectionAsync(cancellationToken); + await namedPipeWriterStream.WriteAsync(contentBytes, cancellationToken); } } } + + [Fact] + [PlatformSpecific(TestPlatforms.Linux)] + public async Task ReadAllBytes_NonSeekableFileStream_InLinux() + { + var path = "/dev/tty"; + var contentBytes = new byte[] { 1, 2, 3 }; + + using (var cts = new CancellationTokenSource()) + { + Task writingTask = File.WriteAllBytesAsync(path, contentBytes, cts.Token); + Task readTask = Task.Run(() => File.ReadAllBytes(path), cts.Token); + cts.CancelAfter(TimeSpan.FromMilliseconds(500)); + + await writingTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index 5d103244ceded..c2c5cad9316dd 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -197,21 +197,45 @@ public async Task ReadAllBytesAsync_NonSeekableFileStream() var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); var contentBytes = new byte[] { 1, 2, 3 }; - Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes); - byte[] readBytes = await File.ReadAllBytesAsync(pipePath); + using (var cts = new CancellationTokenSource()) + { + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); + Task readTask = File.ReadAllBytesAsync(pipePath, cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(10)); - await writingServerTask; - Assert.Equal(contentBytes, readBytes); + await writingServerTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } - static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes) + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes, CancellationToken cancellationToken) { await using (namedPipeWriterStream) { - await namedPipeWriterStream.WaitForConnectionAsync(); - await namedPipeWriterStream.WriteAsync(contentBytes); + await namedPipeWriterStream.WaitForConnectionAsync(cancellationToken); + await namedPipeWriterStream.WriteAsync(contentBytes, cancellationToken); } } } + + [Fact] + [PlatformSpecific(TestPlatforms.Linux)] + public async Task ReadAllBytesAsync_NonSeekableFileStream_InLinux() + { + var path = "/dev/tty"; + var contentBytes = new byte[] { 1, 2, 3 }; + + using (var cts = new CancellationTokenSource()) + { + Task writingTask = File.WriteAllBytesAsync(path, contentBytes, cts.Token); + Task readTask = File.ReadAllBytesAsync(path, cts.Token); + cts.CancelAfter(TimeSpan.FromMilliseconds(500)); + + await writingTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } + } } } From e98fb15a21992ecef5a00383b86db55b82c104ec Mon Sep 17 00:00:00 2001 From: lateapexearlyspeed Date: Wed, 29 Sep 2021 17:48:24 +0800 Subject: [PATCH 5/7] issue-58383 Check /dev/tty existence before running test. --- .../tests/File/ReadWriteAllBytes.cs | 12 +++++++++--- .../tests/File/ReadWriteAllBytesAsync.cs | 14 ++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 1b49581c15c34..44e773bc288ad 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Xunit; using System.IO.Pipes; +using Microsoft.DotNet.XUnitExtensions; namespace System.IO.Tests { @@ -189,7 +190,7 @@ public async Task ReadAllBytes_NonSeekableFileStream_InWindows() { Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); Task readTask = Task.Run(() => File.ReadAllBytes(pipePath), cts.Token); - cts.CancelAfter(TimeSpan.FromSeconds(10)); + cts.CancelAfter(TimeSpan.FromSeconds(50)); await writingServerTask; byte[] readBytes = await readTask; @@ -207,10 +208,15 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na } [Fact] - [PlatformSpecific(TestPlatforms.Linux)] - public async Task ReadAllBytes_NonSeekableFileStream_InLinux() + [PlatformSpecific(TestPlatforms.AnyUnix)] + public async Task ReadAllBytes_NonSeekableFileStream_InUnix() { var path = "/dev/tty"; + if (!File.Exists(path)) + { + throw new SkipTestException(path + " is not available in this environment."); + } + var contentBytes = new byte[] { 1, 2, 3 }; using (var cts = new CancellationTokenSource()) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index c2c5cad9316dd..ea7b3bfa18936 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Xunit; using System.IO.Pipes; +using Microsoft.DotNet.XUnitExtensions; namespace System.IO.Tests { @@ -190,7 +191,7 @@ public async Task ProcFs_NotEmpty(string path) [Fact] [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept - public async Task ReadAllBytesAsync_NonSeekableFileStream() + public async Task ReadAllBytesAsync_NonSeekableFileStream_InWindows() { string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); @@ -202,7 +203,7 @@ public async Task ReadAllBytesAsync_NonSeekableFileStream() { Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); Task readTask = File.ReadAllBytesAsync(pipePath, cts.Token); - cts.CancelAfter(TimeSpan.FromSeconds(10)); + cts.CancelAfter(TimeSpan.FromSeconds(50)); await writingServerTask; byte[] readBytes = await readTask; @@ -220,10 +221,15 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na } [Fact] - [PlatformSpecific(TestPlatforms.Linux)] - public async Task ReadAllBytesAsync_NonSeekableFileStream_InLinux() + [PlatformSpecific(TestPlatforms.AnyUnix)] + public async Task ReadAllBytesAsync_NonSeekableFileStream_InUnix() { var path = "/dev/tty"; + if (!File.Exists(path)) + { + throw new SkipTestException(path + " is not available in this environment."); + } + var contentBytes = new byte[] { 1, 2, 3 }; using (var cts = new CancellationTokenSource()) From b0f8adb8d6ad5864a9e89e01a9592ed2b3127bc1 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 13 Oct 2021 15:38:00 +0200 Subject: [PATCH 6/7] improve the tests --- .../tests/File/ReadWriteAllBytes.cs | 31 ++++++++++--------- .../tests/File/ReadWriteAllBytesAsync.cs | 31 ++++++++++--------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 44e773bc288ad..8e0bbdef48edf 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -211,24 +211,25 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na [PlatformSpecific(TestPlatforms.AnyUnix)] public async Task ReadAllBytes_NonSeekableFileStream_InUnix() { - var path = "/dev/tty"; - if (!File.Exists(path)) - { - throw new SkipTestException(path + " is not available in this environment."); - } + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); var contentBytes = new byte[] { 1, 2, 3 }; - using (var cts = new CancellationTokenSource()) - { - Task writingTask = File.WriteAllBytesAsync(path, contentBytes, cts.Token); - Task readTask = Task.Run(() => File.ReadAllBytes(path), cts.Token); - cts.CancelAfter(TimeSpan.FromMilliseconds(500)); - - await writingTask; - byte[] readBytes = await readTask; - Assert.Equal(contentBytes, readBytes); - } + await Task.WhenAll( + Task.Run(() => + { + byte[] readBytes = File.ReadAllBytes(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index ea7b3bfa18936..e7b16782b5acc 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -224,24 +224,25 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na [PlatformSpecific(TestPlatforms.AnyUnix)] public async Task ReadAllBytesAsync_NonSeekableFileStream_InUnix() { - var path = "/dev/tty"; - if (!File.Exists(path)) - { - throw new SkipTestException(path + " is not available in this environment."); - } + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); var contentBytes = new byte[] { 1, 2, 3 }; - using (var cts = new CancellationTokenSource()) - { - Task writingTask = File.WriteAllBytesAsync(path, contentBytes, cts.Token); - Task readTask = File.ReadAllBytesAsync(path, cts.Token); - cts.CancelAfter(TimeSpan.FromMilliseconds(500)); - - await writingTask; - byte[] readBytes = await readTask; - Assert.Equal(contentBytes, readBytes); - } + await Task.WhenAll( + Task.Run(async () => + { + byte[] readBytes = await File.ReadAllBytesAsync(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); } } } From b741120a73a9e329d1ec11753d7a947c2e13262c Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 13 Oct 2021 17:59:58 +0200 Subject: [PATCH 7/7] mkfifo is not available for Browser --- .../System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs | 2 +- .../System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 8e0bbdef48edf..bb94b18b3115e 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -208,7 +208,7 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na } [Fact] - [PlatformSpecific(TestPlatforms.AnyUnix)] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] public async Task ReadAllBytes_NonSeekableFileStream_InUnix() { string fifoPath = GetTestFilePath(); diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index e7b16782b5acc..be562f15ca953 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -221,7 +221,7 @@ static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream na } [Fact] - [PlatformSpecific(TestPlatforms.AnyUnix)] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] public async Task ReadAllBytesAsync_NonSeekableFileStream_InUnix() { string fifoPath = GetTestFilePath();