Files
riojoy/tests/RioJoy.Core.Tests/Hosting/CompanionExitTests.cs
T
CydandClaude Fable 5 97caf124a6 pod: bundled per-game deployment (portable config, --exit-with, build-pod)
Phase 10: RIO hardware exists only on pods + dev boxes, so production is one
RIOJoy copy inside each podized game folder, no resident tray. ConfigLocator
makes a config.json beside the exe win over %APPDATA%; --exit-with <exe|pid>
(CompanionTarget/CompanionExit, 60s startup grace) tears down and quits when
the game exits; a starting --exit-with instance waits up to 15s for the
predecessor mutex instead of silently exiting. deploy/build-pod.ps1 emits
the ~4.5MB drop-in (app + portable config wrapping the profile + start
script, no drivers) - verified against the shipped Descent profile. 455
tests; PLAN.md Phase 10 + INPUT-INTEGRATION.md pod section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 22:01:52 -05:00

67 lines
2.3 KiB
C#

using RioJoy.Core.Hosting;
using Xunit;
namespace RioJoy.Core.Tests.Hosting;
public class CompanionTargetTests
{
[Fact]
public void NumericValue_IsAPid()
{
CompanionTarget target = CompanionTarget.Parse("4312");
Assert.Equal(4312, target.Pid);
Assert.Null(target.Name);
}
[Theory]
[InlineData("d1x-rebirth")]
[InlineData("D1X-Rebirth.exe")]
[InlineData(@"C:\games\descent\d1x-rebirth.exe")]
public void NameForms_NormalizeLikeTriggers(string value)
{
CompanionTarget target = CompanionTarget.Parse(value);
Assert.Null(target.Pid);
Assert.Equal("d1x-rebirth", target.Name);
}
[Fact]
public void BlankValue_Throws()
{
Assert.Throws<ArgumentException>(() => CompanionTarget.Parse(" "));
}
}
public class CompanionExitTests
{
private static readonly TimeSpan Grace = TimeSpan.FromSeconds(60);
[Fact]
public void CompanionSeenThenGone_Exits()
{
var exit = new CompanionExit(Grace);
Assert.False(exit.ShouldExit(companionRunning: true, TimeSpan.FromSeconds(1)));
Assert.False(exit.ShouldExit(companionRunning: true, TimeSpan.FromSeconds(2)));
Assert.True(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(3)));
}
[Fact]
public void CompanionNeverSeen_WaitsOutTheStartupGrace()
{
// Launch order is not guaranteed: the game may still be loading.
var exit = new CompanionExit(Grace);
Assert.False(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(5)));
Assert.False(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(59)));
Assert.True(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(60)));
}
[Fact]
public void LateStart_WithinGrace_StillTracksTheCompanion()
{
var exit = new CompanionExit(Grace);
Assert.False(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(30)));
Assert.False(exit.ShouldExit(companionRunning: true, TimeSpan.FromSeconds(45))); // game arrived late
Assert.False(exit.ShouldExit(companionRunning: true, TimeSpan.FromSeconds(90))); // grace no longer matters
Assert.True(exit.ShouldExit(companionRunning: false, TimeSpan.FromSeconds(91)));
}
}