Skip to content
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

feat: add testability for DriveInfo #1094

Merged
merged 3 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ public interface IMockFileDataAccessor : IFileSystem
/// <returns>The file. <see langword="null"/> if the file does not exist.</returns>
MockFileData GetFile(string path);

/// <summary>
/// Gets a drive.
/// </summary>
/// <param name="name">The name of the drive to get.</param>
/// <returns>The drive. <see langword="null"/> if the drive does not exist.</returns>
MockDriveData GetDrive(string name);

/// <summary>
/// </summary>
void AddFile(string path, MockFileData mockFile);
Expand All @@ -31,6 +38,10 @@ public interface IMockFileDataAccessor : IFileSystem
/// </summary>
void AddDirectory(string path);

/// <summary>
/// </summary>
void AddDrive(string name, MockDriveData mockDrive);

/// <summary>
/// </summary>
void AddFileFromEmbeddedResource(string path, Assembly resourceAssembly, string embeddedResourcePath);
Expand Down Expand Up @@ -74,6 +85,11 @@ public interface IMockFileDataAccessor : IFileSystem
/// </summary>
IEnumerable<string> AllDirectories { get; }

/// <summary>
/// Gets the names of all drives.
/// </summary>
IEnumerable<string> AllDrives { get; }

/// <summary>
/// Gets a helper for string operations.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

namespace System.IO.Abstractions.TestingHelpers
{
/// <summary>
/// The class represents the associated data of a drive.
/// </summary>
#if FEATURE_SERIALIZABLE
[Serializable]
#endif
public class MockDriveData
{
/// <summary>
/// Initializes a new instance of the <see cref="MockDriveData"/> class.
/// </summary>
public MockDriveData()
{
IsReady = true;
}

/// <summary>
/// Initializes a new instance of the <see cref="MockDriveData"/> class by copying the given <see cref="MockDriveData"/>.
/// </summary>
/// <param name="template">The template instance.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="template"/> is <see langword="null"/>.</exception>
public MockDriveData(MockDriveData template)
{
if (template == null)
{
throw new ArgumentNullException(nameof(template));
}

AvailableFreeSpace = template.AvailableFreeSpace;
DriveFormat = template.DriveFormat;
DriveType = template.DriveType;
IsReady = template.IsReady;
TotalFreeSpace = template.TotalFreeSpace;
TotalSize = template.TotalSize;
VolumeLabel = template.VolumeLabel;
}

/// <summary>
/// Gets or sets the amount of available free space of the <see cref="MockDriveData"/>, in bytes.
/// </summary>
public long AvailableFreeSpace { get; set; }

/// <summary>
/// Gets or sets the name of the file system of the <see cref="MockDriveData"/>, such as NTFS or FAT32.
/// </summary>
public string DriveFormat { get; set; }

/// <summary>
/// Gets or sets the drive type of the <see cref="MockDriveData"/>, such as CD-ROM, removable, network, or fixed.
/// </summary>
public DriveType DriveType { get; set; }

/// <summary>
/// Gets or sets the value that indicates whether the <see cref="MockDriveData"/> is ready.
/// </summary>
public bool IsReady { get; set; }

/// <summary>
/// Gets or sets the total amount of free space available on the <see cref="MockDriveData"/>, in bytes.
/// </summary>
public long TotalFreeSpace { get; set; }

/// <summary>
/// Gets or sets the total size of storage space on the <see cref="MockDriveData"/>, in bytes.
/// </summary>
public long TotalSize { get; set; }

/// <summary>
/// Gets or sets the volume label of the <see cref="MockDriveData"/>.
/// </summary>
public string VolumeLabel { get; set; }
}
}
109 changes: 76 additions & 33 deletions src/TestableIO.System.IO.Abstractions.TestingHelpers/MockDriveInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,60 @@
public class MockDriveInfo : DriveInfoBase
{
private readonly IMockFileDataAccessor mockFileDataAccessor;
private readonly string name;

/// <inheritdoc />
public MockDriveInfo(IMockFileDataAccessor mockFileDataAccessor, string name) : base(mockFileDataAccessor?.FileSystem)
{
this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
this.name = mockFileDataAccessor.PathVerifier.NormalizeDriveName(name);
}

if (name == null)
/// <inheritdoc />
public override long AvailableFreeSpace
{
get
{
throw new ArgumentNullException(nameof(name));
var mockDriveData = GetMockDriveData();
return mockDriveData.AvailableFreeSpace;
}
}

const string DRIVE_SEPARATOR = @":\";

if (name.Length == 1
|| (name.Length == 2 && name[1] == ':')
|| (name.Length == 3 && mockFileDataAccessor.StringOperations.EndsWith(name, DRIVE_SEPARATOR)))
/// <inheritdoc />
public override string DriveFormat
{
get
{
name = name[0] + DRIVE_SEPARATOR;
var mockDriveData = GetMockDriveData();
return mockDriveData.DriveFormat;
}
else
{
mockFileDataAccessor.PathVerifier.CheckInvalidPathChars(name);
name = mockFileDataAccessor.Path.GetPathRoot(name);
}

if (string.IsNullOrEmpty(name) || mockFileDataAccessor.StringOperations.StartsWith(name, @"\\"))
{
throw new ArgumentException(
@"Object must be a root directory (""C:\"") or a drive letter (""C"").");
}
/// <inheritdoc />
public override DriveType DriveType
{
get
{
var mockDriveData = GetMockDriveData();
return mockDriveData.DriveType;
}

Name = name;
IsReady = true;
}

/// <inheritdoc />
public new long AvailableFreeSpace { get; set; }
/// <inheritdoc />
public new string DriveFormat { get; set; }
/// <inheritdoc />
public new DriveType DriveType { get; set; }
/// <inheritdoc />
public new bool IsReady { get; protected set; }
public override bool IsReady
{
get
{
var mockDriveData = GetMockDriveData();
return mockDriveData.IsReady;
}
}

/// <inheritdoc />
public override string Name { get; protected set; }
public override string Name
{
get { return name; }
}

/// <inheritdoc />
public override IDirectoryInfo RootDirectory
Expand All @@ -63,16 +72,50 @@ public override IDirectoryInfo RootDirectory
}

/// <inheritdoc />
public override string ToString()
public override long TotalFreeSpace
{
return Name;
get
{
var mockDriveData = GetMockDriveData();
return mockDriveData.TotalFreeSpace;
}
}

/// <inheritdoc />
public new long TotalFreeSpace { get; protected set; }
public override long TotalSize
{
get
{
var mockDriveData = GetMockDriveData();
return mockDriveData.TotalSize;
}
}

/// <inheritdoc />
public new long TotalSize { get; protected set; }
public override string VolumeLabel
{
get
{
var mockDriveData = GetMockDriveData();
return mockDriveData.VolumeLabel;
}
set
{
var mockDriveData = GetMockDriveData();
mockDriveData.VolumeLabel = value;
}
}

/// <inheritdoc />
public override string VolumeLabel { get; set; }
public override string ToString()
{
return Name;
}

private MockDriveData GetMockDriveData()
{
return mockFileDataAccessor.GetDrive(name)
?? throw CommonExceptions.FileNotFound(name);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,8 @@ public IFileSystem FileSystem
/// <inheritdoc />
public IDriveInfo[] GetDrives()
{
var driveLetters = new HashSet<string>(new DriveEqualityComparer(mockFileSystem));
foreach (var path in mockFileSystem.AllPaths)
{
var pathRoot = mockFileSystem.Path.GetPathRoot(path);
driveLetters.Add(pathRoot);
}

var result = new List<DriveInfoBase>();
foreach (string driveLetter in driveLetters)
foreach (string driveLetter in mockFileSystem.AllDrives)
{
try
{
Expand Down
Loading
Loading