using DodoSSH.Client.ObjectStore;
namespace DodoSSH.Client.ObjectStore.Tests;
///
/// Translating between the paths a file browser uses and the keys a bucket has.
///
///
/// Small and worth having, because every one of these cases is a way a bucket listing goes subtly wrong
/// rather than loudly: a missing trailing slash lists a sibling directory's contents, and a leading one asks
/// the service for a key beginning with /, which is legal and is never what anybody stored.
///
public sealed class ObjectKeysTests
{
[Theory]
[InlineData("/", "")]
[InlineData("/reports", "reports")]
[InlineData("/reports/2026/q3.csv", "reports/2026/q3.csv")]
public void APathBecomesAKeyWithNoLeadingSlash(string path, string expected)
{
ObjectKeys.ToKey(path).ShouldBe(expected);
}
[Theory]
[InlineData("", "/")]
[InlineData("reports/2026/q3.csv", "/reports/2026/q3.csv")]
public void AKeyBecomesAnAbsolutePath(string key, string expected)
{
ObjectKeys.ToPath(key).ShouldBe(expected);
}
///
/// The one that matters most. Without the trailing slash, listing /reports also returns everything
/// under /reports-archive — a prefix match knows nothing about path segments, and the result is a
/// directory listing with another directory's files in it.
///
[Theory]
[InlineData("/reports", "reports/")]
[InlineData("/reports/", "reports/")]
[InlineData("/reports/2026", "reports/2026/")]
public void APrefixAlwaysEndsInASlash(string path, string expected)
{
ObjectKeys.ToPrefix(path).ShouldBe(expected);
}
///
/// Empty rather than "/", because a prefix of / matches nothing: no key stored by anything
/// begins with a slash. This is the case that makes the root of a bucket list at all.
///
[Fact]
public void TheRootHasAnEmptyPrefix()
{
ObjectKeys.ToPrefix("/").ShouldBeEmpty();
}
///
/// A common prefix arrives with its trailing slash on, so trimming has to happen before the last segment
/// is taken — otherwise every directory in the listing is named "".
///
[Theory]
[InlineData("reports/2026/", "2026")]
[InlineData("reports/2026/q3.csv", "q3.csv")]
[InlineData("q3.csv", "q3.csv")]
[InlineData("reports/", "reports")]
public void ANameIsTheLastSegment(string key, string expected)
{
ObjectKeys.NameOf(key).ShouldBe(expected);
}
[Theory]
[InlineData("/")]
[InlineData("/reports")]
[InlineData("/reports/2026/q3.csv")]
public void APathSurvivesARoundTrip(string path)
{
ObjectKeys.ToPath(ObjectKeys.ToKey(path)).ShouldBe(path);
}
}