diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamOptions.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamOptions.cs index d078deb07e55ef..9be492d21bdbf9 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamOptions.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamOptions.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; using System.Linq; +using System.Text; using Xunit; namespace System.IO.Tests @@ -134,5 +134,59 @@ public void BufferSize() Assert.Throws(() => new FileStreamOptions { BufferSize = -1 }); } + + [Theory] + [InlineData(FileMode.Create, FileAccess.Write, FileOptions.None)] + [InlineData(FileMode.Create, FileAccess.Write, FileOptions.Asynchronous)] + [InlineData(FileMode.Open, FileAccess.Read, FileOptions.None)] + [InlineData(FileMode.Open, FileAccess.Read, FileOptions.Asynchronous)] + [InlineData(FileMode.Create, FileAccess.ReadWrite, FileOptions.None)] + [InlineData(FileMode.Create, FileAccess.ReadWrite, FileOptions.Asynchronous)] + public void SettingsArePropagated(FileMode mode, FileAccess access, FileOptions fileOptions) + { + string filePath = GetTestFilePath(); + if (mode == FileMode.Open) + { + File.Create(filePath).Dispose(); + } + + bool canRead = (access & FileAccess.Read) != 0; + bool canWrite = (access & FileAccess.Write) != 0; + bool isAsync = (fileOptions & FileOptions.Asynchronous) != 0; + + var options = new FileStreamOptions + { + Mode = mode, + Access = access, + Options = fileOptions + }; + + Validate(new FileStream(filePath, options), filePath, isAsync, canRead, canWrite); + Validate(File.Open(filePath, options), filePath, isAsync, canRead, canWrite); + Validate(new FileInfo(filePath).Open(options), filePath, isAsync, canRead, canWrite); + + if (canWrite) + { + Validate((FileStream)new StreamWriter(filePath, options).BaseStream, filePath, isAsync, canRead, canWrite); + Validate((FileStream)new StreamWriter(filePath, Encoding.UTF8, options).BaseStream, filePath, isAsync, canRead, canWrite); + } + + if (canRead) + { + Validate((FileStream)new StreamReader(filePath, options).BaseStream, filePath, isAsync, canRead, canWrite); + Validate((FileStream)new StreamReader(filePath, Encoding.UTF8, false, options).BaseStream, filePath, isAsync, canRead, canWrite); + } + + static void Validate(FileStream fs, string expectedPath, bool expectedAsync, bool expectedCanRead, bool expectedCanWrite) + { + using (fs) + { + Assert.Equal(expectedPath, fs.Name); + Assert.Equal(expectedAsync, fs.IsAsync); + Assert.Equal(expectedCanRead, fs.CanRead); + Assert.Equal(expectedCanWrite, fs.CanWrite); + } + } + } } } diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs index d4c7ac4ad847f1..2e19dd283ebbb1 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs @@ -47,6 +47,16 @@ public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() AssertExtensions.Throws("bufferSize", () => new StreamReader("path", Encoding.UTF8, true, 0)); } + [Fact] + public static void LackOfReadAccess_ThrowsArgumentException() + { + var noReadAccess = new FileStreamOptions { Access = FileAccess.Write }; + + AssertExtensions.Throws("options", () => new StreamReader("path", noReadAccess)); + AssertExtensions.Throws("options", () => new StreamReader("path", Encoding.UTF8, false, noReadAccess)); + AssertExtensions.Throws("options", () => new StreamReader("path", Encoding.UTF8, true, noReadAccess)); + } + [Theory] [InlineData(true)] [InlineData(false)] diff --git a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs index 95041cd56503a6..841ff591aeff23 100644 --- a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -46,6 +46,15 @@ public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() AssertExtensions.Throws("bufferSize", () => new StreamWriter("path", true, Encoding.UTF8, 0)); } + [Fact] + public static void LackOfWriteAccess_ThrowsArgumentException() + { + var readOptions = new FileStreamOptions { Access = FileAccess.Read }; + + AssertExtensions.Throws("options", () => new StreamWriter("path", readOptions)); + AssertExtensions.Throws("options", () => new StreamWriter("path", Encoding.UTF8, readOptions)); + } + [Fact] public static void CreateStreamWriter() { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index af35711a682d08..3b3e03a806ff54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -211,8 +211,15 @@ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteO private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) { ValidateArgs(path, encoding); - if (options == null) + + if (options is null) + { throw new ArgumentNullException(nameof(options)); + } + if ((options.Access & FileAccess.Read) == 0) + { + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(options)); + } return new FileStream(path, options); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index 96ac62fd51dd4e..7ba362604d01c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -167,8 +167,15 @@ public StreamWriter(string path, Encoding encoding, FileStreamOptions options) private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) { ValidateArgs(path, encoding); - if (options == null) + + if (options is null) + { throw new ArgumentNullException(nameof(options)); + } + if ((options.Access & FileAccess.Write) == 0) + { + throw new ArgumentException(SR.Argument_StreamNotWritable, nameof(options)); + } return new FileStream(path, options); }