tests/test_flow_capture.cs
using HumanoidMocapX.Core.Motion;
using HumanoidMocapX;
using HumanoidMocapX.EditorTools;
static class FlowCaptureTests
{
internal static async Task Run()
{
var hosting = new HostingSettings(); var machine = new SshSettings();
var hosted = new RecordingCapture("hosted"); var remote = new RecordingCapture("remote"); var local = new RecordingCapture("local");
var capture = new FlowCapture(new CaptureOptions(), hosting, hosted, machine, remote, local) { Blocked = "Finish setup first." };
// A held-back capture reports its reason and never reaches any backend.
MotionTests.Equal("Finish setup first.", capture.UnavailableReason);
MotionTests.Throws<InvalidOperationException>(() => capture.CaptureAsync("clip.mp4", 0, null, null, default));
MotionTests.Equal(0, hosted.Calls + remote.Calls + local.Calls);
capture.Blocked = null;
MotionTests.Equal("local", await capture.CaptureAsync("clip.mp4", 0, null, null, default));
machine.Enabled = true;
MotionTests.Equal("remote", await capture.CaptureAsync("clip.mp4", 0, null, null, default));
hosting.Enabled = true;
MotionTests.Equal("hosted", await capture.CaptureAsync("clip.mp4", 0, null, null, default));
MotionTests.Equal(1, hosted.Calls); MotionTests.Equal(1, remote.Calls); MotionTests.Equal(1, local.Calls);
Console.WriteLine("PASS: capture routing holds back blocked captures and picks the hosted, processing machine or local backend");
}
sealed class RecordingCapture(string result) : IBodyCapture
{
internal int Calls;
public string UnavailableReason => null;
public Task<string> CaptureAsync(string video, double start, double? end, Action<string> progress, CancellationToken cancellationToken)
{ Calls++; return Task.FromResult(result); }
}
}