Skip to content

Commit bfaa9f3

Browse files
authored
feat: implement TryJoin for simulated Path (#568)
Implement the `TryJoin` methods for `Path`.
1 parent e1c23f8 commit bfaa9f3

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

Source/Testably.Abstractions.Testing/Helpers/Execute.SimulatedPath.cs

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Diagnostics.CodeAnalysis;
34
using System.Text;
4-
55
#if FEATURE_FILESYSTEM_NET7
66
using Testably.Abstractions.Testing.Storage;
77
#endif
@@ -407,7 +407,18 @@ public bool TryJoin(ReadOnlySpan<char> path1,
407407
ReadOnlySpan<char> path2,
408408
Span<char> destination,
409409
out int charsWritten)
410-
=> System.IO.Path.TryJoin(path1, path2, destination, out charsWritten);
410+
{
411+
string result = Join(path1, path2);
412+
if (destination.Length < result.Length)
413+
{
414+
charsWritten = 0;
415+
return false;
416+
}
417+
418+
result.AsSpan().CopyTo(destination);
419+
charsWritten = result.Length;
420+
return true;
421+
}
411422
#endif
412423

413424
#if FEATURE_PATH_JOIN
@@ -417,7 +428,18 @@ public bool TryJoin(ReadOnlySpan<char> path1,
417428
ReadOnlySpan<char> path3,
418429
Span<char> destination,
419430
out int charsWritten)
420-
=> System.IO.Path.TryJoin(path1, path2, path3, destination, out charsWritten);
431+
{
432+
string result = Join(path1, path2, path3);
433+
if (destination.Length < result.Length)
434+
{
435+
charsWritten = 0;
436+
return false;
437+
}
438+
439+
result.AsSpan().CopyTo(destination);
440+
charsWritten = result.Length;
441+
return true;
442+
}
421443
#endif
422444

423445
#endregion
@@ -440,7 +462,7 @@ private string JoinInternal(string?[] paths)
440462
return string.Empty;
441463
}
442464

443-
StringBuilder sb = new StringBuilder();
465+
StringBuilder sb = new();
444466
foreach (string? path in paths)
445467
{
446468
if (string.IsNullOrEmpty(path))

Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ private bool IncludeSimulatedTests(ClassModel @class)
241241
"GetTempPathTests",
242242
"IsPathRootedTests",
243243
"JoinTests",
244-
"Tests"
244+
"Tests",
245+
"TryJoinTests"
245246
];
246247
return @class.Namespace
247248
.StartsWith("Testably.Abstractions.Tests.FileSystem.Path", StringComparison.Ordinal)

Tests/Testably.Abstractions.Tests/FileSystem/Path/TryJoinTests.cs

+57
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,33 @@ public void TryJoin_2Paths_BufferTooLittle_ShouldReturnFalse(
2727
charsWritten.Should().Be(0);
2828
}
2929

30+
[SkippableTheory]
31+
[InlineAutoData("/foo/", "/bar/", "/foo//bar/")]
32+
[InlineAutoData("foo/", "/bar", "foo//bar")]
33+
[InlineAutoData("foo/", "bar", "foo/bar")]
34+
[InlineAutoData("foo", "/bar", "foo/bar")]
35+
[InlineAutoData("foo", "bar", "foo/bar")]
36+
[InlineAutoData("/foo", "bar/", "/foo/bar/")]
37+
public void TryJoin_2Paths_ShouldReturnExpectedResult(
38+
string path1, string path2, string expectedResult)
39+
{
40+
path1 = path1.Replace('/', FileSystem.Path.DirectorySeparatorChar);
41+
path2 = path2.Replace('/', FileSystem.Path.DirectorySeparatorChar);
42+
expectedResult = expectedResult.Replace('/', FileSystem.Path.DirectorySeparatorChar);
43+
char[] buffer = new char[expectedResult.Length];
44+
Span<char> destination = new(buffer);
45+
46+
bool result = FileSystem.Path.TryJoin(
47+
path1.AsSpan(),
48+
path2.AsSpan(),
49+
destination,
50+
out int charsWritten);
51+
52+
result.Should().BeTrue();
53+
charsWritten.Should().Be(expectedResult.Length);
54+
destination.Slice(0, charsWritten).ToString().Should().Be(expectedResult);
55+
}
56+
3057
[SkippableTheory]
3158
[AutoData]
3259
public void TryJoin_2Paths_ShouldReturnPathsCombinedByDirectorySeparatorChar(
@@ -72,6 +99,36 @@ public void TryJoin_3Paths_BufferTooLittle_ShouldReturnFalse(
7299
charsWritten.Should().Be(0);
73100
}
74101

102+
[SkippableTheory]
103+
[InlineAutoData("/foo/", "/bar/", "/baz/", "/foo//bar//baz/")]
104+
[InlineAutoData("foo/", "/bar/", "/baz", "foo//bar//baz")]
105+
[InlineAutoData("foo/", "bar", "/baz", "foo/bar/baz")]
106+
[InlineAutoData("foo", "/bar", "/baz", "foo/bar/baz")]
107+
[InlineAutoData("foo", "/bar/", "baz", "foo/bar/baz")]
108+
[InlineAutoData("foo", "bar", "baz", "foo/bar/baz")]
109+
[InlineAutoData("/foo", "bar", "baz/", "/foo/bar/baz/")]
110+
public void TryJoin_3Paths_ShouldReturnExpectedResult(
111+
string path1, string path2, string path3, string expectedResult)
112+
{
113+
path1 = path1.Replace('/', FileSystem.Path.DirectorySeparatorChar);
114+
path2 = path2.Replace('/', FileSystem.Path.DirectorySeparatorChar);
115+
path3 = path3.Replace('/', FileSystem.Path.DirectorySeparatorChar);
116+
expectedResult = expectedResult.Replace('/', FileSystem.Path.DirectorySeparatorChar);
117+
char[] buffer = new char[expectedResult.Length];
118+
Span<char> destination = new(buffer);
119+
120+
bool result = FileSystem.Path.TryJoin(
121+
path1.AsSpan(),
122+
path2.AsSpan(),
123+
path3.AsSpan(),
124+
destination,
125+
out int charsWritten);
126+
127+
result.Should().BeTrue();
128+
charsWritten.Should().Be(expectedResult.Length);
129+
destination.Slice(0, charsWritten).ToString().Should().Be(expectedResult);
130+
}
131+
75132
[SkippableTheory]
76133
[AutoData]
77134
public void TryJoin_3Paths_ShouldReturnPathsCombinedByDirectorySeparatorChar(

0 commit comments

Comments
 (0)