-
Notifications
You must be signed in to change notification settings - Fork 263
Add FileStreamFactory and support for mocking FileStreams #177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f6f1d1a
9444c03
3d50fcb
46ba25d
0e3d7ec
520db27
84574a8
9fb859d
2ed93bc
371288b
a6dc64d
d925c8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| using System.Security.AccessControl; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace System.IO.Abstractions | ||
| { | ||
| [Serializable] | ||
| internal sealed class FileStreamFactory : IFileStreamFactory | ||
| { | ||
| public Stream Create(string path, FileMode mode) | ||
| => new FileStream(path, mode); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access) | ||
| => new FileStream(path, mode, access); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share) | ||
| => new FileStream(path, mode, access, share); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) | ||
| => new FileStream(path, mode, access, share, bufferSize); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) | ||
| => new FileStream(path, mode, access, share, bufferSize, options); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) | ||
| => new FileStream(path, mode, access, share, bufferSize, useAsync); | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access) | ||
| => new FileStream(handle, access); | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize) | ||
| => new FileStream(handle, access, bufferSize); | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) | ||
| => new FileStream(handle, access, bufferSize, isAsync); | ||
|
|
||
| #if NET40 | ||
| public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity) | ||
| => new FileStream(path, mode, rights, share, bufferSize, options, fileSecurity); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) | ||
| => new FileStream(path, mode, rights, share, bufferSize, options); | ||
| #endif | ||
|
|
||
| #if NET40 || NETSTANDARD_20 | ||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access) | ||
| => new FileStream(handle, access); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle) | ||
| => new FileStream(handle, access, ownsHandle); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) | ||
| => new FileStream(handle, access, ownsHandle, bufferSize); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) | ||
| => new FileStream(handle, access, ownsHandle, bufferSize, isAsync); | ||
| #endif | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| using System.Security.AccessControl; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace System.IO.Abstractions | ||
| { | ||
| public interface IFileStreamFactory | ||
| { | ||
| Stream Create(string path, FileMode mode); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileAccess access); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileAccess access, FileShare share); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync); | ||
|
|
||
| Stream Create(SafeFileHandle handle, FileAccess access); | ||
|
|
||
| Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize); | ||
|
|
||
| Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync); | ||
|
|
||
| #if NET40 | ||
| Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity); | ||
|
|
||
| Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options); | ||
| #endif | ||
|
|
||
| #if NET40 || NETSTANDARD_20 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the NET40/NETSTANDARD check here? I don't see a mirroring check in the MockFileStreamFactory
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, because the “real” implementation doesn’t support these overloads on NS1.4. |
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| Stream Create(IntPtr handle, FileAccess access); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| Stream Create(IntPtr handle, FileAccess access, bool ownsHandle); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync); | ||
| #endif | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ public interface IFileSystem | |
| FileBase File { get; } | ||
| DirectoryBase Directory { get; } | ||
| IFileInfoFactory FileInfo { get; } | ||
| IFileStreamFactory FileStream { get; } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is my only concern. Since we're adding onto IFileSystem, it's a breaking change.. but is anyone really writing their own classes using IFileSystem?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, same goes for 07227bc... I also don't think this will be a big problem for people. Whenever we are done with the old issues/PRs we should again think about release strategy, versioning, issue tagging, etc...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear. I would merge this one and as a follow-up take care about our future strategy.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I would agree. It's probably an incredibly small subset of users it would impact. |
||
| PathBase Path { get; } | ||
| IDirectoryInfoFactory DirectoryInfo { get; } | ||
| IDriveInfoFactory DriveInfo { get; } | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| using System.Collections.Generic; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace System.IO.Abstractions.TestingHelpers.Tests | ||
| { | ||
| [TestFixture] | ||
| public class MockFileStreamFactoryTests | ||
| { | ||
| [Test] | ||
| [TestCase(FileMode.Create)] | ||
| [TestCase(FileMode.Append)] | ||
| public void MockFileStreamFactory_CreateForExistingFile_ShouldReturnStream(FileMode fileMode) | ||
| { | ||
| // Arrange | ||
| var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData> | ||
| { | ||
| { @"c:\existing.txt", MockFileData.NullObject } | ||
| }); | ||
|
|
||
| var fileStreamFactory = new MockFileStreamFactory(fileSystem); | ||
|
|
||
| // Act | ||
| var result = fileStreamFactory.Create(@"c:\existing.txt", fileMode); | ||
|
|
||
| // Assert | ||
| Assert.IsNotNull(result); | ||
| } | ||
|
|
||
| [Test] | ||
| [TestCase(FileMode.Create)] | ||
| [TestCase(FileMode.Append)] | ||
| public void MockFileStreamFactory_CreateForNonExistingFile_ShouldReturnStream(FileMode fileMode) | ||
| { | ||
| // Arrange | ||
| var fileSystem = new MockFileSystem(); | ||
| var fileStreamFactory = new MockFileStreamFactory(fileSystem); | ||
|
|
||
| // Act | ||
| var result = fileStreamFactory.Create(@"c:\not_existing.txt", fileMode); | ||
|
|
||
| // Assert | ||
| Assert.IsNotNull(result); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| using System.Security.AccessControl; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace System.IO.Abstractions.TestingHelpers | ||
| { | ||
| [Serializable] | ||
| public class MockFileStreamFactory : IFileStreamFactory | ||
| { | ||
| private readonly IMockFileDataAccessor mockFileSystem; | ||
|
|
||
| public MockFileStreamFactory(IMockFileDataAccessor mockFileSystem) | ||
| => this.mockFileSystem = mockFileSystem ?? throw new ArgumentNullException(nameof(mockFileSystem)); | ||
|
|
||
| public Stream Create(string path, FileMode mode) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode, access)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode, access)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode, access)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode, access)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode, access)); | ||
|
|
||
| #if NET40 | ||
| public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode)); | ||
|
|
||
| public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) | ||
| => new MockFileStream(mockFileSystem, path, GetStreamType(mode)); | ||
| #endif | ||
|
|
||
| #if NET40 || NETSTANDARD_20 | ||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| [Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] | ||
| public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
| #endif | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) | ||
| => new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access)); | ||
|
|
||
| private static MockFileStream.StreamType GetStreamType(FileMode mode, FileAccess access = FileAccess.ReadWrite) | ||
| { | ||
| if (access == FileAccess.Read) | ||
| { | ||
| return MockFileStream.StreamType.READ; | ||
| } | ||
| else if (mode == FileMode.Append) | ||
| { | ||
| return MockFileStream.StreamType.APPEND; | ||
| } | ||
| else | ||
| { | ||
| return MockFileStream.StreamType.WRITE; | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a nit, but thought this was interesting.
https://ericlippert.com/2014/09/15/internal-or-public/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 That's a good read, thanks! I also prefer
publicin these cases, but I could never provide non-subjective reasons for that