fix(archreview): gateway core P0 remediation (GWC-01/02/03, TST-02, TST-12)
Interlocking changes across the gateway server (shared GatewaySession.cs / SessionManager.cs), committed together: - GWC-01 (Critical): alarm monitor now attaches as an internal (non-counted) distributor subscriber instead of a second raw drain of the single worker event channel; WorkerClient._events -> SingleReader with a claimed-once guard so a future dual-consumer regression throws loudly. - GWC-02 (High): faulted sessions are swept in CloseExpiredLeasesAsync (IsFaultedReapable + FaultedReason); new FaultedGraceSeconds (default 0). - GWC-03 (High): configurable MaxSparseArrayLength (default 1_000_000) enforced before allocation. - TST-02 (High, security): StreamEvents attach now enforces the opening key id -> PermissionDenied on owner mismatch. - TST-12 (Medium): CLAUDE.md retention-defaults sentence corrected. Verified: NonWindows build clean; targeted tests 135/135 on macOS, plus WorkerClientTests 18/18 on the Windows host.
This commit is contained in:
@@ -222,4 +222,35 @@ public sealed class SparseArrayExpanderTests
|
||||
RpcException ex = Assert.Throws<RpcException>(() => SparseArrayExpander.Expand(value));
|
||||
Assert.Equal(StatusCode.InvalidArgument, ex.StatusCode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a total length above the configured cap throws <see cref="StatusCode.InvalidArgument"/> before the full array is allocated.</summary>
|
||||
[Fact]
|
||||
public void Expand_TotalLengthExceedsConfiguredCap_ThrowsBeforeAllocation()
|
||||
{
|
||||
// A total_length that would force a huge allocation, but well below Array.MaxLength,
|
||||
// so only the configured cap can reject it (the Array.MaxLength backstop would not).
|
||||
MxValue value = SparseValue(MxDataType.Integer, 500_000_000u);
|
||||
|
||||
RpcException ex = Assert.Throws<RpcException>(() => SparseArrayExpander.Expand(value, maxSparseArrayLength: 1_000_000));
|
||||
Assert.Equal(StatusCode.InvalidArgument, ex.StatusCode);
|
||||
Assert.Contains("MaxSparseArrayLength", ex.Status.Detail, StringComparison.Ordinal);
|
||||
|
||||
// The value must be untouched — expansion (allocation) never ran.
|
||||
Assert.Equal(MxValue.KindOneofCase.SparseArrayValue, value.KindCase);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a total length at or below the configured cap still expands normally.</summary>
|
||||
[Fact]
|
||||
public void Expand_TotalLengthAtConfiguredCap_Expands()
|
||||
{
|
||||
MxValue value = SparseValue(
|
||||
MxDataType.Integer,
|
||||
4,
|
||||
(1, new MxValue { Int32Value = 7 }));
|
||||
|
||||
SparseArrayExpander.Expand(value, maxSparseArrayLength: 4);
|
||||
|
||||
Assert.Equal(MxValue.KindOneofCase.ArrayValue, value.KindCase);
|
||||
Assert.Equal(new[] { 0, 7, 0, 0 }, value.ArrayValue.Int32Values.Values);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user