lnd/graph/db/reject_cache_test.go
Elle Mouton f8899dd324
graph/db: migrate tests from Fatal to require helpers
Replace remaining fatal-style assertions in graph/db tests with direct
testify/require helpers. This simplifies control flow and reduces
indentation by using NoError, True/False, Equal, Len, Empty, and Nil
assertions directly.
2026-02-25 11:14:55 +02:00

103 lines
3.1 KiB
Go

package graphdb
import (
"testing"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
// TestRejectCache checks the behavior of the rejectCache with respect to insertion,
// eviction, and removal of cache entries.
func TestRejectCache(t *testing.T) {
const cacheSize = 100
// Create a new reject cache with the configured max size.
c := newRejectCache(cacheSize)
// As a sanity check, assert that querying the empty cache does not
// return an entry.
_, ok := c.get(lnwire.GossipVersion1, 0)
require.False(t, ok)
// Now, fill up the cache entirely.
for i := uint64(0); i < cacheSize; i++ {
c.insert(lnwire.GossipVersion1, i, entryForInt(i))
}
// Assert that the cache has all of the entries just inserted, since no
// eviction should occur until we try to surpass the max size.
assertHasEntries(t, c, 0, cacheSize)
// Now, insert a new element that causes the cache to evict an element.
c.insert(
lnwire.GossipVersion1, cacheSize,
entryForInt(cacheSize),
)
// Assert that the cache has this last entry, as the cache should evict
// some prior element and not the newly inserted one.
assertHasEntries(t, c, cacheSize, cacheSize)
// Iterate over all inserted elements and construct a set of the evicted
// elements.
evicted := make(map[uint64]struct{})
for i := uint64(0); i < cacheSize+1; i++ {
_, ok := c.get(lnwire.GossipVersion1, i)
if !ok {
evicted[i] = struct{}{}
}
}
// Assert that exactly one element has been evicted.
numEvicted := len(evicted)
require.Equal(t, 1, numEvicted)
// Remove the highest item which initially caused the eviction and
// reinsert the element that was evicted prior.
c.remove(lnwire.GossipVersion1, cacheSize)
for i := range evicted {
c.insert(lnwire.GossipVersion1, i, entryForInt(i))
}
// Since the removal created an extra slot, the last insertion should
// not have caused an eviction and the entries for all channels in the
// original set that filled the cache should be present.
assertHasEntries(t, c, 0, cacheSize)
// Finally, reinsert the existing set back into the cache and test that
// the cache still has all the entries. If the randomized eviction were
// happening on inserts for existing cache items, we expect this to fail
// with high probability.
for i := uint64(0); i < cacheSize; i++ {
c.insert(lnwire.GossipVersion1, i, entryForInt(i))
}
assertHasEntries(t, c, 0, cacheSize)
}
// assertHasEntries queries the reject cache for all channels in the range [start,
// end), asserting that they exist and their value matches the entry produced by
// entryForInt.
func assertHasEntries(t *testing.T, c *rejectCache, start, end uint64) {
t.Helper()
for i := start; i < end; i++ {
entry, ok := c.get(lnwire.GossipVersion1, i)
require.True(t, ok)
expEntry := entryForInt(i)
require.Equal(t, expEntry, entry)
}
}
// entryForInt generates a unique rejectCacheEntry given an integer.
func entryForInt(i uint64) rejectCacheEntry {
exists := i%2 == 0
isZombie := i%3 == 0
return rejectCacheEntry{
upd1Time: int64(2 * i),
upd2Time: int64(2*i + 1),
flags: packRejectFlags(exists, isZombie),
}
}