github.com/outbrain/consul@v1.4.5/agent/cache/entry_test.go (about) 1 package cache 2 3 import ( 4 "container/heap" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestExpiryHeap_impl(t *testing.T) { 12 var _ heap.Interface = new(expiryHeap) 13 } 14 15 func TestExpiryHeap(t *testing.T) { 16 require := require.New(t) 17 now := time.Now() 18 ch := make(chan struct{}, 10) // buffered to prevent blocking in tests 19 h := &expiryHeap{NotifyCh: ch} 20 21 // Init, shouldn't trigger anything 22 heap.Init(h) 23 testNoMessage(t, ch) 24 25 // Push an initial value, expect one message 26 entry := &cacheEntryExpiry{Key: "foo", HeapIndex: -1, Expires: now.Add(100)} 27 heap.Push(h, entry) 28 require.Equal(0, entry.HeapIndex) 29 testMessage(t, ch) 30 testNoMessage(t, ch) // exactly one asserted above 31 32 // Push another that goes earlier than entry 33 entry2 := &cacheEntryExpiry{Key: "bar", HeapIndex: -1, Expires: now.Add(50)} 34 heap.Push(h, entry2) 35 require.Equal(0, entry2.HeapIndex) 36 require.Equal(1, entry.HeapIndex) 37 testMessage(t, ch) 38 testNoMessage(t, ch) // exactly one asserted above 39 40 // Push another that goes at the end 41 entry3 := &cacheEntryExpiry{Key: "bar", HeapIndex: -1, Expires: now.Add(1000)} 42 heap.Push(h, entry3) 43 require.Equal(2, entry3.HeapIndex) 44 testNoMessage(t, ch) // no notify cause index 0 stayed the same 45 46 // Remove the first entry (not Pop, since we don't use Pop, but that works too) 47 remove := h.Entries[0] 48 heap.Remove(h, remove.HeapIndex) 49 require.Equal(0, entry.HeapIndex) 50 require.Equal(1, entry3.HeapIndex) 51 testMessage(t, ch) 52 testMessage(t, ch) // we have two because two swaps happen 53 testNoMessage(t, ch) 54 55 // Let's change entry 3 to be early, and fix it 56 entry3.Expires = now.Add(10) 57 h.Fix(entry3) 58 require.Equal(1, entry.HeapIndex) 59 require.Equal(0, entry3.HeapIndex) 60 testMessage(t, ch) 61 testNoMessage(t, ch) 62 63 // Let's change entry 3 again, this is an edge case where if the 0th 64 // element changed, we didn't trigger the channel. Our Fix func should. 65 entry.Expires = now.Add(20) 66 h.Fix(entry3) 67 require.Equal(1, entry.HeapIndex) // no move 68 require.Equal(0, entry3.HeapIndex) 69 testMessage(t, ch) 70 testNoMessage(t, ch) // one message 71 } 72 73 func testNoMessage(t *testing.T, ch <-chan struct{}) { 74 t.Helper() 75 76 select { 77 case <-ch: 78 t.Fatal("should not have a message") 79 default: 80 } 81 } 82 83 func testMessage(t *testing.T, ch <-chan struct{}) { 84 t.Helper() 85 86 select { 87 case <-ch: 88 default: 89 t.Fatal("should have a message") 90 } 91 }