Skip to content

Commit 0d425ae

Browse files
committed
(#18) LocalPath, AbsolutePath: migrate to the new logic for Parent calculation
1 parent af5fb1a commit 0d425ae

3 files changed

Lines changed: 42 additions & 37 deletions

File tree

TruePath.Tests/AbsolutePathTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,18 @@ public void ReadKind_IsSymlink()
9494
Directory.Delete(currentDirectory, true);
9595
}
9696

97+
[Theory]
98+
[InlineData("foo", ".")]
99+
[InlineData("foo/bar", "foo")]
100+
[InlineData("/", null)]
101+
public void ParentIsCalculatedCorrectly(string relativePath, string? expectedRelativePath)
102+
{
103+
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");
104+
var parent = root / relativePath;
105+
AbsolutePath? expectedPath = expectedRelativePath == null ? null : new(root / expectedRelativePath);
106+
Assert.Equal(expectedPath, parent.Parent);
107+
}
108+
97109
[Theory]
98110
[InlineData("/home/user", "/home/user/documents")]
99111
[InlineData("/home/usEr", "/home/User/documents")]

TruePath.Tests/LocalPathTests.cs

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,41 @@ namespace TruePath.Tests;
88

99
public class LocalPathTests(ITestOutputHelper output)
1010
{
11-
[Fact]
12-
public void AnyExclusivelyRelativePath()
11+
[Theory]
12+
[InlineData("foo", ".")]
13+
[InlineData("foo/bar", "foo")]
14+
[InlineData("/", null)]
15+
public void AbsolutePathParent(string relativePath, string? expectedRelativePath)
1316
{
14-
// Arrange
15-
var dots = new string(Enumerable.Repeat('.', Random.Shared.Next(1, 21)).ToArray());
16-
var backslashes = new string(Enumerable.Repeat(Path.DirectorySeparatorChar, Random.Shared.Next(0, 20)).ToArray());
17-
var result = string.Concat(dots.AsSpan(), backslashes.AsSpan()).ToArray();
18-
Random.Shared.Shuffle(result.ToArray());
19-
var path = new string(result);
20-
21-
var localPath = new LocalPath(path);
22-
23-
// Act
24-
var parent = localPath.Parent;
25-
26-
// Assert
27-
Assert.Null(parent);
17+
var root = new AbsolutePath(OperatingSystem.IsWindows() ? @"A:\" : "/");
18+
var parent = root / relativePath;
19+
AbsolutePath? expectedPath = expectedRelativePath == null ? null : new(root / expectedRelativePath);
20+
Assert.Equal(expectedPath, parent.Parent);
2821
}
2922

3023
[Theory]
31-
[InlineData(".")]
32-
[InlineData("..")]
33-
[InlineData("../..")]
34-
[InlineData("../../")]
35-
[InlineData("../...")]
36-
[InlineData(".../..")]
37-
[InlineData("./.")]
38-
[InlineData("../../.")]
39-
public void ExclusivelyRelativePath(string path)
24+
[InlineData(".", "..")]
25+
[InlineData("..", "../..")]
26+
[InlineData("../..", "../../..")]
27+
[InlineData("../../", "../../..")]
28+
[InlineData("../...", "..")]
29+
[InlineData(".../..", "..")]
30+
[InlineData("./.", "..")]
31+
[InlineData("../../.", "../../..")]
32+
[InlineData("b", ".")]
33+
[InlineData("../b", "..")]
34+
[InlineData("b/..", "b/../..")]
35+
public void RelativePathParent(string path, string? expected)
4036
{
4137
// Arrange
4238
var localPath = new LocalPath(path);
39+
LocalPath? expectedPath = expected == null ? null : new(expected);
4340

4441
// Act
4542
var parent = localPath.Parent;
4643

4744
// Assert
48-
Assert.Null(parent);
45+
Assert.Equal(expectedPath, parent);
4946
}
5047

5148
[Theory]
@@ -56,8 +53,6 @@ public void ExclusivelyRelativePath(string path)
5653
public void IsPrefixOfShouldBeEquivalentToStartsWith(string pathA, string pathB)
5754
{
5855
// Arrange
59-
var y = PathStrings.Normalize("../..");
60-
6156
var a = new LocalPath(pathA);
6257
var b = new LocalPath(pathB);
6358

TruePath/LocalPath.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace TruePath;
1616
/// </summary>
1717
public readonly struct LocalPath(string value) : IEquatable<LocalPath>, IPath, IPath<LocalPath>
1818
{
19+
private static char Separator => Path.DirectorySeparatorChar;
20+
1921
/// <inheritdoc cref="IPath.Value"/>
2022
public string Value { get; } = PathStrings.Normalize(value);
2123

@@ -29,18 +31,14 @@ public readonly struct LocalPath(string value) : IEquatable<LocalPath>, IPath, I
2931
public bool IsAbsolute => Path.IsPathRooted(Value);
3032

3133
/// <inheritdoc cref="IPath.Parent"/>
32-
public LocalPath? Parent {
34+
public LocalPath? Parent
35+
{
3336
get
3437
{
35-
var value = PathStrings.ResolveRelativePaths(Value);
36-
if (string.IsNullOrWhiteSpace(value))
37-
{
38-
return null;
39-
}
40-
38+
if (Value == "" || Value == ".." || Value.EndsWith($"{Separator}..")) return this / "..";
4139
return Path.GetDirectoryName(Value) is { } parent ? new(parent) : null;
4240
}
43-
}
41+
}
4442

4543
/// <inheritdoc cref="IPath.Parent"/>
4644
IPath? IPath.Parent => Parent;
@@ -89,7 +87,7 @@ public override int GetHashCode()
8987
public bool IsPrefixOf(LocalPath other)
9088
{
9189
if (!(Value.Length <= other.Value.Length && other.Value.StartsWith(Value))) return false;
92-
return other.Value.Length == Value.Length || other.Value[Value.Length] == Path.DirectorySeparatorChar;
90+
return other.Value.Length == Value.Length || other.Value[Value.Length] == Separator;
9391
}
9492

9593
/// <summary>

0 commit comments

Comments
 (0)