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>
67 lines
2.3 KiB
C#
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)));
|
|
}
|
|
}
|