Skip to content
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
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Testably.Abstractions.Helpers;

namespace Testably.Abstractions.Testing.Helpers;
Expand Down Expand Up @@ -44,4 +45,16 @@ internal void CopyMetadataTo(IFileSystemExtensibility target)
}
}
}

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
{
if (_metadata.Count == 0)
{
return "[]";
}

return
$"[{string.Join(", ", _metadata.Select(x => $"{x.Key}: {x.Value}"))}]";
}
}
15 changes: 15 additions & 0 deletions Source/Testably.Abstractions.Testing/MockFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using Testably.Abstractions.Testing.FileSystem;
using Testably.Abstractions.Testing.Storage;

Expand Down Expand Up @@ -40,6 +42,15 @@ public sealed class MockFileSystem : IFileSystem
/// </summary>
internal IStorage Storage => _storage;

/// <summary>
/// The registered containers in the in-Memory <see cref="Storage" />.
/// </summary>
internal IReadOnlyList<IStorageContainer> Containers
=> _storage.Containers
.OrderBy(x => x.Key.FullPath)
.Select(x => x.Value)
.ToList();

private readonly DirectoryMock _directoryMock;
private readonly FileMock _fileMock;
private readonly PathMock _pathMock;
Expand Down Expand Up @@ -110,6 +121,10 @@ public IPath Path

#endregion

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
=> $"MockFileSystem (directories: {_storage.Containers.Count(x => x.Value.Type == FileSystemTypes.Directory)}, files: {_storage.Containers.Count(x => x.Value.Type == FileSystemTypes.File)})";

/// <summary>
/// Implements a custom access control (ACL) mechanism.
/// <para />
Expand Down
7 changes: 6 additions & 1 deletion Source/Testably.Abstractions.Testing/MockRandomSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Testably.Abstractions.RandomSystem;
using System;
using Testably.Abstractions.RandomSystem;
using Testably.Abstractions.Testing.RandomSystem;

namespace Testably.Abstractions.Testing;
Expand Down Expand Up @@ -46,4 +47,8 @@ public IRandomFactory Random
=> _randomFactoryMock;

#endregion

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
=> "MockRandomSystem";
}
4 changes: 4 additions & 0 deletions Source/Testably.Abstractions.Testing/MockTimeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ public ITimerFactory Timer

#endregion

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
=> $"MockTimeSystem (now: {DateTime.UtcNow}Z)";

/// <summary>
/// Specifies the <see cref="ITimerStrategy" /> to use when dealing with timers.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions Source/Testably.Abstractions.Testing/Storage/InMemoryContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ public void WriteBytes(byte[] bytes)

#endregion

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
{
if (Type == FileSystemTypes.Directory)
{
return $"{_location.FullPath}: Directory";
}

if (Type == FileSystemTypes.File)
{
return $"{_location.FullPath}: File ({_bytes.Length} bytes)";
}

return $"{_location.FullPath}: Unknown Container";
}

/// <summary>
/// Create a new directory on the <paramref name="location" />.
/// </summary>
Expand Down Expand Up @@ -318,6 +334,10 @@ public void Set(DateTime time, DateTimeKind kind)
}

#endregion

/// <inheritdoc cref="object.ToString()" />
public override string ToString()
=> _time.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ssZ");
}

private sealed class FileHandle : IStorageAccessHandle
Expand Down
62 changes: 31 additions & 31 deletions Source/Testably.Abstractions.Testing/Storage/InMemoryStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ namespace Testably.Abstractions.Testing.Storage;
/// </summary>
internal sealed class InMemoryStorage : IStorage
{
private readonly ConcurrentDictionary<IStorageLocation, IStorageContainer>
_containers = new();
internal readonly ConcurrentDictionary<IStorageLocation, IStorageContainer>
Containers = new();

private readonly ConcurrentDictionary<string, IStorageDrive> _drives =
new(StringComparer.OrdinalIgnoreCase);
Expand Down Expand Up @@ -45,7 +45,7 @@ public InMemoryStorage(MockFileSystem fileSystem)
{
ThrowIfParentDoesNotExist(destination, _ => ExceptionFactory.DirectoryNotFound());

if (!_containers.TryGetValue(source,
if (!Containers.TryGetValue(source,
out IStorageContainer? sourceContainer))
{
return null;
Expand All @@ -59,15 +59,15 @@ public InMemoryStorage(MockFileSystem fileSystem)
using (_ = sourceContainer.RequestAccess(FileAccess.ReadWrite, FileShare.None))
{
if (overwrite &&
_containers.TryRemove(destination,
Containers.TryRemove(destination,
out IStorageContainer? existingContainer))
{
existingContainer.ClearBytes();
}

IStorageContainer copiedContainer =
InMemoryContainer.NewFile(destination, _fileSystem);
if (_containers.TryAdd(destination, copiedContainer))
if (Containers.TryAdd(destination, copiedContainer))
{
copiedContainer.WriteBytes(sourceContainer.GetBytes().ToArray());
Execute.OnMac(
Expand Down Expand Up @@ -99,11 +99,11 @@ public InMemoryStorage(MockFileSystem fileSystem)
/// <inheritdoc cref="IStorage.DeleteContainer(IStorageLocation, bool)" />
public bool DeleteContainer(IStorageLocation location, bool recursive = false)
{
if (!_containers.TryGetValue(location, out IStorageContainer? container))
if (!Containers.TryGetValue(location, out IStorageContainer? container))
{
IStorageLocation? parentLocation = location.GetParent();
if (parentLocation != null &&
!_containers.TryGetValue(parentLocation, out _))
!Containers.TryGetValue(parentLocation, out _))
{
throw ExceptionFactory.DirectoryNotFound(parentLocation.FullPath);
}
Expand Down Expand Up @@ -140,7 +140,7 @@ public bool DeleteContainer(IStorageLocation location, bool recursive = false)
using (container.RequestAccess(FileAccess.Write, FileShare.ReadWrite,
deleteAccess: true))
{
if (_containers.TryRemove(location, out IStorageContainer? removed))
if (Containers.TryRemove(location, out IStorageContainer? removed))
{
removed.ClearBytes();
_fileSystem.ChangeHandler.NotifyCompletedChange(fileSystemChange);
Expand All @@ -160,7 +160,7 @@ public IEnumerable<IStorageLocation> EnumerateLocations(
EnumerationOptions? enumerationOptions = null)
{
ValidateExpression(searchPattern);
if (!_containers.ContainsKey(location))
if (!Containers.ContainsKey(location))
{
throw ExceptionFactory.DirectoryNotFound(location.FullPath);
}
Expand All @@ -177,7 +177,7 @@ public IEnumerable<IStorageLocation> EnumerateLocations(
fullPath += _fileSystem.Path.DirectorySeparatorChar;
}

foreach (KeyValuePair<IStorageLocation, IStorageContainer> item in _containers
foreach (KeyValuePair<IStorageLocation, IStorageContainer> item in Containers
.Where(x => x.Key.FullPath.StartsWith(fullPath,
InMemoryLocation.StringComparisonMode) &&
!x.Key.Equals(location)))
Expand Down Expand Up @@ -215,7 +215,7 @@ public IEnumerable<IStorageLocation> EnumerateLocations(
return null;
}

if (_containers.TryGetValue(location, out IStorageContainer? container))
if (Containers.TryGetValue(location, out IStorageContainer? container))
{
return container;
}
Expand Down Expand Up @@ -287,7 +287,7 @@ public IStorageContainer GetOrCreateContainer(
IFileSystemExtensibility? fileSystemExtensibility = null)
{
ChangeDescription? fileSystemChange = null;
IStorageContainer container = _containers.GetOrAdd(location,
IStorageContainer container = Containers.GetOrAdd(location,
loc =>
{
IStorageContainer container =
Expand All @@ -302,7 +302,7 @@ public IStorageContainer GetOrCreateContainer(
{
IStorageLocation? parentLocation = loc.GetParent();
if (parentLocation is { IsRooted: false } &&
!_containers.ContainsKey(parentLocation))
!Containers.ContainsKey(parentLocation))
{
throw ExceptionFactory.DirectoryNotFound(loc.FullPath);
}
Expand Down Expand Up @@ -359,13 +359,13 @@ public IStorageContainer GetOrCreateContainer(
() => ExceptionFactory.DirectoryNotFound(location.FullPath),
() => ExceptionFactory.FileNotFound(location.FullPath)));

if (!_containers.TryGetValue(source,
if (!Containers.TryGetValue(source,
out IStorageContainer? sourceContainer))
{
return null;
}

if (!_containers.TryGetValue(destination,
if (!Containers.TryGetValue(destination,
out IStorageContainer? destinationContainer))
{
return null;
Expand All @@ -383,22 +383,22 @@ public IStorageContainer GetOrCreateContainer(
using (_ = destinationContainer.RequestAccess(FileAccess.ReadWrite,
FileShare.None, ignoreMetadataErrors: ignoreMetadataErrors))
{
if (_containers.TryRemove(destination,
if (Containers.TryRemove(destination,
out IStorageContainer? existingDestinationContainer))
{
int destinationBytesLength =
existingDestinationContainer.GetBytes().Length;
destination.Drive?.ChangeUsedBytes(-1 * destinationBytesLength);
if (backup != null &&
_containers.TryAdd(backup, existingDestinationContainer))
Containers.TryAdd(backup, existingDestinationContainer))
{
Execute.OnWindowsIf(sourceContainer.Type == FileSystemTypes.File,
() => existingDestinationContainer.Attributes |=
FileAttributes.Archive);
backup.Drive?.ChangeUsedBytes(destinationBytesLength);
}

if (_containers.TryRemove(source,
if (Containers.TryRemove(source,
out IStorageContainer? existingSourceContainer))
{
int sourceBytesLength = existingSourceContainer.GetBytes().Length;
Expand All @@ -414,7 +414,7 @@ public IStorageContainer GetOrCreateContainer(
DateTimeKind.Utc),
DateTimeKind.Utc);
});
_containers.TryAdd(destination, existingSourceContainer);
Containers.TryAdd(destination, existingSourceContainer);
return destination;
}
}
Expand All @@ -429,13 +429,13 @@ public IStorageContainer GetOrCreateContainer(
public IStorageLocation? ResolveLinkTarget(IStorageLocation location,
bool returnFinalTarget = false)
{
if (_containers.TryGetValue(location,
if (Containers.TryGetValue(location,
out IStorageContainer? initialContainer) &&
initialContainer.LinkTarget != null)
{
IStorageLocation? nextLocation =
_fileSystem.Storage.GetLocation(initialContainer.LinkTarget);
if (_containers.TryGetValue(nextLocation,
if (Containers.TryGetValue(nextLocation,
out IStorageContainer? container))
{
if (returnFinalTarget)
Expand All @@ -462,14 +462,14 @@ public bool TryAddContainer(
{
IStorageLocation? parentLocation = location.GetParent();
if (parentLocation is { IsRooted: false } &&
!_containers.ContainsKey(parentLocation))
!Containers.ContainsKey(parentLocation))
{
throw ExceptionFactory.DirectoryNotFound(location.FullPath);
}

ChangeDescription? fileSystemChange = null;

container = _containers.GetOrAdd(
container = Containers.GetOrAdd(
location,
_ =>
{
Expand Down Expand Up @@ -535,7 +535,7 @@ private void CreateParents(MockFileSystem fileSystem, IStorageLocation location)
ChangeDescription? fileSystemChange = null;
IStorageLocation parentLocation =
_fileSystem.Storage.GetLocation(parentPath);
_ = _containers.AddOrUpdate(
_ = Containers.AddOrUpdate(
parentLocation,
loc =>
{
Expand Down Expand Up @@ -571,7 +571,7 @@ private void CreateParents(MockFileSystem fileSystem, IStorageLocation location)
FileSystemTypes? sourceType,
List<Rollback>? rollbacks = null)
{
if (!_containers.TryGetValue(source,
if (!Containers.TryGetValue(source,
out IStorageContainer? container))
{
return null;
Expand Down Expand Up @@ -615,16 +615,16 @@ private void CreateParents(MockFileSystem fileSystem, IStorageLocation location)
NotifyFilters.FileName,
destination,
source);
if (_containers.TryRemove(source, out IStorageContainer? sourceContainer))
if (Containers.TryRemove(source, out IStorageContainer? sourceContainer))
{
if (overwrite &&
_containers.TryRemove(destination,
Containers.TryRemove(destination,
out IStorageContainer? existingContainer))
{
existingContainer.ClearBytes();
}

if (_containers.TryAdd(destination, sourceContainer))
if (Containers.TryAdd(destination, sourceContainer))
{
int bytesLength = sourceContainer.GetBytes().Length;
source.Drive?.ChangeUsedBytes(-1 * bytesLength);
Expand All @@ -638,7 +638,7 @@ private void CreateParents(MockFileSystem fileSystem, IStorageLocation location)
return destination;
}

_containers.TryAdd(source, sourceContainer);
Containers.TryAdd(source, sourceContainer);
throw ExceptionFactory.CannotCreateFileWhenAlreadyExists(
sourceType == FileSystemTypes.Directory
? -2147024891
Expand All @@ -665,7 +665,7 @@ private void CreateParents(MockFileSystem fileSystem, IStorageLocation location)
}

nextLocation = _fileSystem.Storage.GetLocation(container.LinkTarget);
if (!_containers.TryGetValue(nextLocation,
if (!Containers.TryGetValue(nextLocation,
out IStorageContainer? nextContainer))
{
return nextLocation;
Expand All @@ -692,7 +692,7 @@ private void ThrowIfParentDoesNotExist(IStorageLocation location,
if (parentLocation != null &&
_fileSystem.Path.GetPathRoot(parentLocation.FullPath) !=
parentLocation.FullPath &&
!_containers.TryGetValue(parentLocation, out _))
!Containers.TryGetValue(parentLocation, out _))
{
throw exceptionCallback(parentLocation);
}
Expand Down