Agent was stopped for token budget partway through the LA1 review fix round. Landed here: F1 best-effort SessionStatusWriter, F2 App reader tolerance (paths/mode), F5 argument-parsing hardening, plus new tests. NOT DONE: F4 shared-fixture production shape (was the next step), F3 reconnect disconnected edge + recorded limitation, F6 exited idempotency/reasons, F7 structural redaction test, F8 platform-guard test + comment fix, optional RuntimeOptions PrintMembers redaction. Build/test state UNVERIFIED at this commit. Next session: finish the remaining findings, run the suites, then narrow re-review. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
97 lines
2.8 KiB
C#
97 lines
2.8 KiB
C#
using AcDream.App.Configuration;
|
|
|
|
namespace AcDream.App.Tests.Configuration;
|
|
|
|
/// <summary>
|
|
/// Campaign LA slice LA1 review fix (F5): pins
|
|
/// <see cref="SessionConfigArgumentParsing"/>'s trailing-flag edge case —
|
|
/// <c>--session-config</c> present as the LAST argument with nothing after
|
|
/// it must be distinguishable from the flag being entirely absent, so
|
|
/// <c>Program.cs</c> can turn it into a hard error instead of a silent
|
|
/// fall-through to the env-var/positional dat-dir path.
|
|
/// </summary>
|
|
public sealed class SessionConfigArgumentParsingTests
|
|
{
|
|
private const string Flag = "--session-config";
|
|
|
|
[Fact]
|
|
public void FlagWithAFollowingValueReturnsThatValueAndIsPresent()
|
|
{
|
|
string? value = SessionConfigArgumentParsing.ExtractFlagValue(
|
|
["D:\\dats", Flag, "session.json"],
|
|
Flag,
|
|
out bool present);
|
|
|
|
Assert.True(present);
|
|
Assert.Equal("session.json", value);
|
|
}
|
|
|
|
[Fact]
|
|
public void FlagAbsentReturnsNullAndIsNotPresent()
|
|
{
|
|
string? value = SessionConfigArgumentParsing.ExtractFlagValue(
|
|
["D:\\dats"],
|
|
Flag,
|
|
out bool present);
|
|
|
|
Assert.False(present);
|
|
Assert.Null(value);
|
|
}
|
|
|
|
[Fact]
|
|
public void TrailingFlagWithNoValueIsPresentWithANullValue()
|
|
{
|
|
string? value = SessionConfigArgumentParsing.ExtractFlagValue(
|
|
["D:\\dats", Flag],
|
|
Flag,
|
|
out bool present);
|
|
|
|
// This is the case Program.cs must turn into exit code 2 — present
|
|
// but no value is categorically different from "not present at
|
|
// all", even though both currently yield a null return value.
|
|
Assert.True(present);
|
|
Assert.Null(value);
|
|
}
|
|
|
|
[Fact]
|
|
public void FlagAloneAsTheOnlyArgumentIsPresentWithANullValue()
|
|
{
|
|
string? value = SessionConfigArgumentParsing.ExtractFlagValue(
|
|
[Flag],
|
|
Flag,
|
|
out bool present);
|
|
|
|
Assert.True(present);
|
|
Assert.Null(value);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutFlagAndValueDropsTheFlagAndItsValue()
|
|
{
|
|
string[] positional = SessionConfigArgumentParsing.WithoutFlagAndValue(
|
|
["D:\\dats", Flag, "session.json", "extra"],
|
|
Flag);
|
|
|
|
Assert.Equal(["D:\\dats", "extra"], positional);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutFlagAndValueTrailingFlagDropsOnlyTheFlagItself()
|
|
{
|
|
string[] positional = SessionConfigArgumentParsing.WithoutFlagAndValue(
|
|
["D:\\dats", Flag],
|
|
Flag);
|
|
|
|
Assert.Equal(["D:\\dats"], positional);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutFlagAndValueLeavesArgumentsUnchangedWhenFlagIsAbsent()
|
|
{
|
|
string[] positional = SessionConfigArgumentParsing.WithoutFlagAndValue(
|
|
["D:\\dats"],
|
|
Flag);
|
|
|
|
Assert.Equal(["D:\\dats"], positional);
|
|
}
|
|
}
|