fix(transport): zero a bundle session's content when it expires, not only on apply/abandon (review 2026-10-21 04/C3)
This commit is contained in:
@@ -130,6 +130,57 @@ public sealed class BundleSessionStoreTests
|
||||
Assert.Null(sut.Get(dropB.SessionId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Review 2026-10-21 04/C3: a session dropped by TTL expiry on the <c>Get</c> path
|
||||
/// has its content buffer zeroed, matching the zero-then-remove discipline that
|
||||
/// <c>ApplyAsync</c>/<c>Abandon</c> already follow.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Get_after_TTL_zeroes_the_content_buffer()
|
||||
{
|
||||
var clock = new TestTimeProvider(DateTimeOffset.UtcNow);
|
||||
var sut = new BundleSessionStore(Options(), clock);
|
||||
var content = new byte[] { 0x11, 0x22, 0x33 };
|
||||
var session = SessionWithContent(clock.GetUtcNow().AddMinutes(30), content);
|
||||
sut.Open(session);
|
||||
|
||||
clock.Advance(TimeSpan.FromMinutes(31));
|
||||
|
||||
Assert.Null(sut.Get(session.SessionId));
|
||||
Assert.All(content, b => Assert.Equal(0, b));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Review 2026-10-21 04/C3: <c>EvictExpired</c> zeroes the content buffer of each
|
||||
/// session it drops, and leaves a live session's buffer untouched.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void EvictExpired_zeroes_the_content_of_expired_sessions_only()
|
||||
{
|
||||
var clock = new TestTimeProvider(DateTimeOffset.UtcNow);
|
||||
var sut = new BundleSessionStore(Options(), clock);
|
||||
var expiredContent = new byte[] { 0x11, 0x22 };
|
||||
var liveContent = new byte[] { 0x33, 0x44 };
|
||||
sut.Open(SessionWithContent(clock.GetUtcNow().AddMinutes(5), expiredContent));
|
||||
var live = SessionWithContent(clock.GetUtcNow().AddMinutes(60), liveContent);
|
||||
sut.Open(live);
|
||||
|
||||
clock.Advance(TimeSpan.FromMinutes(10));
|
||||
sut.EvictExpired();
|
||||
|
||||
Assert.All(expiredContent, b => Assert.Equal(0, b));
|
||||
Assert.Equal(new byte[] { 0x33, 0x44 }, liveContent);
|
||||
Assert.NotNull(sut.Get(live.SessionId));
|
||||
}
|
||||
|
||||
private static BundleSession SessionWithContent(DateTimeOffset expiresAt, byte[] content) => new()
|
||||
{
|
||||
SessionId = Guid.NewGuid(),
|
||||
Manifest = StubManifest(),
|
||||
DecryptedContent = content,
|
||||
ExpiresAt = expiresAt,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that the legacy failed-unlock-attempts field still round-trips through the shared reference.</summary>
|
||||
[Fact]
|
||||
public void Legacy_FailedUnlockAttempts_field_still_round_trips_via_shared_reference()
|
||||
|
||||
Reference in New Issue
Block a user