Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 101 additions & 5 deletions TruePath.Tests/AbsolutePathTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ public void ConstructionTest()
[Fact]
public void PathRootReturnsRoot()
{
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");
var path = root / "foo" / "bar";
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");
var path = root / "foo" / "bar";

Assert.Equal(root, path.PathRoot());
Assert.Equal(root, path.PathRoot());
}

[Fact]
public void PathRootOfRootReturnsItself()
{
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");

Assert.Equal(root, root.PathRoot());
Assert.Equal(root, root.PathRoot());
}

[Fact]
Expand Down Expand Up @@ -261,6 +261,102 @@ public void PathIsNormalizedOnCreation()
Assert.Equal(@"C:\Users\John Doe\Documents", absolutePath.Value);
}

[Theory]
[InlineData(@"/.")]
[InlineData(@"/./.")]
[InlineData(@"/././.")]
public void ConstructorCreatesValidPathWithDotInUnix(string path)
{
if (OperatingSystem.IsWindows()) return;
const string expectedPath = @"/";

var absolutePath = new AbsolutePath(path);

Assert.Equal(expectedPath, absolutePath.Value);
}

[Theory]
[InlineData(@"/...")]
[InlineData(@"/..SomeFolder")]
[InlineData(@"/..00")]
[InlineData(@"/..#")]
public void ConstructorCreatesValidPathCorrectlyInUnix(string path)
{
if (OperatingSystem.IsWindows()) return;

var absolutePath = new AbsolutePath(path);

Assert.Equal(path, absolutePath.Value);
}

[Theory]
[InlineData(@"/../")]
[InlineData(@"/../..")]
[InlineData(@"/../../SomeFolder")]
[InlineData(@"/../.SomeFolder")]
[InlineData(@"/../SomeFolder")]
[InlineData(@"/../1123")]
[InlineData(@"/../()")]
[InlineData(@"/./..")]
[InlineData(@"/./../.")]
public void ConstructorThrowsOnInvalidPathInUnix(string path)
{
if (OperatingSystem.IsWindows()) return;
string expectedMessage = $"Path \"{path}\" is not valid.";

var ex = Assert.Throws<ArgumentException>(() => new AbsolutePath(path));

Assert.Equal(expectedMessage, ex.Message);
}

[Theory]
[InlineData(@"C:\.")]
[InlineData(@"C:\.\.")]
[InlineData(@"C:\.\.\.")]
public void ConstructorCreatesValidPathWithDotInWindows(string path)
{
if (OperatingSystem.IsWindows() is false) return;
const string expectedPath = @"C:\";

var absolutePath = new AbsolutePath(path);

Assert.Equal(expectedPath, absolutePath.Value);
}

[Theory]
[InlineData(@"C:\...")]
[InlineData(@"C:\..SomeFolder")]
[InlineData(@"C:\..00")]
[InlineData(@"C:\..#")]
public void ConstructorCreatesValidPathCorrectlyInWindows(string path)
{
if (OperatingSystem.IsWindows() is false) return;

var absolutePath = new AbsolutePath(path);

Assert.Equal(path, absolutePath.Value);
}

[Theory]
[InlineData(@"C:\..\")]
[InlineData(@"C:\..\..")]
[InlineData(@"C:\..\..SomeFolder")]
[InlineData(@"C:\..\.SomeFolder")]
[InlineData(@"C:\..\SomeFolder")]
[InlineData(@"C:\..\1123")]
[InlineData(@"C:\..\()")]
[InlineData(@"C:\.\..")]
[InlineData(@"C:\.\..\.")]
public void ConstructorThrowsOnInvalidPathInWindows(string path)
{
if (OperatingSystem.IsWindows() is false) return;
string expectedMessage = $"Path \"{path}\" is not valid.";

var ex = Assert.Throws<ArgumentException>(() => new AbsolutePath(path));

Assert.Equal(expectedMessage, ex.Message);
}

[Fact]
public void ConstructorThrowsOnNonRootedPath()
{
Expand Down
12 changes: 12 additions & 0 deletions TruePath/AbsolutePath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,24 @@ namespace TruePath;
/// <param name="value">Path string to normalize.</param>
/// <param name="checkAbsoluteness">Flag indicating whether absoluteness of path should be checked</param>
/// <exception cref="ArgumentException">Thrown if the passed string does not represent an absolute path.</exception>>
/// <exception cref="ArgumentException">
/// Thrown if the passed string matches the dot-dot directory directly after root (e.g. C:/../ or /../)
/// </exception>>

private AbsolutePath(string value, bool checkAbsoluteness)
{
Underlying = new LocalPath(value);

if (checkAbsoluteness && Underlying.IsAbsolute is false)
throw new ArgumentException($"Path \"{value}\" is not absolute.");

var pathRoot = Path.GetPathRoot(Underlying.Value)!;
var pathWithoutRoot = Underlying.Value[pathRoot.Length..];
if (pathWithoutRoot.StartsWith("../") || pathWithoutRoot.StartsWith("..\\") ||
pathWithoutRoot.Equals(".."))
{
throw new ArgumentException($"Path \"{value}\" is not valid.");
}
}

/// <summary>
Expand Down
Loading