File: ttl_test.go

package info (click to toggle)
golang-github-dgraph-io-ristretto 2.3.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,004 kB
  • sloc: ansic: 78; asm: 37; makefile: 15
file content (82 lines) | stat: -rw-r--r-- 2,852 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
 * SPDX-License-Identifier: Apache-2.0
 */

package ristretto

import (
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

// TestExpirationMapCleanup tests the cleanup functionality of the expiration map.
// It verifies that expired items are correctly evicted from the store and that
// non-expired items remain in the store.
func TestExpirationMapCleanup(t *testing.T) {
	// Create a new expiration map
	em := newExpirationMap[int]()
	// Create a new store
	s := newShardedMap[int]()
	// Create a new policy
	p := newDefaultPolicy[int](100, 10)

	// Add items to the store and expiration map
	now := time.Now()
	i1 := &Item[int]{Key: 1, Conflict: 1, Value: 100, Expiration: now.Add(1 * time.Second)}
	s.Set(i1)
	em.add(i1.Key, i1.Conflict, i1.Expiration)

	i2 := &Item[int]{Key: 2, Conflict: 2, Value: 200, Expiration: now.Add(3 * time.Second)}
	s.Set(i2)
	em.add(i2.Key, i2.Conflict, i2.Expiration)

	// Create a map to store evicted items
	evictedItems := make(map[uint64]int)
	evictedItemsOnEvictFunc := func(item *Item[int]) {
		evictedItems[item.Key] = item.Value
	}

	// Wait for the first item to expire
	time.Sleep(2 * time.Second)

	// Cleanup the expiration map
	cleanedBucketsCount := em.cleanup(s, p, evictedItemsOnEvictFunc)
	require.Equal(t, 1, cleanedBucketsCount, "cleanedBucketsCount should be 1 after first cleanup")

	// Check that the first item was evicted
	require.Equal(t, 1, len(evictedItems), "evictedItems should have 1 item")
	require.Equal(t, 100, evictedItems[1], "evictedItems should have the first item")
	_, ok := s.Get(i1.Key, i1.Conflict)
	require.False(t, ok, "i1 should have been evicted")

	// Check that the second item is still in the store
	_, ok = s.Get(i2.Key, i2.Conflict)
	require.True(t, ok, "i2 should still be in the store")

	// Wait for the second item to expire
	time.Sleep(2 * time.Second)

	// Cleanup the expiration map
	cleanedBucketsCount = em.cleanup(s, p, evictedItemsOnEvictFunc)
	require.Equal(t, 1, cleanedBucketsCount, "cleanedBucketsCount should be 1 after second cleanup")

	// Check that the second item was evicted
	require.Equal(t, 2, len(evictedItems), "evictedItems should have 2 items")
	require.Equal(t, 200, evictedItems[2], "evictedItems should have the second item")
	_, ok = s.Get(i2.Key, i2.Conflict)
	require.False(t, ok, "i2 should have been evicted")

	t.Run("Miscalculation of buckets does not cause memory leaks", func(t *testing.T) {
		// Break lastCleanedBucketNum, this can happen if the system time is changed.
		em.lastCleanedBucketNum = storageBucket(now.AddDate(-1, 0, 0))

		cleanedBucketsCount = em.cleanup(s, p, evictedItemsOnEvictFunc)
		require.Equal(t,
			0, cleanedBucketsCount,
			"cleanedBucketsCount should be 0 after cleanup with lastCleanedBucketNum change",
		)
	})
}