// Tests for Account.AddReverseRespMapEntry / CheckForReverseEntries and related helpers. // Go reference: server/accounts.go — addRespMapEntry (~line 2800), checkForReverseEntries (~line 2810). using NATS.Server.Auth; namespace NATS.Server.Tests.Auth; public class ReverseResponseMapTests { // --------------------------------------------------------------------------- // AddReverseRespMapEntry / CheckForReverseEntries // --------------------------------------------------------------------------- [Fact] public void AddReverseRespMapEntry_StoresEntry() { // Go ref: accounts.go addRespMapEntry — stores respMapEntry keyed by rewritten reply var account = new Account("A"); account.AddReverseRespMapEntry("_R_.abc", "B", "reply.1"); account.ReverseResponseMapCount.ShouldBe(1); } [Fact] public void CheckForReverseEntries_Found_ReturnsEntry() { // Go ref: accounts.go checkForReverseEntries — returns entry when key exists var account = new Account("A"); account.AddReverseRespMapEntry("_R_.xyz", "origin-account", "original.reply.subject"); var entry = account.CheckForReverseEntries("_R_.xyz"); entry.ShouldNotBeNull(); entry.ReplySubject.ShouldBe("_R_.xyz"); entry.OriginAccount.ShouldBe("origin-account"); entry.OriginalReply.ShouldBe("original.reply.subject"); } [Fact] public void CheckForReverseEntries_NotFound_ReturnsNull() { // Go ref: accounts.go checkForReverseEntries — returns nil when key absent var account = new Account("A"); var entry = account.CheckForReverseEntries("_R_.nonexistent"); entry.ShouldBeNull(); } // --------------------------------------------------------------------------- // RemoveReverseRespMapEntry // --------------------------------------------------------------------------- [Fact] public void RemoveReverseRespMapEntry_Found_ReturnsTrue() { // Go ref: accounts.go — reverse map cleanup after response is routed var account = new Account("A"); account.AddReverseRespMapEntry("_R_.del", "B", "orig.reply"); var removed = account.RemoveReverseRespMapEntry("_R_.del"); removed.ShouldBeTrue(); account.ReverseResponseMapCount.ShouldBe(0); } [Fact] public void RemoveReverseRespMapEntry_NotFound_ReturnsFalse() { // Go ref: accounts.go — removing an absent entry is a no-op var account = new Account("A"); var removed = account.RemoveReverseRespMapEntry("_R_.missing"); removed.ShouldBeFalse(); } // --------------------------------------------------------------------------- // ReverseResponseMapCount // --------------------------------------------------------------------------- [Fact] public void ReverseResponseMapCount_MatchesEntries() { // Go ref: accounts.go — map length reflects outstanding response mappings var account = new Account("A"); account.ReverseResponseMapCount.ShouldBe(0); account.AddReverseRespMapEntry("_R_.1", "B", "r1"); account.AddReverseRespMapEntry("_R_.2", "C", "r2"); account.AddReverseRespMapEntry("_R_.3", "D", "r3"); account.ReverseResponseMapCount.ShouldBe(3); account.RemoveReverseRespMapEntry("_R_.2"); account.ReverseResponseMapCount.ShouldBe(2); } // --------------------------------------------------------------------------- // ClearReverseResponseMap // --------------------------------------------------------------------------- [Fact] public void ClearReverseResponseMap_EmptiesAll() { // Go ref: accounts.go — clearing map after bulk expiry / account teardown var account = new Account("A"); account.AddReverseRespMapEntry("_R_.a", "B", "ra"); account.AddReverseRespMapEntry("_R_.b", "C", "rb"); account.ClearReverseResponseMap(); account.ReverseResponseMapCount.ShouldBe(0); account.CheckForReverseEntries("_R_.a").ShouldBeNull(); account.CheckForReverseEntries("_R_.b").ShouldBeNull(); } // --------------------------------------------------------------------------- // GetReverseResponseMapKeys // --------------------------------------------------------------------------- [Fact] public void GetReverseResponseMapKeys_ReturnsAllKeys() { // Go ref: accounts.go — iterating active respMapEntry keys for diagnostics var account = new Account("A"); account.AddReverseRespMapEntry("_R_.k1", "B", "r1"); account.AddReverseRespMapEntry("_R_.k2", "C", "r2"); var keys = account.GetReverseResponseMapKeys(); keys.Count.ShouldBe(2); keys.ShouldContain("_R_.k1"); keys.ShouldContain("_R_.k2"); } // --------------------------------------------------------------------------- // Overwrite and CreatedAt preservation // --------------------------------------------------------------------------- [Fact] public void AddReverseRespMapEntry_OverwritesPrevious() { // Go ref: accounts.go addRespMapEntry — map assignment overwrites existing key var account = new Account("A"); account.AddReverseRespMapEntry("_R_.ov", "B", "first.reply"); account.AddReverseRespMapEntry("_R_.ov", "C", "second.reply"); var entry = account.CheckForReverseEntries("_R_.ov"); entry.ShouldNotBeNull(); entry.OriginAccount.ShouldBe("C"); entry.OriginalReply.ShouldBe("second.reply"); account.ReverseResponseMapCount.ShouldBe(1); } [Fact] public void ReverseRespMapEntry_PreservesCreatedAt() { // Go ref: accounts.go respMapEntry — timestamp recorded at map insertion time var before = DateTime.UtcNow; var account = new Account("A"); account.AddReverseRespMapEntry("_R_.ts", "B", "ts.reply"); var after = DateTime.UtcNow; var entry = account.CheckForReverseEntries("_R_.ts"); entry.ShouldNotBeNull(); entry.CreatedAt.ShouldBeGreaterThanOrEqualTo(before); entry.CreatedAt.ShouldBeLessThanOrEqualTo(after); } }