Files
ParkingRobot/ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/RuntimeChecks.cs
T

102 lines
3.8 KiB
C#

using System;
using System.Linq;
using TrajectoryPlanningVisualization;
namespace TrajectoryPlanningVisualizationVerificationHost;
internal static class RuntimeChecks
{
public static void Run()
{
KeepsOnlyTheLatestFrame();
KeepsBoundedDeduplicatedCycleHistory();
SerializesStableCamelCaseJson();
RejectsInvalidOptions();
}
private static void KeepsOnlyTheLatestFrame()
{
var store = new LatestVisualizationFrameStore();
store.Publish(Snap(1));
store.Publish(Snap(2));
Verification.True(store.TryReadAfter(0, out VisualizationFrame frame), "latest frame exists");
Verification.Equal(2L, frame.Snapshot.Sequence, "latest frame replaces old frame");
Verification.True(!store.TryReadAfter(frame.Version, out _), "same frame is not replayed");
}
private static void KeepsBoundedDeduplicatedCycleHistory()
{
var history = new BoundedCycleHistory(2);
history.Add(Cycle(1));
history.Add(Cycle(2));
history.Add(Cycle(3));
history.Add(Cycle(3));
Verification.Equal("2|3", string.Join("|", history.Snapshot().Select(x => x.CycleVersion)),
"history is bounded and deduplicated");
}
private static void SerializesStableCamelCaseJson()
{
string json = VisualizationJson.Serialize(Snap(2));
Verification.True(json.Contains("\"sessionStateChinese\"") && json.Contains("\"observedAtUtc\""),
"JSON uses stable camel case names");
}
private static void RejectsInvalidOptions()
{
Verification.Throws<ArgumentOutOfRangeException>(
() => new PlanningVisualizationOptions { Port = -1 }.CreateValidatedSnapshot(),
"options reject a negative port");
Verification.Throws<ArgumentOutOfRangeException>(
() => new PlanningVisualizationOptions { RefreshRateHz = 0 }.CreateValidatedSnapshot(),
"options reject a zero refresh rate");
Verification.Throws<ArgumentOutOfRangeException>(
() => new PlanningVisualizationOptions { HistoryCycleLimit = 0 }.CreateValidatedSnapshot(),
"options reject a zero history limit");
Verification.Throws<ArgumentOutOfRangeException>(
() => new PlanningVisualizationOptions { Port = 65536 }.CreateValidatedSnapshot(),
"options reject a port above the TCP range");
var snapshot = new PlanningVisualizationOptions().CreateValidatedSnapshot();
Verification.Equal(0, snapshot.Port, "default port is automatic");
Verification.Equal(10, snapshot.RefreshRateHz, "default refresh rate is 10 Hz");
Verification.Equal(60, snapshot.HistoryCycleLimit, "default history is bounded to 60 cycles");
Verification.Equal(2, snapshot.MaximumClients, "maximum clients is fixed at two");
}
private static PlanningVisualizationDynamicSnapshot Snap(long sequence)
{
return new PlanningVisualizationDynamicSnapshot(
sequence,
DateTimeOffset.Parse("2026-08-06T00:00:00+00:00").AddSeconds(sequence),
"运行中",
0,
"forward",
new VisualizationPose(1d, 2d, 0d),
Array.Empty<VisualizationPolyline>(),
Array.Empty<VisualizationMarker>(),
Array.Empty<VisualizationChart>(),
Array.Empty<VisualizationValue>(),
Cycle(sequence));
}
private static VisualizationCycleSummary Cycle(long cycleVersion)
{
return new VisualizationCycleSummary(
cycleVersion,
DateTimeOffset.Parse("2026-08-06T00:00:00+00:00").AddSeconds(cycleVersion),
"成功",
true,
2.5d,
0,
"forward",
"rolling",
"none",
null,
null,
"");
}
}