feat: add bounded visualization snapshots
This commit is contained in:
@@ -9,6 +9,7 @@ internal static class Program
|
||||
try
|
||||
{
|
||||
ContractChecks.Run();
|
||||
RuntimeChecks.Run();
|
||||
Console.WriteLine("PASS trajectory-planning-visualization");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
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,
|
||||
"");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user