ThrustAllocator: tests for a one-thruster first call and for stale rows; drop the b clear

Stryker survivors 12390 (initial _columns +1 skips the first resize at n = 1) and
12399/12400 (A not cleared between same-count calls) get tests. Array.Clear on b was an
equivalent mutant: rows 0-6 are assigned every call and the ridge rows are never written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-10 03:23:50 +02:00
commit c770e11bfa
2 changed files with 21 additions and 1 deletions

View file

@ -40,7 +40,6 @@ public sealed class ThrustAllocator
var vars = n + ErrorVariables;
var rows = FixedRows + n;
Array.Clear(_a, 0, rows * vars);
Array.Clear(_b, 0, rows);
// Rows 0 and 1 are the translation axes (starboard, forward), row 2 the yaw.
for (var axis = 0; axis < 3; axis++)

View file

@ -290,4 +290,25 @@ public class ThrustAllocatorTests
for (var i = 0; i < columns.Length; i++) Assert.True(MathF.Abs(warm[i] - fresh[i]) <= 1e-5f, $"{columns.Length} columns: throttle {i}");
}
}
[Fact]
public void AShipWithOneThrusterIsFlownFromItsFirstCall()
{
var throttle = Solve(new[] { Col(0, 50, 0) }, 0, 1, 0);
Assert.True(throttle[0] > .99f, $"{throttle[0]}");
}
[Fact]
public void ChangedColumnsOfTheSameCountLeaveNothingBehind()
{
// Thruster 1 first strafes, then only pushes forward: the strafe row it left must not shape the second answer.
var strafing = new[] { Col(0, 60, 0), Col(30, 0, 0), Col(-20, 0, 0) };
var forwardOnly = new[] { Col(0, 60, 0), Col(0, 40, 0), Col(0, -20, 0) };
var allocator = new ThrustAllocator();
Solve(allocator, strafing, 1, 1, .5f);
var warm = Solve(allocator, forwardOnly, 0, 1, 0);
var fresh = Solve(forwardOnly, 0, 1, 0);
for (var i = 0; i < warm.Length; i++) Assert.True(MathF.Abs(warm[i] - fresh[i]) <= 1e-5f, $"throttle {i}: {warm[i]} vs {fresh[i]}");
Assert.True(warm[1] > .9f, $"{warm[1]}");
}
}