diff --git a/.editorconfig b/.editorconfig
index bfb9d50..b20343b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -110,7 +110,7 @@ dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggest
#Style - Modifier preferences
#when this rule is set to a list of modifiers, prefer the specified ordering.
-csharp_preferred_modifier_order = public,protected,private,internal,static,async,abstract,virtual,readonly,sealed,override:suggestion
+csharp_preferred_modifier_order = public, protected, private, internal, static, async, abstract, virtual, readonly, sealed, override:suggestion
#Style - Pattern matching
@@ -167,31 +167,31 @@ dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.interface.required_modifiers =
+dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.types.required_modifiers =
+dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.non_field_members.required_modifiers =
+dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.begins_with_i.required_prefix = I
-dotnet_naming_style.begins_with_i.required_suffix =
-dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
-dotnet_naming_style.pascal_case.required_prefix =
-dotnet_naming_style.pascal_case.required_suffix =
-dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
-dotnet_naming_style.pascal_case.required_prefix =
-dotnet_naming_style.pascal_case.required_suffix =
-dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
diff --git a/README.md b/README.md
index 2b31fd7..0476db9 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,11 @@
A virtual file system implementation in modern C#.
-When writing applications in .NET, you often need to write or read the contents of a file. .NET provides `System.IO` namespace dedicated to this purpose. But how do we deal with the filesystem when testing our code?
-
-"Virtual File System" is an attempt to solve this problem. Currently, this library is at an early stage of development. If you need additional functionality, I invite you to open an issue to discuss it.
+When writing applications in .NET, you often need to write or read the contents of a file. .NET provides `System.IO`
+namespace dedicated to this purpose. But how do we deal with the filesystem when testing our code?
+"Virtual File System" is an attempt to solve this problem. Currently, this library is at an early stage of development.
+If you need additional functionality, I invite you to open an issue to discuss it.
## Badges
@@ -16,7 +17,6 @@ _Social buttons_
[![stars - VirtualFileSystem](https://img.shields.io/github/stars/Atypical-Consulting/VirtualFileSystem?style=social)](https://github.com/Atypical-Consulting/VirtualFileSystem)
[![forks - VirtualFileSystem](https://img.shields.io/github/forks/Atypical-Consulting/VirtualFileSystem?style=social)](https://github.com/Atypical-Consulting/VirtualFileSystem)
-
_Repo metadata_
[![GitHub tag](https://img.shields.io/github/tag/Atypical-Consulting/VirtualFileSystem?include_prereleases=&sort=semver&color=blue)](https://github.com/Atypical-Consulting/VirtualFileSystem/releases/)
@@ -30,21 +30,24 @@ _Call-to-Action buttons_
[![View site - GH Pages](https://img.shields.io/badge/View_site-GH_Pages-2ea44f?style=for-the-badge)](https://atypical-consulting.github.io/VirtualFileSystem/)
[![view - Documentation](https://img.shields.io/badge/view-Documentation-blue?style=for-the-badge)](/docs/ "Go to project documentation")
-
## What is a virtual file system and why should I use it?
-A virtual file system is a data structure that represents a file system in memory. It is used to simulate a file system on a computer. It is useful for testing purposes, for example, when you want to test a file system without actually creating files on the hard drive.
+A virtual file system is a data structure that represents a file system in memory. It is used to simulate a file system
+on a computer. It is useful for testing purposes, for example, when you want to test a file system without actually
+creating files on the hard drive.
## We use the lastest C# features
-This library targets .NET 7.0 and uses the latest C# features. It is written in C# 11.0 and uses the new `init` properties, `record` types, `switch` expressions, `using` declarations, and more.
-
-I invite you to read the [C# 11.0 documentation](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11) to learn more about these features.
+This library targets .NET 7.0 and uses the latest C# features. It is written in C# 11.0 and uses the new `init`
+properties, `record` types, `switch` expressions, `using` declarations, and more.
+I invite you to read the [C# 11.0 documentation](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11) to
+learn more about these features.
## License
This project is licensed under the terms of the BSD-3-Clause license.
If you use this library in your project, please consider adding a link to this repository in your project's README.
-This project is maintained by [Atypical Consulting](https://www.atypical.consulting/). If you need help with this project, please contact us from this repository by opening an issue.
+This project is maintained by [Atypical Consulting](https://www.atypical.consulting/). If you need help with this
+project, please contact us from this repository by opening an issue.
diff --git a/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSNode.cs b/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSNode.cs
index c202669..de7877c 100644
--- a/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSNode.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSNode.cs
@@ -1,49 +1,49 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Abstractions;
-
-///
-/// Represents a node in a virtual file system.
-/// A node can be a file or a directory.
-///
-public abstract record VFSNode
- : IVirtualFileSystemNode
-{
- ///
- /// Initializes a new instance of the class.
- /// This constructor is used by derived classes.
- ///
- /// The path of the node.
- protected VFSNode(VFSPath path)
- {
- ArgumentNullException.ThrowIfNull(path);
-
- // set timestamps
- var now = DateTime.UtcNow;
- CreationTime = now;
- LastAccessTime = now;
- LastWriteTime = now;
- }
-
- ///
- public abstract VFSPath Path { get; }
-
- ///
- public DateTimeOffset CreationTime { get; }
-
- ///
- public DateTimeOffset LastAccessTime { get; }
-
- ///
- public DateTimeOffset LastWriteTime { get; }
-
- ///
- public abstract bool IsDirectory { get; }
-
- ///
- public abstract bool IsFile { get; }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Abstractions;
+
+///
+/// Represents a node in a virtual file system.
+/// A node can be a file or a directory.
+///
+public abstract record VFSNode
+ : IVirtualFileSystemNode
+{
+ ///
+ /// Initializes a new instance of the class.
+ /// This constructor is used by derived classes.
+ ///
+ /// The path of the node.
+ protected VFSNode(VFSPath path)
+ {
+ ArgumentNullException.ThrowIfNull(path);
+
+ // set timestamps
+ var now = DateTime.UtcNow;
+ CreationTime = now;
+ LastAccessTime = now;
+ LastWriteTime = now;
+ }
+
+ ///
+ public abstract VFSPath Path { get; }
+
+ ///
+ public DateTimeOffset CreationTime { get; }
+
+ ///
+ public DateTimeOffset LastAccessTime { get; }
+
+ ///
+ public DateTimeOffset LastWriteTime { get; }
+
+ ///
+ public abstract bool IsDirectory { get; }
+
+ ///
+ public abstract bool IsFile { get; }
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSPath.cs b/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSPath.cs
index 223988f..ceddade 100644
--- a/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSPath.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Abstractions/VFSPath.cs
@@ -1,194 +1,187 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Abstractions;
-
-///
-/// Represents a file system entry (file or directory) in the virtual file system.
-///
-public abstract record VFSPath
-{
- ///
- /// Regex pattern for matching a valid file system path.
- ///
- private const string VFSPathRegexPattern =
- @$"^{ROOT_PATH}(?([a-zA-Z0-9_\-\.]+{DIRECTORY_SEPARATOR})*[a-zA-Z0-9_\-\.]+)$";
-
- ///
- /// Regex for matching a valid file system path.
- ///
- public static readonly Regex VFSPathRegex = new(VFSPathRegexPattern, RegexOptions.Compiled);
-
- ///
- /// Creates a new instance of .
- ///
- /// The path to the file system entry.
- /// Thrown when the path is null.
- /// Thrown when the path is invalid.
- public VFSPath(string path)
- {
- ArgumentNullException.ThrowIfNull(path);
-
- var vfsPath = CleanVFSPathInput(path);
-
- if (vfsPath == ROOT_PATH)
- {
- Value = vfsPath;
- Parent = null;
- return;
- }
-
- if (!VFSPathRegex.IsMatch(vfsPath))
- throw new ArgumentException($"The path '{path}' is invalid.", nameof(path));
-
- if (vfsPath.Contains($".{DIRECTORY_SEPARATOR}") || vfsPath.Contains($"{DIRECTORY_SEPARATOR}."))
- throw new ArgumentException($"The path '{path}' contains relative path segments.", nameof(path));
-
- Value = vfsPath;
-
- // set parent path
- var lastIndexOfParentPath = vfsPath.LastIndexOf(DIRECTORY_SEPARATOR, StringComparison.Ordinal);
- var parentPath = vfsPath[..lastIndexOfParentPath] + DIRECTORY_SEPARATOR;
- Parent = new VFSDirectoryPath(parentPath);
- }
-
- ///
- /// Gets the path of the file system entry with the VFS prefix.
- ///
- public string Value { get; }
-
- ///
- /// Gets the path of the parent directory.
- ///
- public VFSDirectoryPath? Parent { get; }
-
- ///
- /// Indicates whether the path has a parent directory.
- ///
- public bool HasParent
- => Parent != null;
-
- ///
- /// Gets a value indicating whether the directory is the root directory.
- ///
- ///
- /// if the directory is the root directory; otherwise, .
- ///
- public bool IsRoot
- => Value == ROOT_PATH;
-
- ///
- /// Gets the depth of the file system entry.
- /// The root directory has a depth of 0.
- /// The depth of a file is the depth of its parent directory plus one.
- /// The depth of a directory is the depth of its parent directory plus one.
- ///
- public int Depth {
- get
- {
- if (IsRoot)
- return 0;
-
- var depth = 0;
- var path = this;
- while (path!.Value != ROOT_PATH)
- {
- path = path.Parent;
- depth++;
- }
-
- return depth;
- }
- }
-
- ///
- /// Gets the name of the file system entry.
- /// The name of the root directory is .
- /// The name of a file is the name of the file with its extension.
- ///
- public string Name {
- get
- {
- if (IsRoot)
- return ROOT_PATH;
-
- var lastIndexOfName = Value.LastIndexOf(DIRECTORY_SEPARATOR, StringComparison.Ordinal);
- return Value[(lastIndexOfName + 1)..];
- }
- }
-
- ///
- /// Cleans the input path.
- ///
- /// The path to clean.
- /// The cleaned path.
- private string CleanVFSPathInput(string path)
- {
- // clean up the path
- var cleanPath = path.Trim();
-
- // if is root path, return it
- if (cleanPath is ROOT_PATH or "")
- return cleanPath;
-
- // clean up the path - remove leading and trailing slashes
- cleanPath = cleanPath.TrimStart('/');
- cleanPath = cleanPath.TrimEnd('/');
-
- // if path does not start with the root path, add it
- if (!cleanPath.StartsWith(ROOT_PATH))
- cleanPath = $"{ROOT_PATH}{cleanPath}";
-
- return cleanPath;
- }
-
- ///
- /// Gets the absolute path of the parent directory with depth .
- /// The root directory has a depth of 0.
- /// The depth of a file is the depth of its parent directory plus one.
- /// The depth of a directory is the depth of its parent directory plus one.
- ///
- /// The depth of the parent directory from the root directory.
- /// The absolute path of the parent directory with depth .
- /// Thrown when the depth is negative.
- public VFSPath GetAbsoluteParentPath(int depthFromRoot)
- {
- if (depthFromRoot < 0)
- throw new ArgumentOutOfRangeException(nameof(depthFromRoot), "The depth from root must be greater than or equal to 0.");
-
- if (IsRoot)
- return this;
-
- var path = this;
- while (path!.Depth > depthFromRoot)
- {
- path = path.Parent;
- }
-
- return path;
- }
-
- ///
- /// Indicates whether the current object is equal to another object of the same type.
- ///
- /// An object to compare with this object.
- /// A value that indicates whether the current object is equal to the parameter.
- public virtual bool Equals(VFSPath? other)
- {
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
- return Value == other.Value;
- }
-
- ///
- /// Serves as the default hash function.
- ///
- /// A hash code for the current object.
- public override int GetHashCode()
- {
- return Value.GetHashCode();
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Abstractions;
+
+///
+/// Represents a file system entry (file or directory) in the virtual file system.
+///
+public abstract record VFSPath
+{
+ ///
+ /// Regex pattern for matching a valid file system path.
+ ///
+ private const string VFSPathRegexPattern =
+ @$"^{ROOT_PATH}(?([a-zA-Z0-9_\-\.]+{DIRECTORY_SEPARATOR})*[a-zA-Z0-9_\-\.]+)$";
+
+ ///
+ /// Regex for matching a valid file system path.
+ ///
+ public static readonly Regex VFSPathRegex = new(VFSPathRegexPattern, RegexOptions.Compiled);
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The path to the file system entry.
+ /// Thrown when the path is null.
+ /// Thrown when the path is invalid.
+ public VFSPath(string path)
+ {
+ ArgumentNullException.ThrowIfNull(path);
+
+ var vfsPath = CleanVFSPathInput(path);
+
+ if (vfsPath == ROOT_PATH)
+ {
+ Value = vfsPath;
+ Parent = null;
+ return;
+ }
+
+ if (!VFSPathRegex.IsMatch(vfsPath))
+ throw new ArgumentException($"The path '{path}' is invalid.", nameof(path));
+
+ if (vfsPath.Contains($".{DIRECTORY_SEPARATOR}") || vfsPath.Contains($"{DIRECTORY_SEPARATOR}."))
+ throw new ArgumentException($"The path '{path}' contains relative path segments.", nameof(path));
+
+ Value = vfsPath;
+
+ // set parent path
+ var lastIndexOfParentPath = vfsPath.LastIndexOf(DIRECTORY_SEPARATOR, StringComparison.Ordinal);
+ var parentPath = vfsPath[..lastIndexOfParentPath] + DIRECTORY_SEPARATOR;
+ Parent = new VFSDirectoryPath(parentPath);
+ }
+
+ ///
+ /// Gets the path of the file system entry with the VFS prefix.
+ ///
+ public string Value { get; }
+
+ ///
+ /// Gets the path of the parent directory.
+ ///
+ public VFSDirectoryPath? Parent { get; }
+
+ ///
+ /// Indicates whether the path has a parent directory.
+ ///
+ public bool HasParent
+ => Parent != null;
+
+ ///
+ /// Gets a value indicating whether the directory is the root directory.
+ ///
+ ///
+ /// if the directory is the root directory; otherwise, .
+ ///
+ public bool IsRoot
+ => Value == ROOT_PATH;
+
+ ///
+ /// Gets the depth of the file system entry.
+ /// The root directory has a depth of 0.
+ /// The depth of a file is the depth of its parent directory plus one.
+ /// The depth of a directory is the depth of its parent directory plus one.
+ ///
+ public int Depth {
+ get {
+ if (IsRoot)
+ return 0;
+
+ var depth = 0;
+ var path = this;
+ while (path!.Value != ROOT_PATH)
+ {
+ path = path.Parent;
+ depth++;
+ }
+
+ return depth;
+ }
+ }
+
+ ///
+ /// Gets the name of the file system entry.
+ /// The name of the root directory is .
+ /// The name of a file is the name of the file with its extension.
+ ///
+ public string Name {
+ get {
+ if (IsRoot)
+ return ROOT_PATH;
+
+ var lastIndexOfName = Value.LastIndexOf(DIRECTORY_SEPARATOR, StringComparison.Ordinal);
+ return Value[(lastIndexOfName + 1)..];
+ }
+ }
+
+ ///
+ /// Indicates whether the current object is equal to another object of the same type.
+ ///
+ /// An object to compare with this object.
+ /// A value that indicates whether the current object is equal to the parameter.
+ public virtual bool Equals(VFSPath? other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Value == other.Value;
+ }
+
+ ///
+ /// Cleans the input path.
+ ///
+ /// The path to clean.
+ /// The cleaned path.
+ private string CleanVFSPathInput(string path)
+ {
+ // clean up the path
+ var cleanPath = path.Trim();
+
+ // if is root path, return it
+ if (cleanPath is ROOT_PATH or "")
+ return cleanPath;
+
+ // clean up the path - remove leading and trailing slashes
+ cleanPath = cleanPath.TrimStart('/');
+ cleanPath = cleanPath.TrimEnd('/');
+
+ // if path does not start with the root path, add it
+ if (!cleanPath.StartsWith(ROOT_PATH))
+ cleanPath = $"{ROOT_PATH}{cleanPath}";
+
+ return cleanPath;
+ }
+
+ ///
+ /// Gets the absolute path of the parent directory with depth .
+ /// The root directory has a depth of 0.
+ /// The depth of a file is the depth of its parent directory plus one.
+ /// The depth of a directory is the depth of its parent directory plus one.
+ ///
+ /// The depth of the parent directory from the root directory.
+ /// The absolute path of the parent directory with depth .
+ /// Thrown when the depth is negative.
+ public VFSPath GetAbsoluteParentPath(int depthFromRoot)
+ {
+ if (depthFromRoot < 0)
+ throw new ArgumentOutOfRangeException(nameof(depthFromRoot),
+ "The depth from root must be greater than or equal to 0.");
+
+ if (IsRoot)
+ return this;
+
+ var path = this;
+ while (path!.Depth > depthFromRoot) path = path.Parent;
+
+ return path;
+ }
+
+ ///
+ /// Serves as the default hash function.
+ ///
+ /// A hash code for the current object.
+ public override int GetHashCode() => Value.GetHashCode();
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Atypical.VirtualFileSystem.Core.csproj b/src/Atypical.VirtualFileSystem.Core/Atypical.VirtualFileSystem.Core.csproj
index 9486bf8..f75d44d 100644
--- a/src/Atypical.VirtualFileSystem.Core/Atypical.VirtualFileSystem.Core.csproj
+++ b/src/Atypical.VirtualFileSystem.Core/Atypical.VirtualFileSystem.Core.csproj
@@ -12,11 +12,11 @@
-
+
-
+
Atypical.VirtualFileSystem
@@ -39,7 +39,7 @@
- Initial release
-
+
diff --git a/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystem.cs b/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystem.cs
index 904ecd6..e7f3a0e 100644
--- a/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystem.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystem.cs
@@ -1,220 +1,220 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Contracts;
-
-///
-/// Represents a virtual file system.
-/// This is the main entry point for all operations on the file system.
-/// You can get an instance of this interface by calling .
-///
-public interface IVirtualFileSystem
-{
- ///
- /// Gets the root directory of the file system.
- /// This is the entry point for all operations on the file system.
- ///
- IRootNode Root { get; }
-
- ///
- /// Gets the file index of the file system.
- /// Basically, this is a dictionary that maps file paths to file nodes.
- /// This is useful for quickly finding a file node by its path.
- ///
- VFSIndex Index { get; }
-
- ///
- /// Indicates whether the file system is empty.
- /// This is the case if the root directory is empty.
- ///
- bool IsEmpty { get; }
-
- ///
- /// Gets a directory node by its path.
- /// The path must be absolute.
- ///
- /// The path of the directory node.
- /// The directory node.
- IDirectoryNode GetDirectory(VFSDirectoryPath directoryPath);
-
- ///
- /// Gets a file node by its path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file node.
- IDirectoryNode GetDirectory(string directoryPath);
-
- ///
- /// Try to get a directory node by its path.
- /// The path must be absolute.
- /// If the directory node does not exist, this method returns false
- /// and is set to null.
- ///
- /// The path of the directory node.
- /// The directory node.
- /// true if the directory node exists; otherwise, false.
- bool TryGetDirectory(VFSDirectoryPath directoryPath, out IDirectoryNode? directory);
-
- ///
- /// Try to get a directory node by its path.
- /// The path must be absolute.
- /// If the directory node does not exist, this method returns false
- /// and is set to null.
- ///
- /// The path of the directory node.
- /// The directory node.
- /// true if the directory node exists; otherwise, false.
- bool TryGetDirectory(string directoryPath, out IDirectoryNode? directory);
-
- ///
- /// Creates a directory node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the directory node.
- /// The file system.
- IVirtualFileSystem CreateDirectory(VFSDirectoryPath directoryPath);
-
- ///
- /// Creates a directory node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the directory node.
- /// The file system.
- IVirtualFileSystem CreateDirectory(string directoryPath);
-
- ///
- /// Deletes a directory node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the directory node.
- /// The file system.
- IVirtualFileSystem DeleteDirectory(VFSDirectoryPath directoryPath);
-
- ///
- /// Deletes a directory node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the directory node.
- /// The file system.
- IVirtualFileSystem DeleteDirectory(string directoryPath);
-
- ///
- /// Finds all directory nodes.
- ///
- /// The directory nodes.
- IEnumerable FindDirectories();
-
- ///
- /// Finds all directory nodes that match the specified regular expression.
- /// The regular expression must be relative to the root directory.
- ///
- /// The regular expression pattern.
- /// The directory nodes.
- IEnumerable FindDirectories(Regex regexPattern);
-
- ///
- /// Gets a file node by its path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file node.
- IFileNode GetFile(VFSFilePath filePath);
-
- ///
- /// Gets a file node by its path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file node.
- IFileNode GetFile(string filePath);
-
- ///
- /// Try to get a file node by its path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file node.
- /// true if the file node exists; otherwise, false.
- bool TryGetFile(VFSFilePath filePath, out IFileNode? file);
-
- ///
- /// Try to get a file node by its path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file node.
- /// true if the file node exists; otherwise, false.
- bool TryGetFile(string filePath, out IFileNode? file);
-
- ///
- /// Creates a file node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The content of the file node.
- /// The file system.
- IVirtualFileSystem CreateFile(VFSFilePath filePath, string? content = null);
-
- ///
- /// Creates a file node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The content of the file node.
- /// The file system.
- IVirtualFileSystem CreateFile(string filePath, string? content = null);
-
- ///
- /// Deletes a file node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file system.
- IVirtualFileSystem DeleteFile(VFSFilePath filePath);
-
- ///
- /// Deletes a file node at the specified path.
- /// The path must be absolute.
- ///
- /// The path of the file node.
- /// The file system.
- IVirtualFileSystem DeleteFile(string filePath);
-
- ///
- /// Finds all file nodes.
- ///
- /// The file nodes.
- IEnumerable FindFiles();
-
- ///
- /// Finds all file nodes that match the specified regular expression.
- ///
- /// The regular expression pattern.
- /// The file nodes.
- IEnumerable FindFiles(Regex regexPattern);
-
- // TODO: Add methods for copying, moving, renaming, etc.
- // ///
- // /// Reads the content of a file.
- // /// The file must exist.
- // ///
- // /// The path to the file.
- // /// The content of the file.
- // /// Thrown if the file does not exist.
- // /// Thrown if an error occurs while reading the file.
- // string ReadContentFromFile(VFSFilePath path);
- //
- // ///
- // /// Writes the content of a file.
- // /// The file must exist.
- // ///
- // /// The path to the file.
- // /// The content to write to the file.
- // /// Thrown if the file does not exist.
- // /// Thrown if an error occurs while writing the file.
- // void WriteContentToFile(VFSFilePath path, string content);
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Contracts;
+
+///
+/// Represents a virtual file system.
+/// This is the main entry point for all operations on the file system.
+/// You can get an instance of this interface by calling .
+///
+public interface IVirtualFileSystem
+{
+ ///
+ /// Gets the root directory of the file system.
+ /// This is the entry point for all operations on the file system.
+ ///
+ IRootNode Root { get; }
+
+ ///
+ /// Gets the file index of the file system.
+ /// Basically, this is a dictionary that maps file paths to file nodes.
+ /// This is useful for quickly finding a file node by its path.
+ ///
+ VFSIndex Index { get; }
+
+ ///
+ /// Indicates whether the file system is empty.
+ /// This is the case if the root directory is empty.
+ ///
+ bool IsEmpty { get; }
+
+ ///
+ /// Gets a directory node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the directory node.
+ /// The directory node.
+ IDirectoryNode GetDirectory(VFSDirectoryPath directoryPath);
+
+ ///
+ /// Gets a file node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file node.
+ IDirectoryNode GetDirectory(string directoryPath);
+
+ ///
+ /// Try to get a directory node by its path.
+ /// The path must be absolute.
+ /// If the directory node does not exist, this method returns false
+ /// and is set to null.
+ ///
+ /// The path of the directory node.
+ /// The directory node.
+ /// true if the directory node exists; otherwise, false.
+ bool TryGetDirectory(VFSDirectoryPath directoryPath, out IDirectoryNode? directory);
+
+ ///
+ /// Try to get a directory node by its path.
+ /// The path must be absolute.
+ /// If the directory node does not exist, this method returns false
+ /// and is set to null.
+ ///
+ /// The path of the directory node.
+ /// The directory node.
+ /// true if the directory node exists; otherwise, false.
+ bool TryGetDirectory(string directoryPath, out IDirectoryNode? directory);
+
+ ///
+ /// Creates a directory node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the directory node.
+ /// The file system.
+ IVirtualFileSystem CreateDirectory(VFSDirectoryPath directoryPath);
+
+ ///
+ /// Creates a directory node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the directory node.
+ /// The file system.
+ IVirtualFileSystem CreateDirectory(string directoryPath);
+
+ ///
+ /// Deletes a directory node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the directory node.
+ /// The file system.
+ IVirtualFileSystem DeleteDirectory(VFSDirectoryPath directoryPath);
+
+ ///
+ /// Deletes a directory node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the directory node.
+ /// The file system.
+ IVirtualFileSystem DeleteDirectory(string directoryPath);
+
+ ///
+ /// Finds all directory nodes.
+ ///
+ /// The directory nodes.
+ IEnumerable FindDirectories();
+
+ ///
+ /// Finds all directory nodes that match the specified regular expression.
+ /// The regular expression must be relative to the root directory.
+ ///
+ /// The regular expression pattern.
+ /// The directory nodes.
+ IEnumerable FindDirectories(Regex regexPattern);
+
+ ///
+ /// Gets a file node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file node.
+ IFileNode GetFile(VFSFilePath filePath);
+
+ ///
+ /// Gets a file node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file node.
+ IFileNode GetFile(string filePath);
+
+ ///
+ /// Try to get a file node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file node.
+ /// true if the file node exists; otherwise, false.
+ bool TryGetFile(VFSFilePath filePath, out IFileNode? file);
+
+ ///
+ /// Try to get a file node by its path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file node.
+ /// true if the file node exists; otherwise, false.
+ bool TryGetFile(string filePath, out IFileNode? file);
+
+ ///
+ /// Creates a file node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The content of the file node.
+ /// The file system.
+ IVirtualFileSystem CreateFile(VFSFilePath filePath, string? content = null);
+
+ ///
+ /// Creates a file node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The content of the file node.
+ /// The file system.
+ IVirtualFileSystem CreateFile(string filePath, string? content = null);
+
+ ///
+ /// Deletes a file node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file system.
+ IVirtualFileSystem DeleteFile(VFSFilePath filePath);
+
+ ///
+ /// Deletes a file node at the specified path.
+ /// The path must be absolute.
+ ///
+ /// The path of the file node.
+ /// The file system.
+ IVirtualFileSystem DeleteFile(string filePath);
+
+ ///
+ /// Finds all file nodes.
+ ///
+ /// The file nodes.
+ IEnumerable FindFiles();
+
+ ///
+ /// Finds all file nodes that match the specified regular expression.
+ ///
+ /// The regular expression pattern.
+ /// The file nodes.
+ IEnumerable FindFiles(Regex regexPattern);
+
+ // TODO: Add methods for copying, moving, renaming, etc.
+ // ///
+ // /// Reads the content of a file.
+ // /// The file must exist.
+ // ///
+ // /// The path to the file.
+ // /// The content of the file.
+ // /// Thrown if the file does not exist.
+ // /// Thrown if an error occurs while reading the file.
+ // string ReadContentFromFile(VFSFilePath path);
+ //
+ // ///
+ // /// Writes the content of a file.
+ // /// The file must exist.
+ // ///
+ // /// The path to the file.
+ // /// The content to write to the file.
+ // /// Thrown if the file does not exist.
+ // /// Thrown if an error occurs while writing the file.
+ // void WriteContentToFile(VFSFilePath path, string content);
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystemNode.cs b/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystemNode.cs
index f988bec..6ef4e48 100644
--- a/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystemNode.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Contracts/IVirtualFileSystemNode.cs
@@ -1,59 +1,59 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Contracts;
-
-///
-/// Represents a node in a virtual file system.
-/// A node can be a file or a directory.
-///
-public interface IVirtualFileSystemNode
-{
- ///
- /// Gets the full path of the node.
- /// The path is the path from the root of the file system to the node.
- /// For example, the path of the node with the path "./temp/file.txt" is "./temp/file.txt".
- /// The path of the node with the path "./temp/" is "./temp/".
- ///
- ///
- /// The full path of the node.
- ///
- VFSPath Path { get; }
-
- ///
- /// Gets the name of the virtual file system node.
- /// The name is the last part of the path.
- /// For example, the name of the file "vfs://temp/file.txt" is "file.txt".
- /// The name of the directory "vfs://temp" is "temp".
- ///
- public string Name
- => Path.Name;
-
- ///
- /// Gets the creation time of the node.
- ///
- DateTimeOffset CreationTime { get; }
-
- ///
- /// Gets the last access time of the node.
- ///
- DateTimeOffset LastAccessTime { get; }
-
- ///
- /// Gets the last write time of the node.
- ///
- DateTimeOffset LastWriteTime { get; }
-
- ///
- /// Indicates whether the node is a directory.
- ///
- bool IsDirectory { get; }
-
- ///
- /// Indicates whether the node is a file.
- ///
- bool IsFile { get; }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Contracts;
+
+///
+/// Represents a node in a virtual file system.
+/// A node can be a file or a directory.
+///
+public interface IVirtualFileSystemNode
+{
+ ///
+ /// Gets the full path of the node.
+ /// The path is the path from the root of the file system to the node.
+ /// For example, the path of the node with the path "./temp/file.txt" is "./temp/file.txt".
+ /// The path of the node with the path "./temp/" is "./temp/".
+ ///
+ ///
+ /// The full path of the node.
+ ///
+ VFSPath Path { get; }
+
+ ///
+ /// Gets the name of the virtual file system node.
+ /// The name is the last part of the path.
+ /// For example, the name of the file "vfs://temp/file.txt" is "file.txt".
+ /// The name of the directory "vfs://temp" is "temp".
+ ///
+ public string Name
+ => Path.Name;
+
+ ///
+ /// Gets the creation time of the node.
+ ///
+ DateTimeOffset CreationTime { get; }
+
+ ///
+ /// Gets the last access time of the node.
+ ///
+ DateTimeOffset LastAccessTime { get; }
+
+ ///
+ /// Gets the last write time of the node.
+ ///
+ DateTimeOffset LastWriteTime { get; }
+
+ ///
+ /// Indicates whether the node is a directory.
+ ///
+ bool IsDirectory { get; }
+
+ ///
+ /// Indicates whether the node is a file.
+ ///
+ bool IsFile { get; }
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Models/DirectoryNode.cs b/src/Atypical.VirtualFileSystem.Core/Models/DirectoryNode.cs
index 8bb29d6..248ed54 100644
--- a/src/Atypical.VirtualFileSystem.Core/Models/DirectoryNode.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Models/DirectoryNode.cs
@@ -1,58 +1,55 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Models;
-
-///
-/// Represents a directory in the virtual file system.
-///
-public record DirectoryNode
- : VFSNode, IDirectoryNode
-{
- private readonly List _directories = new();
- private readonly List _files = new();
-
- ///
- /// Initializes a new instance of the class.
- /// Creates a new directory node.
- /// The directory is created with the current date and time as creation and last modification date.
- ///
- /// The path of the directory.
- [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
- public DirectoryNode(VFSDirectoryPath directoryPath)
- : base(directoryPath)
- {
- Path = directoryPath;
- }
-
- ///
- public override VFSDirectoryPath Path { get; }
-
- ///
- public ReadOnlyCollection Directories
- => _directories.AsReadOnly();
-
- ///
- public override bool IsDirectory
- => true;
-
- ///
- public ReadOnlyCollection Files
- => _files.AsReadOnly();
-
- ///
- public override bool IsFile
- => false;
-
- ///
- /// Returns a string that represents the path of the directory.
- ///
- /// A string that represents the path of the directory.
- public override string ToString()
- {
- return Path.ToString();
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Models;
+
+///
+/// Represents a directory in the virtual file system.
+///
+public record DirectoryNode
+ : VFSNode, IDirectoryNode
+{
+ private readonly List _directories = new();
+ private readonly List _files = new();
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Creates a new directory node.
+ /// The directory is created with the current date and time as creation and last modification date.
+ ///
+ /// The path of the directory.
+ [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
+ public DirectoryNode(VFSDirectoryPath directoryPath)
+ : base(directoryPath)
+ {
+ Path = directoryPath;
+ }
+
+ ///
+ public override VFSDirectoryPath Path { get; }
+
+ ///
+ public ReadOnlyCollection Directories
+ => _directories.AsReadOnly();
+
+ ///
+ public ReadOnlyCollection Files
+ => _files.AsReadOnly();
+
+ ///
+ public override bool IsDirectory
+ => true;
+
+ ///
+ public override bool IsFile
+ => false;
+
+ ///
+ /// Returns a string that represents the path of the directory.
+ ///
+ /// A string that represents the path of the directory.
+ public override string ToString() => Path.ToString();
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Models/FileNode.cs b/src/Atypical.VirtualFileSystem.Core/Models/FileNode.cs
index 3f05ad5..3269b4e 100644
--- a/src/Atypical.VirtualFileSystem.Core/Models/FileNode.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Models/FileNode.cs
@@ -1,52 +1,49 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Models;
-
-///
-/// Represents a file in the virtual file system.
-///
-public record FileNode
- : VFSNode, IFileNode
-{
- ///
- /// Initializes a new instance of the class.
- /// Creates a new file node.
- /// The file is created with the current date and time as creation and last modification date.
- ///
- /// The path of the file.
- /// The content of the file.
- [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
- public FileNode(VFSFilePath filePath, string? content = null)
- : base(filePath)
- {
- Path = filePath;
- Content = content ?? string.Empty;
- }
-
- ///
- public string Content { get; set; }
-
- ///
- public override VFSFilePath Path { get; }
-
- ///
- public override bool IsDirectory
- => false;
-
- ///
- public override bool IsFile
- => true;
-
- ///
- /// Returns a string that represents the path of the file.
- ///
- /// A string that represents the path of the file.
- public override string ToString()
- {
- return Path.ToString();
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Models;
+
+///
+/// Represents a file in the virtual file system.
+///
+public record FileNode
+ : VFSNode, IFileNode
+{
+ ///
+ /// Initializes a new instance of the class.
+ /// Creates a new file node.
+ /// The file is created with the current date and time as creation and last modification date.
+ ///
+ /// The path of the file.
+ /// The content of the file.
+ [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
+ public FileNode(VFSFilePath filePath, string? content = null)
+ : base(filePath)
+ {
+ Path = filePath;
+ Content = content ?? string.Empty;
+ }
+
+ ///
+ public override VFSFilePath Path { get; }
+
+ ///
+ public string Content { get; set; }
+
+ ///
+ public override bool IsDirectory
+ => false;
+
+ ///
+ public override bool IsFile
+ => true;
+
+ ///
+ /// Returns a string that represents the path of the file.
+ ///
+ /// A string that represents the path of the file.
+ public override string ToString() => Path.ToString();
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/Models/RootNode.cs b/src/Atypical.VirtualFileSystem.Core/Models/RootNode.cs
index 3ca3331..73d4e7d 100644
--- a/src/Atypical.VirtualFileSystem.Core/Models/RootNode.cs
+++ b/src/Atypical.VirtualFileSystem.Core/Models/RootNode.cs
@@ -1,32 +1,29 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.Models;
-
-///
-/// Represents the root directory of the virtual file system.
-///
-public record RootNode
- : DirectoryNode, IRootNode
-{
- ///
- /// Initializes a new instance of the class.
- ///
- public RootNode()
- : base(new VFSRootPath())
- {
- }
-
- ///
- /// Returns a string that represents the current object.
- /// For this is always the constant string .
- ///
- ///
- public override string ToString()
- {
- return Path.ToString();
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.Models;
+
+///
+/// Represents the root directory of the virtual file system.
+///
+public record RootNode
+ : DirectoryNode, IRootNode
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RootNode()
+ : base(new VFSRootPath())
+ {
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ /// For this is always the constant string .
+ ///
+ ///
+ public override string ToString() => Path.ToString();
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/VFS.cs b/src/Atypical.VirtualFileSystem.Core/VFS.cs
index 19a5112..d4a1ab7 100644
--- a/src/Atypical.VirtualFileSystem.Core/VFS.cs
+++ b/src/Atypical.VirtualFileSystem.Core/VFS.cs
@@ -1,255 +1,255 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core;
-
-///
-/// Represents a virtual file system.
-/// This class cannot be inherited.
-///
-public record VFS
- : IVirtualFileSystem
-{
- ///
- /// Initializes a new instance of the class.
- ///
- public VFS()
- {
- Root = new RootNode();
- Index = new VFSIndex(Root);
- }
-
- ///
- public IRootNode Root { get; }
-
- ///
- public VFSIndex Index { get; }
-
- ///
- public bool IsEmpty
- => Index.Count == 1;
-
- #region Indexing
-
- private void AddToIndex(IVirtualFileSystemNode node)
- {
- var added = Index.TryAdd(node.Path.Value, node);
-
- if (!added)
- throw new InvalidOperationException($"The node '{node.Path}' already exists in the index.");
-
- if (node.Path.Parent is not null && !Index.ContainsKey(node.Path.Parent.Value))
- CreateDirectory(node.Path.Parent);
- }
-
- #endregion
-
- #region Directory
-
- ///
- public IDirectoryNode GetDirectory(VFSDirectoryPath directoryPath)
- => (IDirectoryNode)Index[directoryPath.Value];
-
- ///
- public IDirectoryNode GetDirectory(string directoryPath)
- => GetDirectory(new VFSDirectoryPath(directoryPath));
-
- ///
- public bool TryGetDirectory(VFSDirectoryPath directoryPath, out IDirectoryNode? directory)
- {
- try
- {
- directory = GetDirectory(directoryPath);
- return true;
- }
- catch (KeyNotFoundException)
- {
- directory = null;
- return false;
- }
- }
-
- ///
- public bool TryGetDirectory(string path, out IDirectoryNode? directory)
- => TryGetDirectory(new VFSDirectoryPath(path), out directory);
-
- ///
- public IVirtualFileSystem CreateDirectory(VFSDirectoryPath directoryPath)
- {
- if (directoryPath.IsRoot)
- throw new ArgumentException("Cannot create root directory.", nameof(directoryPath));
-
- var directory = new DirectoryNode(directoryPath);
- AddToIndex(directory);
- return this;
- }
-
- ///
- public IVirtualFileSystem CreateDirectory(string path)
- => CreateDirectory(new VFSDirectoryPath(path));
-
- ///
- public IVirtualFileSystem DeleteDirectory(VFSDirectoryPath directoryPath)
- {
- if (directoryPath.IsRoot)
- throw new ArgumentException("Cannot delete root directory.", nameof(directoryPath));
-
- // try to get the directory
- var found = TryGetDirectory(directoryPath, out _);
- if (!found)
- throw new KeyNotFoundException($"The directory '{directoryPath}' does not exist.");
-
- // find the path and its children in the index
- var paths = Index.Keys
- .Where(p => p.StartsWith(directoryPath.Value))
- .OrderByDescending(p => p.Length)
- .ToList();
-
- // remove the paths from the index
- foreach (var p in paths)
- Index.Remove(p);
-
- return this;
- }
-
- ///
- public IVirtualFileSystem DeleteDirectory(string directoryPath)
- => DeleteDirectory(new VFSDirectoryPath(directoryPath));
-
- ///
- public IEnumerable FindDirectories()
- => Index.Values.OfType();
-
- ///
- public IEnumerable FindDirectories(Regex regexPattern)
- => FindDirectories().Where(f => regexPattern.IsMatch(f.Path.Value));
-
- #endregion
-
- #region File
-
- ///
- public IFileNode GetFile(VFSFilePath filePath)
- => (IFileNode)Index[filePath.Value];
-
- ///
- public IFileNode GetFile(string filePath)
- => GetFile(new VFSFilePath(filePath));
-
- ///
- public bool TryGetFile(VFSFilePath filePath, out IFileNode? file)
- {
- try
- {
- file = GetFile(filePath);
- return true;
- }
- catch (KeyNotFoundException)
- {
- file = null;
- return false;
- }
- }
-
- ///
- public bool TryGetFile(string filePath, out IFileNode? file)
- => TryGetFile(new VFSFilePath(filePath), out file);
-
- ///
- public IVirtualFileSystem CreateFile(VFSFilePath filePath, string? content = null)
- {
- var file = new FileNode(filePath, content);
- AddToIndex(file);
- return this;
- }
-
- ///
- public IVirtualFileSystem CreateFile(string filePath, string? content = null)
- => CreateFile(new VFSFilePath(filePath), content);
-
- ///
- public IVirtualFileSystem DeleteFile(VFSFilePath filePath)
- {
- // try to get the file
- var found = TryGetFile(filePath, out _);
- if (!found)
- throw new KeyNotFoundException($"The file '{filePath}' does not exist.");
-
- // remove the file from the index
- Index.Remove(filePath.Value);
-
- return this;
- }
-
- ///
- public IVirtualFileSystem DeleteFile(string filePath)
- => DeleteFile(new VFSFilePath(filePath));
-
- ///
- public IEnumerable FindFiles()
- => Index.Values.OfType();
-
- ///
- public IEnumerable FindFiles(Regex regexPattern)
- => FindFiles().Where(f => regexPattern.IsMatch(f.Path.Value));
-
- #endregion
-
- ///
- /// Returns the index as an ASCII tree.
- ///
- ///
- /// The index as an ASCII tree.
- ///
- /// The root directory is always the first line.
- ///
- public override string ToString()
- {
- var sb = new StringBuilder();
-
- sb.AppendLine(Root.Name);
-
- foreach (IVirtualFileSystemNode node in Index.Values.Skip(1))
- {
- int depth = node.Path.Depth;
-
- // get all brothers of the node
- var brothers = GetBrothers(node);
-
- // check if the node is the last node on its level
- bool isLastNodeOfLevel = brothers.Last() == node;
-
- while (depth > 1)
- {
- string parent = node.Path.GetAbsoluteParentPath(1).Value;
- bool isLastNodeOfLevelParent = GetBrothers(GetDirectory(parent)).Last() == GetDirectory(parent);
-
- sb.Append(isLastNodeOfLevelParent ? STR_INDENT_CLEAR : STR_INDENT_FILL);
- depth--;
- }
-
- sb.Append(isLastNodeOfLevel ? STR_INDENT_ENTRY_LAST : STR_INDENT_ENTRY_MIDDLE);
- sb.AppendLine(node.Path.Name);
- }
-
- return sb.ToString().Trim();
- }
-
- ///
- /// Get all brothers of the node
- /// (all nodes on the same level including the node itself)
- ///
- /// The node
- ///
- private List GetBrothers(IVirtualFileSystemNode node)
- {
- var brothers = Index.Values
- .Where(n => n.Path.Parent == node.Path.Parent)
- .ToList();
-
- return brothers;
- }
-}
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core;
+
+///
+/// Represents a virtual file system.
+/// This class cannot be inherited.
+///
+public record VFS
+ : IVirtualFileSystem
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public VFS()
+ {
+ Root = new RootNode();
+ Index = new VFSIndex(Root);
+ }
+
+ ///
+ public IRootNode Root { get; }
+
+ ///
+ public VFSIndex Index { get; }
+
+ ///
+ public bool IsEmpty
+ => Index.Count == 1;
+
+ #region Indexing
+
+ private void AddToIndex(IVirtualFileSystemNode node)
+ {
+ var added = Index.TryAdd(node.Path.Value, node);
+
+ if (!added)
+ throw new InvalidOperationException($"The node '{node.Path}' already exists in the index.");
+
+ if (node.Path.Parent is not null && !Index.ContainsKey(node.Path.Parent.Value))
+ CreateDirectory(node.Path.Parent);
+ }
+
+ #endregion
+
+ ///
+ /// Returns the index as an ASCII tree.
+ ///
+ ///
+ /// The index as an ASCII tree.
+ ///
+ /// The root directory is always the first line.
+ ///
+ public override string ToString()
+ {
+ var sb = new StringBuilder();
+
+ sb.AppendLine(Root.Name);
+
+ foreach (var node in Index.Values.Skip(1))
+ {
+ var depth = node.Path.Depth;
+
+ // get all brothers of the node
+ var brothers = GetBrothers(node);
+
+ // check if the node is the last node on its level
+ var isLastNodeOfLevel = brothers.Last() == node;
+
+ while (depth > 1)
+ {
+ var parent = node.Path.GetAbsoluteParentPath(1).Value;
+ var isLastNodeOfLevelParent = GetBrothers(GetDirectory(parent)).Last() == GetDirectory(parent);
+
+ sb.Append(isLastNodeOfLevelParent ? STR_INDENT_CLEAR : STR_INDENT_FILL);
+ depth--;
+ }
+
+ sb.Append(isLastNodeOfLevel ? STR_INDENT_ENTRY_LAST : STR_INDENT_ENTRY_MIDDLE);
+ sb.AppendLine(node.Path.Name);
+ }
+
+ return sb.ToString().Trim();
+ }
+
+ ///
+ /// Get all brothers of the node
+ /// (all nodes on the same level including the node itself)
+ ///
+ /// The node
+ ///
+ private List GetBrothers(IVirtualFileSystemNode node)
+ {
+ var brothers = Index.Values
+ .Where(n => n.Path.Parent == node.Path.Parent)
+ .ToList();
+
+ return brothers;
+ }
+
+ #region Directory
+
+ ///
+ public IDirectoryNode GetDirectory(VFSDirectoryPath directoryPath)
+ => (IDirectoryNode)Index[directoryPath.Value];
+
+ ///
+ public IDirectoryNode GetDirectory(string directoryPath)
+ => GetDirectory(new VFSDirectoryPath(directoryPath));
+
+ ///
+ public bool TryGetDirectory(VFSDirectoryPath directoryPath, out IDirectoryNode? directory)
+ {
+ try
+ {
+ directory = GetDirectory(directoryPath);
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ directory = null;
+ return false;
+ }
+ }
+
+ ///
+ public bool TryGetDirectory(string path, out IDirectoryNode? directory)
+ => TryGetDirectory(new VFSDirectoryPath(path), out directory);
+
+ ///
+ public IVirtualFileSystem CreateDirectory(VFSDirectoryPath directoryPath)
+ {
+ if (directoryPath.IsRoot)
+ throw new ArgumentException("Cannot create root directory.", nameof(directoryPath));
+
+ var directory = new DirectoryNode(directoryPath);
+ AddToIndex(directory);
+ return this;
+ }
+
+ ///
+ public IVirtualFileSystem CreateDirectory(string path)
+ => CreateDirectory(new VFSDirectoryPath(path));
+
+ ///
+ public IVirtualFileSystem DeleteDirectory(VFSDirectoryPath directoryPath)
+ {
+ if (directoryPath.IsRoot)
+ throw new ArgumentException("Cannot delete root directory.", nameof(directoryPath));
+
+ // try to get the directory
+ var found = TryGetDirectory(directoryPath, out _);
+ if (!found)
+ throw new KeyNotFoundException($"The directory '{directoryPath}' does not exist.");
+
+ // find the path and its children in the index
+ var paths = Index.Keys
+ .Where(p => p.StartsWith(directoryPath.Value))
+ .OrderByDescending(p => p.Length)
+ .ToList();
+
+ // remove the paths from the index
+ foreach (var p in paths)
+ Index.Remove(p);
+
+ return this;
+ }
+
+ ///
+ public IVirtualFileSystem DeleteDirectory(string directoryPath)
+ => DeleteDirectory(new VFSDirectoryPath(directoryPath));
+
+ ///
+ public IEnumerable FindDirectories()
+ => Index.Values.OfType();
+
+ ///
+ public IEnumerable FindDirectories(Regex regexPattern)
+ => FindDirectories().Where(f => regexPattern.IsMatch(f.Path.Value));
+
+ #endregion
+
+ #region File
+
+ ///
+ public IFileNode GetFile(VFSFilePath filePath)
+ => (IFileNode)Index[filePath.Value];
+
+ ///
+ public IFileNode GetFile(string filePath)
+ => GetFile(new VFSFilePath(filePath));
+
+ ///
+ public bool TryGetFile(VFSFilePath filePath, out IFileNode? file)
+ {
+ try
+ {
+ file = GetFile(filePath);
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ file = null;
+ return false;
+ }
+ }
+
+ ///
+ public bool TryGetFile(string filePath, out IFileNode? file)
+ => TryGetFile(new VFSFilePath(filePath), out file);
+
+ ///
+ public IVirtualFileSystem CreateFile(VFSFilePath filePath, string? content = null)
+ {
+ var file = new FileNode(filePath, content);
+ AddToIndex(file);
+ return this;
+ }
+
+ ///
+ public IVirtualFileSystem CreateFile(string filePath, string? content = null)
+ => CreateFile(new VFSFilePath(filePath), content);
+
+ ///
+ public IVirtualFileSystem DeleteFile(VFSFilePath filePath)
+ {
+ // try to get the file
+ var found = TryGetFile(filePath, out _);
+ if (!found)
+ throw new KeyNotFoundException($"The file '{filePath}' does not exist.");
+
+ // remove the file from the index
+ Index.Remove(filePath.Value);
+
+ return this;
+ }
+
+ ///
+ public IVirtualFileSystem DeleteFile(string filePath)
+ => DeleteFile(new VFSFilePath(filePath));
+
+ ///
+ public IEnumerable FindFiles()
+ => Index.Values.OfType();
+
+ ///
+ public IEnumerable FindFiles(Regex regexPattern)
+ => FindFiles().Where(f => regexPattern.IsMatch(f.Path.Value));
+
+ #endregion
+}
diff --git a/src/Atypical.VirtualFileSystem.Core/VFSConstants.cs b/src/Atypical.VirtualFileSystem.Core/VFSConstants.cs
index 84940eb..7fc5af6 100644
--- a/src/Atypical.VirtualFileSystem.Core/VFSConstants.cs
+++ b/src/Atypical.VirtualFileSystem.Core/VFSConstants.cs
@@ -1,49 +1,49 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core;
-
-///
-/// Constants used by the Virtual File System.
-///
-public static class VFSConstants
-{
- ///
- /// The root path.
- /// This is the path used to identify the root directory.
- ///
- public const string ROOT_PATH = "vfs://";
-
- ///
- /// The directory separator.
- /// This is the character used to separate directory names.
- ///
- public const string DIRECTORY_SEPARATOR = "/";
-
- ///
- /// The string indent clear.
- /// A 4 characters string used by a string builder to indent a line.
- ///
- public const string STR_INDENT_CLEAR = " ";
-
- ///
- /// The string indent entry middle.
- /// A 4 characters string used by a string builder to indent a line which is not the last one.
- ///
- public const string STR_INDENT_ENTRY_MIDDLE = "├── ";
-
- ///
- /// The string indent entry last.
- /// A 4 characters string used by a string builder to indent a line which is the last one.
- ///
- public const string STR_INDENT_ENTRY_LAST = "└── ";
-
- ///
- /// The string indent entry fill.
- /// A 4 characters string used by a string builder to indent a line which is not the last one.
- ///
- public const string STR_INDENT_FILL = "│ ";
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core;
+
+///
+/// Constants used by the Virtual File System.
+///
+public static class VFSConstants
+{
+ ///
+ /// The root path.
+ /// This is the path used to identify the root directory.
+ ///
+ public const string ROOT_PATH = "vfs://";
+
+ ///
+ /// The directory separator.
+ /// This is the character used to separate directory names.
+ ///
+ public const string DIRECTORY_SEPARATOR = "/";
+
+ ///
+ /// The string indent clear.
+ /// A 4 characters string used by a string builder to indent a line.
+ ///
+ public const string STR_INDENT_CLEAR = " ";
+
+ ///
+ /// The string indent entry middle.
+ /// A 4 characters string used by a string builder to indent a line which is not the last one.
+ ///
+ public const string STR_INDENT_ENTRY_MIDDLE = "├── ";
+
+ ///
+ /// The string indent entry last.
+ /// A 4 characters string used by a string builder to indent a line which is the last one.
+ ///
+ public const string STR_INDENT_ENTRY_LAST = "└── ";
+
+ ///
+ /// The string indent entry fill.
+ /// A 4 characters string used by a string builder to indent a line which is not the last one.
+ ///
+ public const string STR_INDENT_FILL = "│ ";
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/VFSIndex.cs b/src/Atypical.VirtualFileSystem.Core/VFSIndex.cs
index f24488b..630deca 100644
--- a/src/Atypical.VirtualFileSystem.Core/VFSIndex.cs
+++ b/src/Atypical.VirtualFileSystem.Core/VFSIndex.cs
@@ -1,30 +1,30 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core;
-
-///
-/// Represents the index of the virtual file system.
-/// - a vfs index is a dictionary of vfs paths and vfs nodes
-/// - the vfs index is used to store the nodes of the virtual file system
-/// This class cannot be inherited.
-///
-public sealed class VFSIndex
- : SortedDictionary
-{
- ///
- /// Initializes a new instance of the class.
- /// - the vfs index is a dictionary of vfs paths and vfs nodes
- /// - the vfs index is used to store the nodes of the virtual file system
- /// - the vfs index is sorted by the vfs paths
- /// - the vfs index is case insensitive
- ///
- /// The root node of the virtual file system.
- public VFSIndex(IRootNode rootNode)
- {
- Add(rootNode.Path.Value, rootNode);
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core;
+
+///
+/// Represents the index of the virtual file system.
+/// - a vfs index is a dictionary of vfs paths and vfs nodes
+/// - the vfs index is used to store the nodes of the virtual file system
+/// This class cannot be inherited.
+///
+public sealed class VFSIndex
+ : SortedDictionary
+{
+ ///
+ /// Initializes a new instance of the class.
+ /// - the vfs index is a dictionary of vfs paths and vfs nodes
+ /// - the vfs index is used to store the nodes of the virtual file system
+ /// - the vfs index is sorted by the vfs paths
+ /// - the vfs index is case insensitive
+ ///
+ /// The root node of the virtual file system.
+ public VFSIndex(IRootNode rootNode)
+ {
+ Add(rootNode.Path.Value, rootNode);
+ }
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSDirectoryPath.cs b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSDirectoryPath.cs
index e0cc6ef..7ea7790 100644
--- a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSDirectoryPath.cs
+++ b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSDirectoryPath.cs
@@ -1,52 +1,44 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.ValueObjects;
-
-///
-/// Represents a directory in the virtual file system.
-/// A directory is a first-class citizen in the virtual file system.
-/// It can contain files and other directories.
-///
-public record VFSDirectoryPath : VFSPath
-{
- ///
- /// Initializes a new instance of the class.
- /// The file path is relative to the root of the virtual file system.
- ///
- /// The path of the directory.
- public VFSDirectoryPath(string path)
- : base(path)
- {
- // cannot ends with a file extension
- var lastSegment = Value.Split('/').Last();
- if (lastSegment.Contains('.'))
- {
- throw new ArgumentException("The path must not contain a file extension.", nameof(path));
- }
- }
-
- ///
- /// Returns a string that represents the current object.
- /// The string representation of the directory path is the path itself.
- ///
- /// A string that represents the current object.
- public override string ToString()
- {
- return Value;
- }
-
- ///
- /// Implicit conversion to string
- /// This allows you to use a as a string.
- ///
- /// The path to convert.
- /// The string representation of the path.
- public static implicit operator string(VFSDirectoryPath path)
- {
- return path.Value;
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.ValueObjects;
+
+///
+/// Represents a directory in the virtual file system.
+/// A directory is a first-class citizen in the virtual file system.
+/// It can contain files and other directories.
+///
+public record VFSDirectoryPath : VFSPath
+{
+ ///
+ /// Initializes a new instance of the class.
+ /// The file path is relative to the root of the virtual file system.
+ ///
+ /// The path of the directory.
+ public VFSDirectoryPath(string path)
+ : base(path)
+ {
+ // cannot ends with a file extension
+ var lastSegment = Value.Split('/').Last();
+ if (lastSegment.Contains('.'))
+ throw new ArgumentException("The path must not contain a file extension.", nameof(path));
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ /// The string representation of the directory path is the path itself.
+ ///
+ /// A string that represents the current object.
+ public override string ToString() => Value;
+
+ ///
+ /// Implicit conversion to string
+ /// This allows you to use a as a string.
+ ///
+ /// The path to convert.
+ /// The string representation of the path.
+ public static implicit operator string(VFSDirectoryPath path) => path.Value;
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSFilePath.cs b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSFilePath.cs
index cc66751..851806f 100644
--- a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSFilePath.cs
+++ b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSFilePath.cs
@@ -1,45 +1,39 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.ValueObjects;
-
-///
-/// Represents a file system entry in the virtual file system.
-/// A file is a first-class citizen in the virtual file system.
-///
-public record VFSFilePath : VFSPath
-{
- ///
- /// Initializes a new instance of the class.
- /// The file path is relative to the root of the virtual file system.
- ///
- /// The path of the file.
- public VFSFilePath(string path)
- : base(path)
- {
- }
-
- ///
- /// Returns a string that represents the current object.
- /// The file path is relative to the root of the virtual file system.
- ///
- /// A string that represents the current object.
- public override string ToString()
- {
- return Value;
- }
-
- ///
- /// Implicit conversion to string
- /// This allows you to use a as a string.
- ///
- /// The path to convert.
- /// The string representation of the path.
- public static implicit operator string(VFSFilePath path)
- {
- return path.Value;
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.ValueObjects;
+
+///
+/// Represents a file system entry in the virtual file system.
+/// A file is a first-class citizen in the virtual file system.
+///
+public record VFSFilePath : VFSPath
+{
+ ///
+ /// Initializes a new instance of the class.
+ /// The file path is relative to the root of the virtual file system.
+ ///
+ /// The path of the file.
+ public VFSFilePath(string path)
+ : base(path)
+ {
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ /// The file path is relative to the root of the virtual file system.
+ ///
+ /// A string that represents the current object.
+ public override string ToString() => Value;
+
+ ///
+ /// Implicit conversion to string
+ /// This allows you to use a as a string.
+ ///
+ /// The path to convert.
+ /// The string representation of the path.
+ public static implicit operator string(VFSFilePath path) => path.Value;
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSRootPath.cs b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSRootPath.cs
index b1c31c1..3d6cda8 100644
--- a/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSRootPath.cs
+++ b/src/Atypical.VirtualFileSystem.Core/ValueObjects/VFSRootPath.cs
@@ -1,35 +1,29 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core.ValueObjects;
-
-///
-/// Represents the root directory of the virtual file system.
-///
-public record VFSRootPath()
- : VFSDirectoryPath(ROOT_PATH)
-{
- ///
- /// Returns a string that represents the current object.
- /// The string representation of the root directory is the constant .
- ///
- /// A string that represents the current object.
- public override string ToString()
- {
- return Value;
- }
-
- ///
- /// Implicit conversion to string
- /// This allows you to use a as a string.
- ///
- /// The path to convert.
- /// The string representation of the path.
- public static implicit operator string(VFSRootPath path)
- {
- return path.Value;
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core.ValueObjects;
+
+///
+/// Represents the root directory of the virtual file system.
+///
+public record VFSRootPath()
+ : VFSDirectoryPath(ROOT_PATH)
+{
+ ///
+ /// Returns a string that represents the current object.
+ /// The string representation of the root directory is the constant .
+ ///
+ /// A string that represents the current object.
+ public override string ToString() => Value;
+
+ ///
+ /// Implicit conversion to string
+ /// This allows you to use a as a string.
+ ///
+ /// The path to convert.
+ /// The string representation of the path.
+ public static implicit operator string(VFSRootPath path) => path.Value;
}
\ No newline at end of file
diff --git a/src/Atypical.VirtualFileSystem.Core/VirtualFileSystemFactory.cs b/src/Atypical.VirtualFileSystem.Core/VirtualFileSystemFactory.cs
index 9bec380..09058d1 100644
--- a/src/Atypical.VirtualFileSystem.Core/VirtualFileSystemFactory.cs
+++ b/src/Atypical.VirtualFileSystem.Core/VirtualFileSystemFactory.cs
@@ -1,26 +1,23 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace Atypical.VirtualFileSystem.Core;
-
-///
-/// Represents a factory for creating instances.
-///
-public class VirtualFileSystemFactory : IVirtualFileSystemFactory
-{
- ///
- /// Initializes a new instance of the class.
- ///
- public VirtualFileSystemFactory()
- {
- }
-
- ///
- public IVirtualFileSystem CreateFileSystem()
- {
- return new VFS();
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace Atypical.VirtualFileSystem.Core;
+
+///
+/// Represents a factory for creating instances.
+///
+public class VirtualFileSystemFactory : IVirtualFileSystemFactory
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public VirtualFileSystemFactory()
+ {
+ }
+
+ ///
+ public IVirtualFileSystem CreateFileSystem() => new VFS();
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Atypical.VirtualFileSystem.UnitTests.csproj b/tests/Atypical.VirtualFileSystem.UnitTests/Atypical.VirtualFileSystem.UnitTests.csproj
index bc2283c..3236c9f 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Atypical.VirtualFileSystem.UnitTests.csproj
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Atypical.VirtualFileSystem.UnitTests.csproj
@@ -13,9 +13,9 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -27,7 +27,7 @@
-
+
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Models/DirectoryNodeTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/Models/DirectoryNodeTests.cs
index 9b970ab..934acc6 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Models/DirectoryNodeTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Models/DirectoryNodeTests.cs
@@ -1,65 +1,65 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.Models;
-
-public class DirectoryNodeTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_create_a_directory_node()
- {
- // Arrange
- var directoryPath = new VFSDirectoryPath("test");
- const string expectedPath = @"vfs://test";
- const string expectedParentPath = @"vfs://";
-
- // Act
- var directoryNode = new DirectoryNode(directoryPath);
-
- // Assert
- directoryNode.Should().NotBeNull();
- directoryNode.Directories.Should().BeEmpty();
- directoryNode.Files.Should().BeEmpty();
- directoryNode.Path.Value.Should().Be(expectedPath);
- directoryNode.Path.Parent.Should().NotBeNull();
- directoryNode.Path.Parent!.Value.Should().Be(expectedParentPath);
- }
-
- [Fact]
- public void Constructor_create_a_directory_node_with_parent()
- {
- var directoryPath = new VFSDirectoryPath("parent/child");
- var directory = new DirectoryNode(directoryPath);
-
- directory.Path.Value.Should().Be("vfs://parent/child");
- directory.Path.Parent.Should().NotBeNull();
- directory.Path.Parent!.Value.Should().Be("vfs://parent");
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_return_path()
- {
- var directoryPath = new VFSDirectoryPath("test");
- var directoryNode = new DirectoryNode(directoryPath);
-
- directoryNode.ToString().Should().Be("vfs://test");
- }
-
- [Fact]
- public void ToString_return_path_with_parent()
- {
- var directoryPath = new VFSDirectoryPath("parent/child");
- var directory = new DirectoryNode(directoryPath);
-
- directory.ToString().Should().Be("vfs://parent/child");
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.Models;
+
+public class DirectoryNodeTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_create_a_directory_node()
+ {
+ // Arrange
+ var directoryPath = new VFSDirectoryPath("test");
+ const string expectedPath = @"vfs://test";
+ const string expectedParentPath = @"vfs://";
+
+ // Act
+ var directoryNode = new DirectoryNode(directoryPath);
+
+ // Assert
+ directoryNode.Should().NotBeNull();
+ directoryNode.Directories.Should().BeEmpty();
+ directoryNode.Files.Should().BeEmpty();
+ directoryNode.Path.Value.Should().Be(expectedPath);
+ directoryNode.Path.Parent.Should().NotBeNull();
+ directoryNode.Path.Parent!.Value.Should().Be(expectedParentPath);
+ }
+
+ [Fact]
+ public void Constructor_create_a_directory_node_with_parent()
+ {
+ var directoryPath = new VFSDirectoryPath("parent/child");
+ var directory = new DirectoryNode(directoryPath);
+
+ directory.Path.Value.Should().Be("vfs://parent/child");
+ directory.Path.Parent.Should().NotBeNull();
+ directory.Path.Parent!.Value.Should().Be("vfs://parent");
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_return_path()
+ {
+ var directoryPath = new VFSDirectoryPath("test");
+ var directoryNode = new DirectoryNode(directoryPath);
+
+ directoryNode.ToString().Should().Be("vfs://test");
+ }
+
+ [Fact]
+ public void ToString_return_path_with_parent()
+ {
+ var directoryPath = new VFSDirectoryPath("parent/child");
+ var directory = new DirectoryNode(directoryPath);
+
+ directory.ToString().Should().Be("vfs://parent/child");
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Models/FileNodeTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/Models/FileNodeTests.cs
index 24fbf24..aff4482 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Models/FileNodeTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Models/FileNodeTests.cs
@@ -1,46 +1,46 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.Models;
-
-public class FileNodeTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_creates_a_file_with_the_specified_name()
- {
- // Arrange
- VFSFilePath path = new("file.txt");
-
- // Act
- var fileNode = new FileNode(path);
-
- // Assert
- fileNode.Path.Should().Be(path);
- fileNode.Content.Should().BeEmpty();
- fileNode.IsDirectory.Should().BeFalse();
- fileNode.IsFile.Should().BeTrue();
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_returns_the_path_of_the_file()
- {
- // Arrange
- VFSFilePath path = new("file.txt");
- var fileNode = new FileNode(path);
-
- // Act
- string result = fileNode.ToString();
-
- // Assert
- result.Should().Be(path.ToString());
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.Models;
+
+public class FileNodeTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_creates_a_file_with_the_specified_name()
+ {
+ // Arrange
+ VFSFilePath path = new("file.txt");
+
+ // Act
+ var fileNode = new FileNode(path);
+
+ // Assert
+ fileNode.Path.Should().Be(path);
+ fileNode.Content.Should().BeEmpty();
+ fileNode.IsDirectory.Should().BeFalse();
+ fileNode.IsFile.Should().BeTrue();
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_returns_the_path_of_the_file()
+ {
+ // Arrange
+ VFSFilePath path = new("file.txt");
+ var fileNode = new FileNode(path);
+
+ // Act
+ var result = fileNode.ToString();
+
+ // Assert
+ result.Should().Be(path.ToString());
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Models/RootNodeTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/Models/RootNodeTests.cs
index 3fc36ef..a932d8d 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Models/RootNodeTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Models/RootNodeTests.cs
@@ -1,41 +1,41 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.Models;
-
-public class RootNodeTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_create_a_root_node()
- {
- // Arrange
- const string expectedPath = @"vfs://";
-
- // Act
- var rootNode = new RootNode();
-
- // Assert
- rootNode.Should().NotBeNull();
- rootNode.Directories.Should().BeEmpty();
- rootNode.Files.Should().BeEmpty();
- rootNode.Path.Value.Should().Be(expectedPath);
- rootNode.Path.Parent.Should().BeNull();
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_return_path()
- {
- var rootNode = new RootNode();
-
- rootNode.ToString().Should().Be("vfs://");
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.Models;
+
+public class RootNodeTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_create_a_root_node()
+ {
+ // Arrange
+ const string expectedPath = @"vfs://";
+
+ // Act
+ var rootNode = new RootNode();
+
+ // Assert
+ rootNode.Should().NotBeNull();
+ rootNode.Directories.Should().BeEmpty();
+ rootNode.Files.Should().BeEmpty();
+ rootNode.Path.Value.Should().Be(expectedPath);
+ rootNode.Path.Parent.Should().BeNull();
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_return_path()
+ {
+ var rootNode = new RootNode();
+
+ rootNode.ToString().Should().Be("vfs://");
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemFactoryTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemFactoryTests.cs
index ccae2b1..dfeb45b 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemFactoryTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemFactoryTests.cs
@@ -1,41 +1,41 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.Models;
-
-public class VirtualFileSystemFactoryTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_create_a_virtual_file_system_factory()
- {
- // Act
- var virtualFileSystemFactory = new VirtualFileSystemFactory();
-
- // Assert
- virtualFileSystemFactory.Should().NotBeNull();
- }
- }
-
- public class MethodCreateFileSystem
- {
- [Fact]
- public void CreateFileSystem_create_a_virtual_file_system()
- {
- // Arrange
- var virtualFileSystemFactory = new VirtualFileSystemFactory();
-
- // Act
- var virtualFileSystem = virtualFileSystemFactory.CreateFileSystem();
-
- // Assert
- virtualFileSystem.Should().NotBeNull();
- virtualFileSystem.Root.Should().NotBeNull();
- virtualFileSystem.Root.Path.Value.Should().Be("vfs://");
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.Models;
+
+public class VirtualFileSystemFactoryTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_create_a_virtual_file_system_factory()
+ {
+ // Act
+ var virtualFileSystemFactory = new VirtualFileSystemFactory();
+
+ // Assert
+ virtualFileSystemFactory.Should().NotBeNull();
+ }
+ }
+
+ public class MethodCreateFileSystem
+ {
+ [Fact]
+ public void CreateFileSystem_create_a_virtual_file_system()
+ {
+ // Arrange
+ var virtualFileSystemFactory = new VirtualFileSystemFactory();
+
+ // Act
+ var virtualFileSystem = virtualFileSystemFactory.CreateFileSystem();
+
+ // Assert
+ virtualFileSystem.Should().NotBeNull();
+ virtualFileSystem.Root.Should().NotBeNull();
+ virtualFileSystem.Root.Path.Value.Should().Be("vfs://");
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemTests.cs
index 72f8e47..1217c2e 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/Models/VirtualFileSystemTests.cs
@@ -1,621 +1,621 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-using System.Text.RegularExpressions;
-using Atypical.VirtualFileSystem.Core.Contracts;
-
-namespace VirtualFileSystem.UnitTests.Models;
-
-public class VirtualFileSystemTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_creates_a_new_file_system()
- {
- // Act
- IVirtualFileSystem vfs = new VFS();
-
- // Assert
- vfs.Should().NotBeNull();
- vfs.IsEmpty.Should().BeTrue();
- vfs.Root.IsDirectory.Should().BeTrue();
- vfs.Root.IsFile.Should().BeFalse();
- vfs.Root.Path.Value.Should().Be("vfs://");
- vfs.Root.CreationTime.Should().BeCloseTo(DateTime.Now, TimeSpan.FromHours(1));
- }
- }
-
- public class MethodGetDirectory
- {
- [Fact]
- public void GetDirectory_returns_the_root_directory()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- var rootPath = new VFSRootPath();
-
- // Act
- var root = vfs.GetDirectory(rootPath);
-
- // Assert
- root.Should().NotBeNull();
- root.Path.Value.Should().Be("vfs://");
- }
-
- [Fact]
- public void GetDirectory_returns_a_directory()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
- vfs.CreateDirectory(directoryPath);
-
- // Act
- var directory = vfs.GetDirectory(directoryPath);
-
- // Assert
- directory.Should().NotBeNull();
- directory.Path.Value.Should().Be("vfs://dir1/dir2/dir3");
- }
-
- [Fact]
- public void GetDirectory_throws_an_exception_if_the_directory_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
-
- // Act
- Action action = () => vfs.GetDirectory(directoryPath);
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodTryGetDirectory
- {
- [Fact]
- public void TryGetDirectory_returns_true_if_the_directory_exists()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
- vfs.CreateDirectory(directoryPath);
-
- // Act
- var result = vfs.TryGetDirectory(directoryPath, out var directory);
-
- // Assert
- result.Should().BeTrue();
- directory.Should().NotBeNull();
- directory!.Path.Value.Should().Be("vfs://dir1/dir2/dir3");
- }
-
- [Fact]
- public void TryGetDirectory_returns_false_if_the_directory_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
-
- // Act
- var result = vfs.TryGetDirectory(directoryPath, out var directory);
-
- // Assert
- result.Should().BeFalse();
- directory.Should().BeNull();
- }
- }
-
- public class MethodCreateDirectory
- {
- [Fact]
- public void CreateDirectory_creates_a_directory()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1";
-
- // Act
- vfs.CreateDirectory(directoryPath);
-
- // Assert
- vfs.IsEmpty.Should().BeFalse();
- vfs.Root.IsDirectory.Should().BeTrue();
- vfs.Root.IsFile.Should().BeFalse();
- vfs.Root.Path.Value.Should().Be("vfs://");
- vfs.Root.CreationTime.Should().BeCloseTo(DateTime.Now, TimeSpan.FromHours(1));
- }
-
- [Fact]
- public void CreateDirectory_creates_a_directory_and_its_parents()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
- var path = new VFSDirectoryPath(directoryPath);
-
- // Act
- vfs.CreateDirectory(directoryPath);
-
- // Assert
- vfs.Index.Should().NotBeEmpty();
- vfs.Index.Should().HaveCount(4); // Root + dir1 + dir2 + dir3
- vfs.Index.Should().ContainKey(path.Value);
- vfs.Index.Should().ContainKey("vfs://dir1");
- vfs.Index.Should().ContainKey("vfs://dir1/dir2");
- vfs.Index.Should().ContainKey("vfs://dir1/dir2/dir3");
- }
-
- [Fact]
- public void CreateDirectory_throws_an_exception_if_the_directory_already_exists()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- var directoryPath = new VFSDirectoryPath("dir1");
- vfs.CreateDirectory(directoryPath);
-
- // Act
- Action action = () => vfs.CreateDirectory(directoryPath);
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void CreateDirectory_throws_an_exception_if_the_path_is_not_a_directory()
- {
- // Arrange
- var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
- IVirtualFileSystem vfs = new VFS();
- vfs.CreateFile(filePath);
-
- // Act
- Action action = () => vfs.CreateDirectory(filePath);
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodDeleteDirectory
- {
- [Fact]
- public void DeleteDirectory_deletes_a_directory()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1";
- vfs.CreateDirectory(directoryPath);
-
- // Act
- vfs.DeleteDirectory(directoryPath);
-
- // Assert
- vfs.Index.Count.Should().Be(1); // Root
- }
-
- [Fact]
- public void DeleteDirectory_deletes_a_directory_and_its_children()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1/dir2/dir3";
- vfs.CreateDirectory(directoryPath);
-
- // Act
- vfs.DeleteDirectory("dir1");
-
- // Assert
- vfs.Index.Count.Should().Be(1); // Root
- }
-
- [Fact]
- public void DeleteDirectory_throws_an_exception_if_the_directory_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string directoryPath = "dir1";
-
- // Act
- Action action = () => vfs.DeleteDirectory(directoryPath);
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodFindDirectories
- {
- [Fact]
- public void FindDirectories_returns_all_directories()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- vfs.CreateDirectory("dir1");
- vfs.CreateDirectory("dir2");
- vfs.CreateDirectory("dir3");
-
- // Act
- var directories = vfs.FindDirectories().ToList();
-
- // Assert
- directories.Should().NotBeEmpty();
- directories.Should().HaveCount(4); // Root + dir1 + dir2 + dir3
- directories.Should().Contain(d => d.Path.Value == "vfs://dir1");
- directories.Should().Contain(d => d.Path.Value == "vfs://dir2");
- directories.Should().Contain(d => d.Path.Value == "vfs://dir3");
- }
-
- [Fact]
- public void FindDirectories_returns_all_directories_matching_a_pattern()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- vfs.CreateDirectory("dir1");
- vfs.CreateDirectory("dir2");
- vfs.CreateDirectory("dir3");
-
- // Act
- var regexPattern = new Regex("dir1");
- var directories = vfs.FindDirectories(regexPattern).ToList();
-
- // Assert
- directories.Should().NotBeEmpty();
- directories.Should().HaveCount(1);
- directories.Should().Contain(d => d.Path.Value == "vfs://dir1");
- }
- }
-
- public class MethodGetFile
- {
- [Fact]
- public void GetFile_returns_the_file()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string filePath = "dir1/dir2/dir3/file.txt";
- vfs.CreateFile(filePath);
-
- // Act
- var file = vfs.GetFile(filePath);
-
- // Assert
- file.Should().NotBeNull();
- file.Path.Value.Should().Be("vfs://dir1/dir2/dir3/file.txt");
- }
-
- [Fact]
- public void GetFile_throws_an_exception_if_the_file_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string filePath = "dir1/dir2/dir3/file.txt";
-
- // Act
- Action action = () => vfs.GetFile(filePath);
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodTryGetFile
- {
- [Fact]
- public void TryGetFile_returns_the_file()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string filePath = "dir1/dir2/dir3/file.txt";
- vfs.CreateFile(filePath);
-
- // Act
- var result = vfs.TryGetFile(filePath, out IFileNode? file);
-
- // Assert
- result.Should().BeTrue();
- file.Should().NotBeNull();
- file!.Path.Value.Should().Be("vfs://dir1/dir2/dir3/file.txt");
- }
-
- [Fact]
- public void TryGetFile_returns_false_if_the_file_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- const string filePath = "dir1/dir2/dir3/file.txt";
-
- // Act
- var result = vfs.TryGetFile(filePath, out var file);
-
- // Assert
- result.Should().BeFalse();
- file.Should().BeNull();
- }
- }
-
- public class MethodCreateFile
- {
- [Fact]
- public void CreateFile_creates_a_file()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
-
- // Act
- vfs.CreateFile(new VFSFilePath("dir1/dir2/dir3/file.txt"));
-
- // Assert
- vfs.Index.Count.Should().Be(5); // Root + dir1 + dir2 + dir3 + file.txt
- vfs.Index.Should().ContainKey(new VFSFilePath("dir1/dir2/dir3/file.txt"));
- }
-
- [Fact]
- public void CreateFile_throws_an_exception_if_the_file_already_exists()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
- vfs.CreateFile(filePath);
-
- // Act
- Action action = () => vfs.CreateFile(filePath);
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodDeleteFile
- {
- [Fact]
- public void DeleteFile_deletes_a_file()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
- vfs.CreateFile(filePath);
-
- // Act
- vfs.DeleteFile(filePath);
-
- // Assert
- vfs.Index.Count.Should().Be(4); // Root, dir1, dir2, dir3
- }
-
- [Fact]
- public void DeleteFile_throws_an_exception_if_the_file_does_not_exist()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
-
- // Act
- Action action = () => vfs.DeleteFile("dir1/dir2/dir3/file.txt");
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodFindFiles
- {
- [Fact]
- public void FindFiles_returns_all_files()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- vfs.CreateDirectory("dir1");
- vfs.CreateDirectory("dir2");
- vfs.CreateDirectory("dir3");
- vfs.CreateFile("dir1/file1.txt");
- vfs.CreateFile("dir2/file2.txt");
- vfs.CreateFile("dir3/file3.txt");
-
- // Act
- var files = vfs.FindFiles().ToList();
-
- // Assert
- files.Should().NotBeEmpty();
- files.Should().HaveCount(3);
- files.Should().Contain(f => f.Path.Value == "vfs://dir1/file1.txt");
- files.Should().Contain(f => f.Path.Value == "vfs://dir2/file2.txt");
- files.Should().Contain(f => f.Path.Value == "vfs://dir3/file3.txt");
- }
-
- [Fact]
- public void FindFiles_with_valid_data_returns_a_list_of_files_with_content_and_name()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
- vfs.CreateFile("file1.txt", "content1");
- vfs.CreateFile("file2.txt", "content2");
- vfs.CreateFile("file3.txt", "content3");
-
- Regex regex = new Regex(@"file\d.txt");
-
- // Act
- var files = vfs.FindFiles(regex).ToList();
-
- // Assert
- files.Should().NotBeNull();
- files.Count.Should().Be(3);
- files[0].Name.Should().Be("file1.txt");
- files[0].Content.Should().Be("content1");
- files[1].Name.Should().Be("file2.txt");
- files[1].Content.Should().Be("content2");
- files[2].Name.Should().Be("file3.txt");
- files[2].Content.Should().Be("content3");
- // Assert Index
- vfs.Index.Count.Should().Be(4); // Root, file1, file2, file3
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_returns_root_directory()
- {
- // Arrange
- IVirtualFileSystem vfs = new VFS();
-
- // Act
- var result = vfs.ToString();
-
- // Assert
- result.Should().Be("vfs://");
- }
-
- [Fact]
- public void ToString_returns_3_files_as_ASCII_tree()
- {
- // Arrange
- string expected = """
- vfs://
- ├── file1.txt
- ├── file2.txt
- └── file3.txt
- """
- .Replace("\r", "");
-
- IVirtualFileSystem vfs = new VFS()
- .CreateFile("file1.txt")
- .CreateFile("file2.txt")
- .CreateFile("file3.txt");
-
- // Act
- var result = vfs.ToString();
-
- // Assert
- result.Should().Be(expected);
- }
-
- [Fact]
- public void ToString_returns_3_directories_as_ASCII_tree()
- {
- // Arrange
- string expected = """
- vfs://
- ├── dir1
- ├── dir2
- └── dir3
- """
- .Replace("\r", "");
-
- IVirtualFileSystem vfs = new VFS()
- .CreateDirectory("dir1")
- .CreateDirectory("dir2")
- .CreateDirectory("dir3");
-
- // Act
- var result = vfs.ToString();
-
- // Assert
- result.Should().Be(expected);
- }
-
- [Fact]
- public void ToString_returns_3_files_and_3_directories_as_ASCII_tree()
- {
- // Arrange
- string expected = """
- vfs://
- ├── dir1
- │ ├── file1.txt
- │ ├── file2.txt
- │ └── file3.txt
- ├── dir2
- │ ├── file1.txt
- │ ├── file2.txt
- │ └── file3.txt
- └── dir3
- ├── file1.txt
- ├── file2.txt
- └── file3.txt
- """
- .Replace("\r", "");
-
- IVirtualFileSystem vfs = new VFS()
- .CreateFile("dir1/file1.txt")
- .CreateFile("dir1/file2.txt")
- .CreateFile("dir1/file3.txt")
- .CreateFile("dir2/file1.txt")
- .CreateFile("dir2/file2.txt")
- .CreateFile("dir2/file3.txt")
- .CreateFile("dir3/file1.txt")
- .CreateFile("dir3/file2.txt")
- .CreateFile("dir3/file3.txt");
-
- // Act
- var result = vfs.ToString();
-
- // Assert
- result.Should().Be(expected);
- }
-
- [Fact]
- public void ToString_returns_a_complex_tree()
- {
- // Arrange
- string expected = """
- vfs://
- ├── dir1
- │ ├── dir2
- │ │ ├── dir3
- │ │ │ ├── file1.txt
- │ │ │ ├── file2.txt
- │ │ │ └── file3.txt
- │ │ ├── file1.txt
- │ │ ├── file2.txt
- │ │ └── file3.txt
- │ ├── file1.txt
- │ ├── file2.txt
- │ └── file3.txt
- ├── dir2
- │ ├── dir3
- │ │ ├── file1.txt
- │ │ ├── file2.txt
- │ │ └── file3.txt
- │ ├── file1.txt
- │ ├── file2.txt
- │ └── file3.txt
- └── dir3
- ├── file1.txt
- ├── file2.txt
- └── file3.txt
- """
- .Replace("\r", "");
-
- IVirtualFileSystem vfs = new VFS()
- .CreateFile("dir1/dir2/dir3/file1.txt")
- .CreateFile("dir1/dir2/dir3/file2.txt")
- .CreateFile("dir1/dir2/dir3/file3.txt")
- .CreateFile("dir1/dir2/file1.txt")
- .CreateFile("dir1/dir2/file2.txt")
- .CreateFile("dir1/dir2/file3.txt")
- .CreateFile("dir1/file1.txt")
- .CreateFile("dir1/file2.txt")
- .CreateFile("dir1/file3.txt")
- .CreateFile("dir2/dir3/file1.txt")
- .CreateFile("dir2/dir3/file2.txt")
- .CreateFile("dir2/dir3/file3.txt")
- .CreateFile("dir2/file1.txt")
- .CreateFile("dir2/file2.txt")
- .CreateFile("dir2/file3.txt")
- .CreateFile("dir3/file1.txt")
- .CreateFile("dir3/file2.txt")
- .CreateFile("dir3/file3.txt");
-
- // Act
- var result = vfs.ToString();
-
- // Assert
- result.Should().Be(expected);
- }
- }
-}
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+using Atypical.VirtualFileSystem.Core.Contracts;
+using System.Text.RegularExpressions;
+
+namespace VirtualFileSystem.UnitTests.Models;
+
+public class VirtualFileSystemTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_creates_a_new_file_system()
+ {
+ // Act
+ IVirtualFileSystem vfs = new VFS();
+
+ // Assert
+ vfs.Should().NotBeNull();
+ vfs.IsEmpty.Should().BeTrue();
+ vfs.Root.IsDirectory.Should().BeTrue();
+ vfs.Root.IsFile.Should().BeFalse();
+ vfs.Root.Path.Value.Should().Be("vfs://");
+ vfs.Root.CreationTime.Should().BeCloseTo(DateTime.Now, TimeSpan.FromHours(1));
+ }
+ }
+
+ public class MethodGetDirectory
+ {
+ [Fact]
+ public void GetDirectory_returns_the_root_directory()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ var rootPath = new VFSRootPath();
+
+ // Act
+ var root = vfs.GetDirectory(rootPath);
+
+ // Assert
+ root.Should().NotBeNull();
+ root.Path.Value.Should().Be("vfs://");
+ }
+
+ [Fact]
+ public void GetDirectory_returns_a_directory()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+ vfs.CreateDirectory(directoryPath);
+
+ // Act
+ var directory = vfs.GetDirectory(directoryPath);
+
+ // Assert
+ directory.Should().NotBeNull();
+ directory.Path.Value.Should().Be("vfs://dir1/dir2/dir3");
+ }
+
+ [Fact]
+ public void GetDirectory_throws_an_exception_if_the_directory_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+
+ // Act
+ Action action = () => vfs.GetDirectory(directoryPath);
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodTryGetDirectory
+ {
+ [Fact]
+ public void TryGetDirectory_returns_true_if_the_directory_exists()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+ vfs.CreateDirectory(directoryPath);
+
+ // Act
+ var result = vfs.TryGetDirectory(directoryPath, out var directory);
+
+ // Assert
+ result.Should().BeTrue();
+ directory.Should().NotBeNull();
+ directory!.Path.Value.Should().Be("vfs://dir1/dir2/dir3");
+ }
+
+ [Fact]
+ public void TryGetDirectory_returns_false_if_the_directory_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+
+ // Act
+ var result = vfs.TryGetDirectory(directoryPath, out var directory);
+
+ // Assert
+ result.Should().BeFalse();
+ directory.Should().BeNull();
+ }
+ }
+
+ public class MethodCreateDirectory
+ {
+ [Fact]
+ public void CreateDirectory_creates_a_directory()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1";
+
+ // Act
+ vfs.CreateDirectory(directoryPath);
+
+ // Assert
+ vfs.IsEmpty.Should().BeFalse();
+ vfs.Root.IsDirectory.Should().BeTrue();
+ vfs.Root.IsFile.Should().BeFalse();
+ vfs.Root.Path.Value.Should().Be("vfs://");
+ vfs.Root.CreationTime.Should().BeCloseTo(DateTime.Now, TimeSpan.FromHours(1));
+ }
+
+ [Fact]
+ public void CreateDirectory_creates_a_directory_and_its_parents()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+ var path = new VFSDirectoryPath(directoryPath);
+
+ // Act
+ vfs.CreateDirectory(directoryPath);
+
+ // Assert
+ vfs.Index.Should().NotBeEmpty();
+ vfs.Index.Should().HaveCount(4); // Root + dir1 + dir2 + dir3
+ vfs.Index.Should().ContainKey(path.Value);
+ vfs.Index.Should().ContainKey("vfs://dir1");
+ vfs.Index.Should().ContainKey("vfs://dir1/dir2");
+ vfs.Index.Should().ContainKey("vfs://dir1/dir2/dir3");
+ }
+
+ [Fact]
+ public void CreateDirectory_throws_an_exception_if_the_directory_already_exists()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ var directoryPath = new VFSDirectoryPath("dir1");
+ vfs.CreateDirectory(directoryPath);
+
+ // Act
+ Action action = () => vfs.CreateDirectory(directoryPath);
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void CreateDirectory_throws_an_exception_if_the_path_is_not_a_directory()
+ {
+ // Arrange
+ var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
+ IVirtualFileSystem vfs = new VFS();
+ vfs.CreateFile(filePath);
+
+ // Act
+ Action action = () => vfs.CreateDirectory(filePath);
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodDeleteDirectory
+ {
+ [Fact]
+ public void DeleteDirectory_deletes_a_directory()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1";
+ vfs.CreateDirectory(directoryPath);
+
+ // Act
+ vfs.DeleteDirectory(directoryPath);
+
+ // Assert
+ vfs.Index.Count.Should().Be(1); // Root
+ }
+
+ [Fact]
+ public void DeleteDirectory_deletes_a_directory_and_its_children()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1/dir2/dir3";
+ vfs.CreateDirectory(directoryPath);
+
+ // Act
+ vfs.DeleteDirectory("dir1");
+
+ // Assert
+ vfs.Index.Count.Should().Be(1); // Root
+ }
+
+ [Fact]
+ public void DeleteDirectory_throws_an_exception_if_the_directory_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string directoryPath = "dir1";
+
+ // Act
+ Action action = () => vfs.DeleteDirectory(directoryPath);
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodFindDirectories
+ {
+ [Fact]
+ public void FindDirectories_returns_all_directories()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ vfs.CreateDirectory("dir1");
+ vfs.CreateDirectory("dir2");
+ vfs.CreateDirectory("dir3");
+
+ // Act
+ var directories = vfs.FindDirectories().ToList();
+
+ // Assert
+ directories.Should().NotBeEmpty();
+ directories.Should().HaveCount(4); // Root + dir1 + dir2 + dir3
+ directories.Should().Contain(d => d.Path.Value == "vfs://dir1");
+ directories.Should().Contain(d => d.Path.Value == "vfs://dir2");
+ directories.Should().Contain(d => d.Path.Value == "vfs://dir3");
+ }
+
+ [Fact]
+ public void FindDirectories_returns_all_directories_matching_a_pattern()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ vfs.CreateDirectory("dir1");
+ vfs.CreateDirectory("dir2");
+ vfs.CreateDirectory("dir3");
+
+ // Act
+ var regexPattern = new Regex("dir1");
+ var directories = vfs.FindDirectories(regexPattern).ToList();
+
+ // Assert
+ directories.Should().NotBeEmpty();
+ directories.Should().HaveCount(1);
+ directories.Should().Contain(d => d.Path.Value == "vfs://dir1");
+ }
+ }
+
+ public class MethodGetFile
+ {
+ [Fact]
+ public void GetFile_returns_the_file()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string filePath = "dir1/dir2/dir3/file.txt";
+ vfs.CreateFile(filePath);
+
+ // Act
+ var file = vfs.GetFile(filePath);
+
+ // Assert
+ file.Should().NotBeNull();
+ file.Path.Value.Should().Be("vfs://dir1/dir2/dir3/file.txt");
+ }
+
+ [Fact]
+ public void GetFile_throws_an_exception_if_the_file_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string filePath = "dir1/dir2/dir3/file.txt";
+
+ // Act
+ Action action = () => vfs.GetFile(filePath);
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodTryGetFile
+ {
+ [Fact]
+ public void TryGetFile_returns_the_file()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string filePath = "dir1/dir2/dir3/file.txt";
+ vfs.CreateFile(filePath);
+
+ // Act
+ var result = vfs.TryGetFile(filePath, out var file);
+
+ // Assert
+ result.Should().BeTrue();
+ file.Should().NotBeNull();
+ file!.Path.Value.Should().Be("vfs://dir1/dir2/dir3/file.txt");
+ }
+
+ [Fact]
+ public void TryGetFile_returns_false_if_the_file_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ const string filePath = "dir1/dir2/dir3/file.txt";
+
+ // Act
+ var result = vfs.TryGetFile(filePath, out var file);
+
+ // Assert
+ result.Should().BeFalse();
+ file.Should().BeNull();
+ }
+ }
+
+ public class MethodCreateFile
+ {
+ [Fact]
+ public void CreateFile_creates_a_file()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+
+ // Act
+ vfs.CreateFile(new VFSFilePath("dir1/dir2/dir3/file.txt"));
+
+ // Assert
+ vfs.Index.Count.Should().Be(5); // Root + dir1 + dir2 + dir3 + file.txt
+ vfs.Index.Should().ContainKey(new VFSFilePath("dir1/dir2/dir3/file.txt"));
+ }
+
+ [Fact]
+ public void CreateFile_throws_an_exception_if_the_file_already_exists()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
+ vfs.CreateFile(filePath);
+
+ // Act
+ Action action = () => vfs.CreateFile(filePath);
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodDeleteFile
+ {
+ [Fact]
+ public void DeleteFile_deletes_a_file()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ var filePath = new VFSFilePath("dir1/dir2/dir3/file.txt");
+ vfs.CreateFile(filePath);
+
+ // Act
+ vfs.DeleteFile(filePath);
+
+ // Assert
+ vfs.Index.Count.Should().Be(4); // Root, dir1, dir2, dir3
+ }
+
+ [Fact]
+ public void DeleteFile_throws_an_exception_if_the_file_does_not_exist()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+
+ // Act
+ Action action = () => vfs.DeleteFile("dir1/dir2/dir3/file.txt");
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodFindFiles
+ {
+ [Fact]
+ public void FindFiles_returns_all_files()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ vfs.CreateDirectory("dir1");
+ vfs.CreateDirectory("dir2");
+ vfs.CreateDirectory("dir3");
+ vfs.CreateFile("dir1/file1.txt");
+ vfs.CreateFile("dir2/file2.txt");
+ vfs.CreateFile("dir3/file3.txt");
+
+ // Act
+ var files = vfs.FindFiles().ToList();
+
+ // Assert
+ files.Should().NotBeEmpty();
+ files.Should().HaveCount(3);
+ files.Should().Contain(f => f.Path.Value == "vfs://dir1/file1.txt");
+ files.Should().Contain(f => f.Path.Value == "vfs://dir2/file2.txt");
+ files.Should().Contain(f => f.Path.Value == "vfs://dir3/file3.txt");
+ }
+
+ [Fact]
+ public void FindFiles_with_valid_data_returns_a_list_of_files_with_content_and_name()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+ vfs.CreateFile("file1.txt", "content1");
+ vfs.CreateFile("file2.txt", "content2");
+ vfs.CreateFile("file3.txt", "content3");
+
+ var regex = new Regex(@"file\d.txt");
+
+ // Act
+ var files = vfs.FindFiles(regex).ToList();
+
+ // Assert
+ files.Should().NotBeNull();
+ files.Count.Should().Be(3);
+ files[0].Name.Should().Be("file1.txt");
+ files[0].Content.Should().Be("content1");
+ files[1].Name.Should().Be("file2.txt");
+ files[1].Content.Should().Be("content2");
+ files[2].Name.Should().Be("file3.txt");
+ files[2].Content.Should().Be("content3");
+ // Assert Index
+ vfs.Index.Count.Should().Be(4); // Root, file1, file2, file3
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_returns_root_directory()
+ {
+ // Arrange
+ IVirtualFileSystem vfs = new VFS();
+
+ // Act
+ var result = vfs.ToString();
+
+ // Assert
+ result.Should().Be("vfs://");
+ }
+
+ [Fact]
+ public void ToString_returns_3_files_as_ASCII_tree()
+ {
+ // Arrange
+ var expected = """
+ vfs://
+ ├── file1.txt
+ ├── file2.txt
+ └── file3.txt
+ """
+ .Replace("\r", "");
+
+ var vfs = new VFS()
+ .CreateFile("file1.txt")
+ .CreateFile("file2.txt")
+ .CreateFile("file3.txt");
+
+ // Act
+ var result = vfs.ToString();
+
+ // Assert
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void ToString_returns_3_directories_as_ASCII_tree()
+ {
+ // Arrange
+ var expected = """
+ vfs://
+ ├── dir1
+ ├── dir2
+ └── dir3
+ """
+ .Replace("\r", "");
+
+ var vfs = new VFS()
+ .CreateDirectory("dir1")
+ .CreateDirectory("dir2")
+ .CreateDirectory("dir3");
+
+ // Act
+ var result = vfs.ToString();
+
+ // Assert
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void ToString_returns_3_files_and_3_directories_as_ASCII_tree()
+ {
+ // Arrange
+ var expected = """
+ vfs://
+ ├── dir1
+ │ ├── file1.txt
+ │ ├── file2.txt
+ │ └── file3.txt
+ ├── dir2
+ │ ├── file1.txt
+ │ ├── file2.txt
+ │ └── file3.txt
+ └── dir3
+ ├── file1.txt
+ ├── file2.txt
+ └── file3.txt
+ """
+ .Replace("\r", "");
+
+ var vfs = new VFS()
+ .CreateFile("dir1/file1.txt")
+ .CreateFile("dir1/file2.txt")
+ .CreateFile("dir1/file3.txt")
+ .CreateFile("dir2/file1.txt")
+ .CreateFile("dir2/file2.txt")
+ .CreateFile("dir2/file3.txt")
+ .CreateFile("dir3/file1.txt")
+ .CreateFile("dir3/file2.txt")
+ .CreateFile("dir3/file3.txt");
+
+ // Act
+ var result = vfs.ToString();
+
+ // Assert
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void ToString_returns_a_complex_tree()
+ {
+ // Arrange
+ var expected = """
+ vfs://
+ ├── dir1
+ │ ├── dir2
+ │ │ ├── dir3
+ │ │ │ ├── file1.txt
+ │ │ │ ├── file2.txt
+ │ │ │ └── file3.txt
+ │ │ ├── file1.txt
+ │ │ ├── file2.txt
+ │ │ └── file3.txt
+ │ ├── file1.txt
+ │ ├── file2.txt
+ │ └── file3.txt
+ ├── dir2
+ │ ├── dir3
+ │ │ ├── file1.txt
+ │ │ ├── file2.txt
+ │ │ └── file3.txt
+ │ ├── file1.txt
+ │ ├── file2.txt
+ │ └── file3.txt
+ └── dir3
+ ├── file1.txt
+ ├── file2.txt
+ └── file3.txt
+ """
+ .Replace("\r", "");
+
+ var vfs = new VFS()
+ .CreateFile("dir1/dir2/dir3/file1.txt")
+ .CreateFile("dir1/dir2/dir3/file2.txt")
+ .CreateFile("dir1/dir2/dir3/file3.txt")
+ .CreateFile("dir1/dir2/file1.txt")
+ .CreateFile("dir1/dir2/file2.txt")
+ .CreateFile("dir1/dir2/file3.txt")
+ .CreateFile("dir1/file1.txt")
+ .CreateFile("dir1/file2.txt")
+ .CreateFile("dir1/file3.txt")
+ .CreateFile("dir2/dir3/file1.txt")
+ .CreateFile("dir2/dir3/file2.txt")
+ .CreateFile("dir2/dir3/file3.txt")
+ .CreateFile("dir2/file1.txt")
+ .CreateFile("dir2/file2.txt")
+ .CreateFile("dir2/file3.txt")
+ .CreateFile("dir3/file1.txt")
+ .CreateFile("dir3/file2.txt")
+ .CreateFile("dir3/file3.txt");
+
+ // Act
+ var result = vfs.ToString();
+
+ // Assert
+ result.Should().Be(expected);
+ }
+ }
+}
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSDirectoryPathTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSDirectoryPathTests.cs
index a3d2c3c..039f913 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSDirectoryPathTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSDirectoryPathTests.cs
@@ -1,294 +1,294 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.ValueObjects;
-
-public class VFSDirectoryPathTests
-{
- public class Constructor
- {
- // Business rules:
- // - The path must not be null or empty.
- // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
- // - The path must not contain any relative path segments (..).
- // - The path must not contain any consecutive slashes (//).
-
- [Fact]
- public void Constructor_throw_ArgumentNullException_when_path_is_null()
- {
- // Arrange
- const string path = null!;
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path!);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_is_empty()
- {
- // Arrange
- const string path = "";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
- {
- // Arrange
- const string path = @"invalid\path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_relative_path_segments()
- {
- // Arrange
- const string path = @"invalid\..\path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_consecutive_slashes()
- {
- // Arrange
- const string path = @"invalid//path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_is_not_a_directory_path()
- {
- // Arrange
- const string path = @"invalid/path.txt";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid()
- {
- // Arrange
- const string path = @"valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_contains_uppercase_characters()
- {
- // Arrange
- const string path = @"valid/PATH";
- const string expectedPath = @"vfs://valid/PATH";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_contains_numbers()
- {
- // Arrange
- const string path = @"valid/123";
- const string expectedPath = @"vfs://valid/123";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_has_leading_slash()
- {
- // Arrange
- const string path = @"/valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_for_root_directory()
- {
- // Arrange
- const string path = @"/";
- const string expectedPath = @"vfs://";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- directoryPath.IsRoot.Should().BeTrue();
- directoryPath.Parent.Should().BeNull();
- }
-
- [Fact]
- public void Constructor_create_instance_for_simple_directory()
- {
- // Arrange
- const string path = @"/valid";
- const string expectedPath = @"vfs://valid";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- directoryPath.IsRoot.Should().BeFalse();
- directoryPath.Parent.Should().NotBeNull();
- directoryPath.Parent!.Value.Should().Be(@"vfs://");
- }
-
- [Fact]
- public void Constructor_create_instance_for_nested_directory()
- {
- // Arrange
- const string path = @"/valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var directoryPath = new VFSDirectoryPath(path);
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- directoryPath.IsRoot.Should().BeFalse();
- directoryPath.Parent.Should().NotBeNull();
- directoryPath.Parent!.Value.Should().Be(@"vfs://valid");
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_return_path()
- {
- // Arrange
- const string path = @"test";
- const string expectedPath = @"vfs://test";
- var directoryPath = new VFSDirectoryPath(path);
-
- // Act
- var result = directoryPath.ToString();
-
- // Assert
- result.Should().Be(expectedPath);
- }
-
- [Fact]
- public void ToString_return_path_with_vfs_prefix()
- {
- // Arrange
- const string path = @"valid/path";
- var directoryPath = new VFSDirectoryPath(path);
-
- // Act
- var result = directoryPath.ToString();
-
- // Assert
- result.Should().Be($"vfs://{path}");
- }
- }
-
- public class ImplicitOperator
- {
- [Fact]
- public void ImplicitOperator_ToString_returns_value()
- {
- // Arrange
- var directoryPath = new VFSDirectoryPath("valid/path");
- const string expectedPath = "vfs://valid/path";
-
- // Act
- string result = directoryPath;
-
- // Assert
- result.Should().Be(expectedPath);
- }
- }
-
- public class Equality
- {
- [Fact]
- public void Equals_returns_true_when_paths_are_equal()
- {
- // Arrange
- var directoryPath1 = new VFSDirectoryPath("valid/path");
- var directoryPath2 = new VFSDirectoryPath("valid/path");
-
- // Act
- var result = directoryPath1.Equals(directoryPath2);
-
- // Assert
- result.Should().BeTrue();
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.ValueObjects;
+
+public class VFSDirectoryPathTests
+{
+ public class Constructor
+ {
+ // Business rules:
+ // - The path must not be null or empty.
+ // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
+ // - The path must not contain any relative path segments (..).
+ // - The path must not contain any consecutive slashes (//).
+
+ [Fact]
+ public void Constructor_throw_ArgumentNullException_when_path_is_null()
+ {
+ // Arrange
+ const string path = null!;
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path!);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_is_empty()
+ {
+ // Arrange
+ const string path = "";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
+ {
+ // Arrange
+ const string path = @"invalid\path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_relative_path_segments()
+ {
+ // Arrange
+ const string path = @"invalid\..\path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_consecutive_slashes()
+ {
+ // Arrange
+ const string path = @"invalid//path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_is_not_a_directory_path()
+ {
+ // Arrange
+ const string path = @"invalid/path.txt";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_contains_uppercase_characters()
+ {
+ // Arrange
+ const string path = @"valid/PATH";
+ const string expectedPath = @"vfs://valid/PATH";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_contains_numbers()
+ {
+ // Arrange
+ const string path = @"valid/123";
+ const string expectedPath = @"vfs://valid/123";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_has_leading_slash()
+ {
+ // Arrange
+ const string path = @"/valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_for_root_directory()
+ {
+ // Arrange
+ const string path = @"/";
+ const string expectedPath = @"vfs://";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ directoryPath.IsRoot.Should().BeTrue();
+ directoryPath.Parent.Should().BeNull();
+ }
+
+ [Fact]
+ public void Constructor_create_instance_for_simple_directory()
+ {
+ // Arrange
+ const string path = @"/valid";
+ const string expectedPath = @"vfs://valid";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ directoryPath.IsRoot.Should().BeFalse();
+ directoryPath.Parent.Should().NotBeNull();
+ directoryPath.Parent!.Value.Should().Be(@"vfs://");
+ }
+
+ [Fact]
+ public void Constructor_create_instance_for_nested_directory()
+ {
+ // Arrange
+ const string path = @"/valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ directoryPath.IsRoot.Should().BeFalse();
+ directoryPath.Parent.Should().NotBeNull();
+ directoryPath.Parent!.Value.Should().Be(@"vfs://valid");
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_return_path()
+ {
+ // Arrange
+ const string path = @"test";
+ const string expectedPath = @"vfs://test";
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Act
+ var result = directoryPath.ToString();
+
+ // Assert
+ result.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void ToString_return_path_with_vfs_prefix()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ var directoryPath = new VFSDirectoryPath(path);
+
+ // Act
+ var result = directoryPath.ToString();
+
+ // Assert
+ result.Should().Be($"vfs://{path}");
+ }
+ }
+
+ public class ImplicitOperator
+ {
+ [Fact]
+ public void ImplicitOperator_ToString_returns_value()
+ {
+ // Arrange
+ var directoryPath = new VFSDirectoryPath("valid/path");
+ const string expectedPath = "vfs://valid/path";
+
+ // Act
+ string result = directoryPath;
+
+ // Assert
+ result.Should().Be(expectedPath);
+ }
+ }
+
+ public class Equality
+ {
+ [Fact]
+ public void Equals_returns_true_when_paths_are_equal()
+ {
+ // Arrange
+ var directoryPath1 = new VFSDirectoryPath("valid/path");
+ var directoryPath2 = new VFSDirectoryPath("valid/path");
+
+ // Act
+ var result = directoryPath1.Equals(directoryPath2);
+
+ // Assert
+ result.Should().BeTrue();
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSFilePathTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSFilePathTests.cs
index c3e67dd..fbeefab 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSFilePathTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSFilePathTests.cs
@@ -1,137 +1,137 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.ValueObjects;
-
-public class VFSFilePathTests
-{
- public class Constructor
- {
- // Business rules:
- // - The path must not be null or empty.
- // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
- // - The path must not contain any relative path segments (..).
- // - The path must not contain any consecutive slashes (//).
- // - The path must not end with a slash (/).
-
- [Fact]
- public void Constructor_throw_ArgumentNullException_when_path_is_null()
- {
- // Arrange
- const string path = null!;
-
- // Act
- Action action = () =>
- {
- var _ = new VFSFilePath(path!);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_is_empty()
- {
- // Arrange
- const string path = "";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSFilePath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
- {
- // Arrange
- const string path = @"invalid\path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSFilePath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_returns_value()
- {
- // Arrange
- var filePath = new VFSFilePath("valid/path");
- const string expectedPath = "vfs://valid/path";
-
- // Act
- var result = filePath.ToString();
-
- // Assert
- result.Should().Be(expectedPath);
- }
- }
-
- public class MethodGetHashCode
- {
- [Fact]
- public void GetHashCode_returns_same_value_for_same_path()
- {
- // Arrange
- var filePath1 = new VFSFilePath("valid/path");
- var filePath2 = new VFSFilePath("valid/path");
-
- // Act
- var hashCode1 = filePath1.GetHashCode();
- var hashCode2 = filePath2.GetHashCode();
-
- // Assert
- hashCode1.Should().Be(hashCode2);
- }
- }
-
- public class ImplicitOperator
- {
- [Fact]
- public void ImplicitOperator_ToString_returns_value()
- {
- // Arrange
- var filePath = new VFSFilePath("valid/path/file.txt");
- const string expectedPath = "vfs://valid/path/file.txt";
-
- // Act
- string result = filePath;
-
- // Assert
- result.Should().Be(expectedPath);
- }
- }
-
- public class Equality
- {
- [Fact]
- public void Equals_returns_true_when_paths_are_equal()
- {
- // Arrange
- var filePath1 = new VFSFilePath("valid/path");
- var filePath2 = new VFSFilePath("valid/path");
-
- // Act
- var result = filePath1.Equals(filePath2);
-
- // Assert
- result.Should().BeTrue();
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.ValueObjects;
+
+public class VFSFilePathTests
+{
+ public class Constructor
+ {
+ // Business rules:
+ // - The path must not be null or empty.
+ // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
+ // - The path must not contain any relative path segments (..).
+ // - The path must not contain any consecutive slashes (//).
+ // - The path must not end with a slash (/).
+
+ [Fact]
+ public void Constructor_throw_ArgumentNullException_when_path_is_null()
+ {
+ // Arrange
+ const string path = null!;
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSFilePath(path!);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_is_empty()
+ {
+ // Arrange
+ const string path = "";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSFilePath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
+ {
+ // Arrange
+ const string path = @"invalid\path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSFilePath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_returns_value()
+ {
+ // Arrange
+ var filePath = new VFSFilePath("valid/path");
+ const string expectedPath = "vfs://valid/path";
+
+ // Act
+ var result = filePath.ToString();
+
+ // Assert
+ result.Should().Be(expectedPath);
+ }
+ }
+
+ public class MethodGetHashCode
+ {
+ [Fact]
+ public void GetHashCode_returns_same_value_for_same_path()
+ {
+ // Arrange
+ var filePath1 = new VFSFilePath("valid/path");
+ var filePath2 = new VFSFilePath("valid/path");
+
+ // Act
+ var hashCode1 = filePath1.GetHashCode();
+ var hashCode2 = filePath2.GetHashCode();
+
+ // Assert
+ hashCode1.Should().Be(hashCode2);
+ }
+ }
+
+ public class ImplicitOperator
+ {
+ [Fact]
+ public void ImplicitOperator_ToString_returns_value()
+ {
+ // Arrange
+ var filePath = new VFSFilePath("valid/path/file.txt");
+ const string expectedPath = "vfs://valid/path/file.txt";
+
+ // Act
+ string result = filePath;
+
+ // Assert
+ result.Should().Be(expectedPath);
+ }
+ }
+
+ public class Equality
+ {
+ [Fact]
+ public void Equals_returns_true_when_paths_are_equal()
+ {
+ // Arrange
+ var filePath1 = new VFSFilePath("valid/path");
+ var filePath2 = new VFSFilePath("valid/path");
+
+ // Act
+ var result = filePath1.Equals(filePath2);
+
+ // Assert
+ result.Should().BeTrue();
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSPathTest.cs b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSPathTest.cs
index 7a565a4..5ba751a 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSPathTest.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSPathTest.cs
@@ -1,478 +1,478 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.ValueObjects;
-
-public class VFSPathTest
-{
- public class Constructor
- {
- // Business rules:
- // - The path must not be null or empty.
- // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
- // - The path must not contain any relative path segments (..).
- // - The path must not contain any consecutive slashes (//).
- // - The path must not end with a slash (/).
-
- [Fact]
- public void Constructor_throw_ArgumentNullException_when_path_is_null()
- {
- // Arrange
- const string path = null!;
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path!);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_is_empty()
- {
- // Arrange
- const string path = "";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
- {
- // Arrange
- const string path = @"invalid\path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_relative_path_segments()
- {
- // Arrange
- const string path = @"invalid/../path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_throw_ArgumentException_when_path_contains_consecutive_slashes()
- {
- // Arrange
- const string path = @"invalid//path";
-
- // Act
- Action action = () =>
- {
- var _ = new VFSDirectoryPath(path);
- };
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid()
- {
- // Arrange
- const string path = @"valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Value.Should().NotBeNull();
- vfsPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_ends_with_slash()
- {
- // Arrange
- const string path = @"valid/path/";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Value.Should().NotBeNull();
- vfsPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_starts_with_slash()
- {
- // Arrange
- const string path = @"/valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Value.Should().NotBeNull();
- vfsPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_starts_and_ends_with_slash()
- {
- // Arrange
- const string path = @"/valid/path/";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Value.Should().NotBeNull();
- vfsPath.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void PropertyParentPath_return_null_when_path_is_root()
- {
- // Arrange
- const string path = @"/";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Parent.Should().BeNull();
- }
-
- [Fact]
- public void Constructor_create_instance_when_path_is_valid_and_has_parent()
- {
- // Arrange
- const string path = @"valid/path";
- const string expectedPath = @"vfs://valid/path";
- const string expectedParentPath = @"vfs://valid";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Value.Should().NotBeNull();
- vfsPath.Value.Should().Be(expectedPath);
- vfsPath.Parent.Should().NotBeNull();
- vfsPath.Parent!.Value.Should().Be(expectedParentPath);
- }
- }
-
- public class PropertyName
- {
- [Fact]
- public void PropertyName_return_name_of_directory()
- {
- // Arrange
- const string path = @"valid/path";
- const string expectedName = @"path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Name.Should().Be(expectedName);
- }
-
- [Fact]
- public void PropertyName_return_name_of_file()
- {
- // Arrange
- const string path = @"valid/path/file.txt";
- const string expectedName = @"file.txt";
-
- // Act
- var vfsPath = new VFSFilePath(path);
-
- // Assert
- vfsPath.Name.Should().Be(expectedName);
- }
-
- [Fact]
- public void PropertyName_return_name_of_root_directory()
- {
- // Arrange
- const string path = @"/";
- const string expectedName = @"vfs://";
-
- // Act
- var vfsPath = new VFSFilePath(path);
-
- // Assert
- vfsPath.Name.Should().Be(expectedName);
- }
- }
-
- public class PropertyDepth
- {
- [Fact]
- public void PropertyDepth_return_0_when_path_is_root()
- {
- // Arrange
- const string path = @"/";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Depth.Should().Be(0);
- }
-
- [Fact]
- public void PropertyDepth_return_1_with_one_directory()
- {
- // Arrange
- const string path = @"directory";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Depth.Should().Be(1);
- }
-
- [Fact]
- public void PropertyDepth_return_2_with_two_directories()
- {
- // Arrange
- const string path = @"directory/subdirectory";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Depth.Should().Be(2);
- }
-
- [Fact]
- public void PropertyDepth_return_3_with_three_directories()
- {
- // Arrange
- const string path = @"directory/subdirectory/subsubdirectory";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.Depth.Should().Be(3);
- }
- }
-
- public class PropertyHasParent
- {
- [Fact]
- public void PropertyHasParent_return_false_when_path_is_root()
- {
- // Arrange
- const string path = @"/";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.HasParent.Should().BeFalse();
- }
-
- [Fact]
- public void PropertyHasParent_return_true_when_path_has_parent()
- {
- // Arrange
- const string path = @"directory/subdirectory";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.HasParent.Should().BeTrue();
- }
- }
-
- public class MethodGetAbsoluteParentPath
- {
- [Fact]
- public void MethodGetAbsoluteParentPath_return_root_when_path_is_root()
- {
- // Arrange
- const string path = @"/";
- const string expectedPath = @"vfs://";
- var vfsPath = new VFSDirectoryPath(path);
-
- // Act
- var parent = vfsPath.GetAbsoluteParentPath(0);
-
- // Assert
- parent.Should().NotBeNull();
- parent.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void MethodGetAbsoluteParentPath_throw_exception_when_depth_is_negative()
- {
- // Arrange
- const string path = @"directory/subdirectory";
- var vfsPath = new VFSDirectoryPath(path);
-
- // Act
- Action action = () => vfsPath.GetAbsoluteParentPath(-1);
-
- // Assert
- action.Should().Throw();
- }
-
- [Fact]
- public void MethodGetAbsoluteParentPath_return_root_when_depth_is_zero()
- {
- // Arrange
- const string path = @"directory/subdirectory";
- const string expectedPath = @"vfs://";
- var vfsPath = new VFSDirectoryPath(path);
-
- // Act
- var parent = vfsPath.GetAbsoluteParentPath(0);
-
- // Assert
- parent.Should().NotBeNull();
- parent.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void MethodGetAbsoluteParentPath_return_parent_when_depth_is_one()
- {
- // Arrange
- const string path = @"directory/subdirectory";
- const string expectedPath = @"vfs://directory";
- var vfsPath = new VFSDirectoryPath(path);
-
- // Act
- var parent = vfsPath.GetAbsoluteParentPath(1);
-
- // Assert
- parent.Should().NotBeNull();
- parent.Value.Should().Be(expectedPath);
- }
-
- [Fact]
- public void MethodGetAbsoluteParentPath_return_grandparent_when_depth_is_two()
- {
- // Arrange
- const string path = @"directory/subdirectory/subsubdirectory";
- const string expectedPath = @"vfs://directory/subdirectory";
- var vfsPath = new VFSDirectoryPath(path);
-
- // Act
- var parent = vfsPath.GetAbsoluteParentPath(2);
-
- // Assert
- parent.Should().NotBeNull();
- parent.Value.Should().Be(expectedPath);
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_returns_value()
- {
- // Arrange
- const string path = @"valid/path";
- const string expectedPath = @"vfs://valid/path";
-
- // Act
- var vfsPath = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath.ToString().Should().Be(expectedPath);
- }
- }
-
- public class Equality
- {
- [Fact]
- public void Equals_returns_true_when_paths_are_equal()
- {
- // Arrange
- const string path = @"valid/path";
-
- // Act
- var vfsPath1 = new VFSDirectoryPath(path);
- var vfsPath2 = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath1.Equals(vfsPath2).Should().BeTrue();
- }
-
- [Fact]
- public void Equals_returns_true_when_paths_are_the_same()
- {
- // Arrange
- const string path = @"valid/path";
-
- // Act
- var vfsPath1 = new VFSDirectoryPath(path);
-
- // Assert
- vfsPath1.Equals(vfsPath1).Should().BeTrue();
- }
-
- [Fact]
- public void Equals_returns_false_when_paths_are_not_equal()
- {
- // Arrange
- const string path1 = @"valid/path";
- const string path2 = @"valid/path2";
-
- // Act
- var vfsPath1 = new VFSDirectoryPath(path1);
- var vfsPath2 = new VFSDirectoryPath(path2);
-
- // Assert
- vfsPath1.Equals(vfsPath2).Should().BeFalse();
- }
-
- [Fact]
- public void Equals_returns_false_when_paths_are_not_equal_and_one_is_file()
- {
- // Arrange
- const string path1 = @"valid/path";
- const string path2 = @"valid/path/file.txt";
-
- // Act
- var vfsPath1 = new VFSDirectoryPath(path1);
- var vfsPath2 = new VFSFilePath(path2);
-
- // Assert
- vfsPath1.Equals(vfsPath2).Should().BeFalse();
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.ValueObjects;
+
+public class VFSPathTest
+{
+ public class Constructor
+ {
+ // Business rules:
+ // - The path must not be null or empty.
+ // - The path contains only valid characters (a-z, A-Z, 0-9, /, ., _).
+ // - The path must not contain any relative path segments (..).
+ // - The path must not contain any consecutive slashes (//).
+ // - The path must not end with a slash (/).
+
+ [Fact]
+ public void Constructor_throw_ArgumentNullException_when_path_is_null()
+ {
+ // Arrange
+ const string path = null!;
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path!);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_is_empty()
+ {
+ // Arrange
+ const string path = "";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_invalid_characters()
+ {
+ // Arrange
+ const string path = @"invalid\path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_relative_path_segments()
+ {
+ // Arrange
+ const string path = @"invalid/../path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_throw_ArgumentException_when_path_contains_consecutive_slashes()
+ {
+ // Arrange
+ const string path = @"invalid//path";
+
+ // Act
+ var action = () =>
+ {
+ var _ = new VFSDirectoryPath(path);
+ };
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Value.Should().NotBeNull();
+ vfsPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_ends_with_slash()
+ {
+ // Arrange
+ const string path = @"valid/path/";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Value.Should().NotBeNull();
+ vfsPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_starts_with_slash()
+ {
+ // Arrange
+ const string path = @"/valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Value.Should().NotBeNull();
+ vfsPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_starts_and_ends_with_slash()
+ {
+ // Arrange
+ const string path = @"/valid/path/";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Value.Should().NotBeNull();
+ vfsPath.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void PropertyParentPath_return_null_when_path_is_root()
+ {
+ // Arrange
+ const string path = @"/";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Parent.Should().BeNull();
+ }
+
+ [Fact]
+ public void Constructor_create_instance_when_path_is_valid_and_has_parent()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ const string expectedPath = @"vfs://valid/path";
+ const string expectedParentPath = @"vfs://valid";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Value.Should().NotBeNull();
+ vfsPath.Value.Should().Be(expectedPath);
+ vfsPath.Parent.Should().NotBeNull();
+ vfsPath.Parent!.Value.Should().Be(expectedParentPath);
+ }
+ }
+
+ public class PropertyName
+ {
+ [Fact]
+ public void PropertyName_return_name_of_directory()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ const string expectedName = @"path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Name.Should().Be(expectedName);
+ }
+
+ [Fact]
+ public void PropertyName_return_name_of_file()
+ {
+ // Arrange
+ const string path = @"valid/path/file.txt";
+ const string expectedName = @"file.txt";
+
+ // Act
+ var vfsPath = new VFSFilePath(path);
+
+ // Assert
+ vfsPath.Name.Should().Be(expectedName);
+ }
+
+ [Fact]
+ public void PropertyName_return_name_of_root_directory()
+ {
+ // Arrange
+ const string path = @"/";
+ const string expectedName = @"vfs://";
+
+ // Act
+ var vfsPath = new VFSFilePath(path);
+
+ // Assert
+ vfsPath.Name.Should().Be(expectedName);
+ }
+ }
+
+ public class PropertyDepth
+ {
+ [Fact]
+ public void PropertyDepth_return_0_when_path_is_root()
+ {
+ // Arrange
+ const string path = @"/";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Depth.Should().Be(0);
+ }
+
+ [Fact]
+ public void PropertyDepth_return_1_with_one_directory()
+ {
+ // Arrange
+ const string path = @"directory";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Depth.Should().Be(1);
+ }
+
+ [Fact]
+ public void PropertyDepth_return_2_with_two_directories()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Depth.Should().Be(2);
+ }
+
+ [Fact]
+ public void PropertyDepth_return_3_with_three_directories()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory/subsubdirectory";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.Depth.Should().Be(3);
+ }
+ }
+
+ public class PropertyHasParent
+ {
+ [Fact]
+ public void PropertyHasParent_return_false_when_path_is_root()
+ {
+ // Arrange
+ const string path = @"/";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.HasParent.Should().BeFalse();
+ }
+
+ [Fact]
+ public void PropertyHasParent_return_true_when_path_has_parent()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.HasParent.Should().BeTrue();
+ }
+ }
+
+ public class MethodGetAbsoluteParentPath
+ {
+ [Fact]
+ public void MethodGetAbsoluteParentPath_return_root_when_path_is_root()
+ {
+ // Arrange
+ const string path = @"/";
+ const string expectedPath = @"vfs://";
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Act
+ var parent = vfsPath.GetAbsoluteParentPath(0);
+
+ // Assert
+ parent.Should().NotBeNull();
+ parent.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void MethodGetAbsoluteParentPath_throw_exception_when_depth_is_negative()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory";
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Act
+ Action action = () => vfsPath.GetAbsoluteParentPath(-1);
+
+ // Assert
+ action.Should().Throw();
+ }
+
+ [Fact]
+ public void MethodGetAbsoluteParentPath_return_root_when_depth_is_zero()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory";
+ const string expectedPath = @"vfs://";
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Act
+ var parent = vfsPath.GetAbsoluteParentPath(0);
+
+ // Assert
+ parent.Should().NotBeNull();
+ parent.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void MethodGetAbsoluteParentPath_return_parent_when_depth_is_one()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory";
+ const string expectedPath = @"vfs://directory";
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Act
+ var parent = vfsPath.GetAbsoluteParentPath(1);
+
+ // Assert
+ parent.Should().NotBeNull();
+ parent.Value.Should().Be(expectedPath);
+ }
+
+ [Fact]
+ public void MethodGetAbsoluteParentPath_return_grandparent_when_depth_is_two()
+ {
+ // Arrange
+ const string path = @"directory/subdirectory/subsubdirectory";
+ const string expectedPath = @"vfs://directory/subdirectory";
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Act
+ var parent = vfsPath.GetAbsoluteParentPath(2);
+
+ // Assert
+ parent.Should().NotBeNull();
+ parent.Value.Should().Be(expectedPath);
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_returns_value()
+ {
+ // Arrange
+ const string path = @"valid/path";
+ const string expectedPath = @"vfs://valid/path";
+
+ // Act
+ var vfsPath = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath.ToString().Should().Be(expectedPath);
+ }
+ }
+
+ public class Equality
+ {
+ [Fact]
+ public void Equals_returns_true_when_paths_are_equal()
+ {
+ // Arrange
+ const string path = @"valid/path";
+
+ // Act
+ var vfsPath1 = new VFSDirectoryPath(path);
+ var vfsPath2 = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath1.Equals(vfsPath2).Should().BeTrue();
+ }
+
+ [Fact]
+ public void Equals_returns_true_when_paths_are_the_same()
+ {
+ // Arrange
+ const string path = @"valid/path";
+
+ // Act
+ var vfsPath1 = new VFSDirectoryPath(path);
+
+ // Assert
+ vfsPath1.Equals(vfsPath1).Should().BeTrue();
+ }
+
+ [Fact]
+ public void Equals_returns_false_when_paths_are_not_equal()
+ {
+ // Arrange
+ const string path1 = @"valid/path";
+ const string path2 = @"valid/path2";
+
+ // Act
+ var vfsPath1 = new VFSDirectoryPath(path1);
+ var vfsPath2 = new VFSDirectoryPath(path2);
+
+ // Assert
+ vfsPath1.Equals(vfsPath2).Should().BeFalse();
+ }
+
+ [Fact]
+ public void Equals_returns_false_when_paths_are_not_equal_and_one_is_file()
+ {
+ // Arrange
+ const string path1 = @"valid/path";
+ const string path2 = @"valid/path/file.txt";
+
+ // Act
+ var vfsPath1 = new VFSDirectoryPath(path1);
+ var vfsPath2 = new VFSFilePath(path2);
+
+ // Assert
+ vfsPath1.Equals(vfsPath2).Should().BeFalse();
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSRootPathTests.cs b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSRootPathTests.cs
index da4520f..2e42aa4 100644
--- a/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSRootPathTests.cs
+++ b/tests/Atypical.VirtualFileSystem.UnitTests/ValueObjects/VFSRootPathTests.cs
@@ -1,79 +1,79 @@
-// Copyright (c) 2022, Atypical Consulting SRL
-// All rights reserved.
-//
-// This source code is licensed under the BSD-style license found in the
-// LICENSE file in the root directory of this source tree.
-
-namespace VirtualFileSystem.UnitTests.ValueObjects;
-
-public class VFSRootPathTests
-{
- public class Constructor
- {
- [Fact]
- public void Constructor_create_instance()
- {
- // Arrange
- const string expectedPath = @"vfs://";
-
- // Act
- var directoryPath = new VFSRootPath();
-
- // Assert
- directoryPath.Should().NotBeNull();
- directoryPath.Value.Should().Be(expectedPath);
- directoryPath.IsRoot.Should().BeTrue();
- directoryPath.Parent.Should().BeNull();
- }
- }
-
- public class MethodToString
- {
- [Fact]
- public void ToString_returns_value()
- {
- // Arrange
- const string expectedPath = @"vfs://";
-
- // Act
- var directoryPath = new VFSRootPath();
-
- // Assert
- directoryPath.ToString().Should().Be(expectedPath);
- }
- }
-
- public class ImplicitOperator
- {
- [Fact]
- public void ImplicitOperator_ToString_returns_value()
- {
- // Arrange
- var rootPath = new VFSRootPath();
- const string expectedPath = "vfs://";
-
- // Act
- string result = rootPath;
-
- // Assert
- result.Should().Be(expectedPath);
- }
- }
-
- public class Equality
- {
- [Fact]
- public void Equals_returns_true_when_paths_are_equal()
- {
- // Arrange
- var rootPath1 = new VFSRootPath();
- var rootPath2 = new VFSRootPath();
-
- // Act
- var result = rootPath1.Equals(rootPath2);
-
- // Assert
- result.Should().BeTrue();
- }
- }
+// Copyright (c) 2022, Atypical Consulting SRL
+// All rights reserved.
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+namespace VirtualFileSystem.UnitTests.ValueObjects;
+
+public class VFSRootPathTests
+{
+ public class Constructor
+ {
+ [Fact]
+ public void Constructor_create_instance()
+ {
+ // Arrange
+ const string expectedPath = @"vfs://";
+
+ // Act
+ var directoryPath = new VFSRootPath();
+
+ // Assert
+ directoryPath.Should().NotBeNull();
+ directoryPath.Value.Should().Be(expectedPath);
+ directoryPath.IsRoot.Should().BeTrue();
+ directoryPath.Parent.Should().BeNull();
+ }
+ }
+
+ public class MethodToString
+ {
+ [Fact]
+ public void ToString_returns_value()
+ {
+ // Arrange
+ const string expectedPath = @"vfs://";
+
+ // Act
+ var directoryPath = new VFSRootPath();
+
+ // Assert
+ directoryPath.ToString().Should().Be(expectedPath);
+ }
+ }
+
+ public class ImplicitOperator
+ {
+ [Fact]
+ public void ImplicitOperator_ToString_returns_value()
+ {
+ // Arrange
+ var rootPath = new VFSRootPath();
+ const string expectedPath = "vfs://";
+
+ // Act
+ string result = rootPath;
+
+ // Assert
+ result.Should().Be(expectedPath);
+ }
+ }
+
+ public class Equality
+ {
+ [Fact]
+ public void Equals_returns_true_when_paths_are_equal()
+ {
+ // Arrange
+ var rootPath1 = new VFSRootPath();
+ var rootPath2 = new VFSRootPath();
+
+ // Act
+ var result = rootPath1.Equals(rootPath2);
+
+ // Assert
+ result.Should().BeTrue();
+ }
+ }
}
\ No newline at end of file