ttlcache icon indicating copy to clipboard operation
ttlcache copied to clipboard

Set doesn't reset TTL if the key already exists

Open vsavicks opened this issue 1 year ago • 1 comments

According to the docs of the Set() method:

If an item associated with the provided key already exists, the new item overwrites the existing one.

However, if I try to set an item that already exists but has an expired TTL and delete all expired, the newly set item also gets deleted:

package main

import (
	"fmt"
	"time"

	"github.com/jellydator/ttlcache/v3"
)

func main() {
	cache := ttlcache.New[string](
		ttlcache.WithTTL[string, string](1 * time.Second),
	)
	cache.Set("foo", "bar", ttlcache.DefaultTTL)
	fmt.Printf("first: %s\n", cache.Keys())

	time.Sleep(2 * time.Second)
	fmt.Printf("after 2s: %s\n", cache.Keys())

	cache.DeleteExpired()
	fmt.Printf("after delete: %s\n", cache.Keys())

	cache.Set("baz", "qux", ttlcache.DefaultTTL)
	fmt.Printf("new: %s\n", cache.Keys())

	time.Sleep(2 * time.Second)
	fmt.Printf("after 2s: %s\n", cache.Keys())

	cache.Set("baz", "qum", ttlcache.DefaultTTL)
	cache.DeleteExpired()
	fmt.Printf("after set and delete: %s\n", cache.Keys())
}

Output:

first: [foo]
after 2s: [foo]
after delete: []
new: [baz]
after 2s: [baz]
after set and delete: []

I would expect the replaced item to have new TTL and not get deleted by DeleteExpired() call.

vsavicks avatar May 09 '24 23:05 vsavicks

Thanks for reporting this @vsavicks. We'll try to have it fixed soon.

swithek avatar May 11 '24 10:05 swithek

just to provide some infomation.

I can't reproduce it at:

go version go1.23.5 darwin/arm64 github.com/jellydator/ttlcache/[email protected]

same code. but the output is:

first: [foo]
after 2s: []
after delete: []
new: [baz]
after 2s: []
after set and delete: [baz]

QisFj avatar Jan 24 '25 07:01 QisFj

Entertainingly if I try to add a test case for this, I get different results:

func TestBug136(t *testing.T) {
    t.Parallel()
    c := New[string, string](WithTTL[string, string](time.Millisecond))
    c.Set("foo", "bar", DefaultTTL)
    time.Sleep(2 * time.Millisecond)
    assert.Equal(t, []string{"foo"}, c.Keys())
    c.DeleteExpired()
    assert.Equal(t, []string{}, c.Keys())
    c.Set("baz", "qux", DefaultTTL)
    time.Sleep(2 * time.Millisecond)
    c.Set("baz", "bux", DefaultTTL)
    c.DeleteExpired()
    require.Equal(t, []string{"baz"}, c.Keys())
}
jellydator/ttlcache  bug/136 *?!❯ go test -v -race -shuffle on -timeout 1m -coverprofile=covprofile ./...            21s go-v1.23.7 1 07:59:31
-test.shuffle 1742648374783277255
=== RUN   Test_expirationQueue_Len
--- PASS: Test_expirationQueue_Len (0.00s)
=== RUN   Test_expirationQueue_push
--- PASS: Test_expirationQueue_push (0.00s)
=== RUN   Test_WithCapacity
=== PAUSE Test_WithCapacity
=== RUN   Test_Cache_Has
--- PASS: Test_Cache_Has (0.00s)
=== RUN   Test_withVersionTracking
=== PAUSE Test_withVersionTracking
=== RUN   Test_Cache_DeleteExpired
--- PASS: Test_Cache_DeleteExpired (0.00s)
=== RUN   Test_Cache_get
=== RUN   Test_Cache_get/Retrieval_of_existing_item_without_update
=== PAUSE Test_Cache_get/Retrieval_of_existing_item_without_update
=== RUN   Test_Cache_get/Retrieval_of_existing_item_with_touch_and_non_zero_TTL
=== PAUSE Test_Cache_get/Retrieval_of_existing_item_with_touch_and_non_zero_TTL
=== RUN   Test_Cache_get/Retrieval_of_existing_item_with_touch_and_zero_TTL
=== PAUSE Test_Cache_get/Retrieval_of_existing_item_with_touch_and_zero_TTL
=== RUN   Test_Cache_get/Retrieval_of_non-existent_item
=== PAUSE Test_Cache_get/Retrieval_of_non-existent_item
=== RUN   Test_Cache_get/Retrieval_of_expired_item
=== PAUSE Test_Cache_get/Retrieval_of_expired_item
=== CONT  Test_Cache_get/Retrieval_of_existing_item_with_touch_and_non_zero_TTL
=== CONT  Test_Cache_get/Retrieval_of_non-existent_item
=== CONT  Test_Cache_get/Retrieval_of_expired_item
=== CONT  Test_Cache_get/Retrieval_of_existing_item_with_touch_and_zero_TTL
=== CONT  Test_Cache_get/Retrieval_of_existing_item_without_update
--- PASS: Test_Cache_get (0.00s)
    --- PASS: Test_Cache_get/Retrieval_of_existing_item_with_touch_and_non_zero_TTL (0.00s)
    --- PASS: Test_Cache_get/Retrieval_of_existing_item_with_touch_and_zero_TTL (0.00s)
    --- PASS: Test_Cache_get/Retrieval_of_existing_item_without_update (0.00s)
    --- PASS: Test_Cache_get/Retrieval_of_non-existent_item (0.00s)
    --- PASS: Test_Cache_get/Retrieval_of_expired_item (0.00s)
=== RUN   Test_Cache_Start
--- PASS: Test_Cache_Start (1.00s)
=== RUN   Test_Cache_Keys
--- PASS: Test_Cache_Keys (0.00s)
=== RUN   Test_Cache_Stop
--- PASS: Test_Cache_Stop (0.00s)
=== RUN   Test_Cache_OnInsertion
--- PASS: Test_Cache_OnInsertion (1.40s)
=== RUN   Test_WithMaxCost
=== PAUSE Test_WithMaxCost
=== RUN   Test_LoaderFunc_Load
--- PASS: Test_LoaderFunc_Load (0.00s)
=== RUN   Test_expirationQueue_update
--- PASS: Test_expirationQueue_update (0.00s)
=== RUN   Test_expirationQueue_Swap
--- PASS: Test_expirationQueue_Swap (0.00s)
=== RUN   Test_WithLoader
=== PAUSE Test_WithLoader
=== RUN   Test_newItemWithOpts
=== PAUSE Test_newItemWithOpts
=== RUN   Test_Item_TTL
=== PAUSE Test_Item_TTL
=== RUN   Test_NewItem
=== PAUSE Test_NewItem
=== RUN   Test_Cache_Items
--- PASS: Test_Cache_Items (0.00s)
=== RUN   Test_Cache_Len
--- PASS: Test_Cache_Len (0.00s)
=== RUN   Test_newExpirationQueue
--- PASS: Test_newExpirationQueue (0.00s)
=== RUN   TestBug136
=== PAUSE TestBug136
=== RUN   Test_WithTTL
=== PAUSE Test_WithTTL
=== RUN   Test_Item_update
=== PAUSE Test_Item_update
=== RUN   Test_Cache_Range
--- PASS: Test_Cache_Range (0.00s)
=== RUN   Test_optionFunc_apply
=== PAUSE Test_optionFunc_apply
=== RUN   Test_Cache_updateExpirations
=== RUN   Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_non_fresh_item_and_matching_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_non_fresh_item_and_matching_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_non_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_non_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_fresh_item_and_matching_new_and_old_expiresAt_fields
=== PAUSE Test_Cache_updateExpirations/Update_with_fresh_item_and_matching_new_and_old_expiresAt_fields
=== RUN   Test_Cache_updateExpirations/Update_with_non_zero_new_expiresAt_field_and_empty_queue
=== PAUSE Test_Cache_updateExpirations/Update_with_non_zero_new_expiresAt_field_and_empty_queue
=== CONT  Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_non_zero_new_expiresAt_field_and_empty_queue
=== CONT  Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_non_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_fresh_item_and_matching_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_non_fresh_item_and_matching_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields
=== CONT  Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_old_expiresAt_fields
--- PASS: Test_Cache_updateExpirations (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_non_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_non_zero_new_expiresAt_field_and_empty_queue (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_zero_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_fresh_item_and_matching_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_non_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_fresh_item_and_zero_new_and_non_zero_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_non_fresh_item_and_matching_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_full_timerCh_(greater_value),_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
    --- PASS: Test_Cache_updateExpirations/Update_with_full_timerCh_(lesser_value),_non_fresh_item_and_non_zero_new_and_old_expiresAt_fields (0.00s)
=== RUN   Test_applyOptions
=== PAUSE Test_applyOptions
=== RUN   Test_Item_Version
=== PAUSE Test_Item_Version
=== RUN   Test_Cache_Touch
--- PASS: Test_Cache_Touch (0.00s)
=== RUN   Test_New
--- PASS: Test_New (0.00s)
=== RUN   Test_Cache_set
=== RUN   Test_Cache_set/Set_with_new_key_and_eviction_caused_by_small_capacity
=== PAUSE Test_Cache_set/Set_with_new_key_and_eviction_caused_by_small_capacity
=== RUN   Test_Cache_set/Set_with_existing_key_and_eviction_caused_by_exhausted_cost
=== PAUSE Test_Cache_set/Set_with_existing_key_and_eviction_caused_by_exhausted_cost
=== RUN   Test_Cache_set/Set_with_existing_key_and_no_eviction
=== PAUSE Test_Cache_set/Set_with_existing_key_and_no_eviction
=== RUN   Test_Cache_set/Set_with_existing_key_and_DefaultTTL
=== PAUSE Test_Cache_set/Set_with_existing_key_and_DefaultTTL
=== RUN   Test_Cache_set/Set_with_existing_key_and_PreviousOrDefaultTTL
=== PAUSE Test_Cache_set/Set_with_existing_key_and_PreviousOrDefaultTTL
=== RUN   Test_Cache_set/Set_with_new_key_and_no_eviction_caused_by_large_capacity
=== PAUSE Test_Cache_set/Set_with_new_key_and_no_eviction_caused_by_large_capacity
=== RUN   Test_Cache_set/Set_with_new_key_and_custom_TTL
=== PAUSE Test_Cache_set/Set_with_new_key_and_custom_TTL
=== RUN   Test_Cache_set/Set_with_new_key_and_NoTTL
=== PAUSE Test_Cache_set/Set_with_new_key_and_NoTTL
=== RUN   Test_Cache_set/Set_with_new_key_and_DefaultTTL
=== PAUSE Test_Cache_set/Set_with_new_key_and_DefaultTTL
=== RUN   Test_Cache_set/Set_with_new_key_and_PreviousOrDefaultTTL
=== PAUSE Test_Cache_set/Set_with_new_key_and_PreviousOrDefaultTTL
=== RUN   Test_Cache_set/Set_with_new_key_and_eviction_caused_by_exhausted_cost
=== PAUSE Test_Cache_set/Set_with_new_key_and_eviction_caused_by_exhausted_cost
=== RUN   Test_Cache_set/Set_with_existing_key_and_custom_TTL
=== PAUSE Test_Cache_set/Set_with_existing_key_and_custom_TTL
=== RUN   Test_Cache_set/Set_with_existing_key_and_NoTTL
=== PAUSE Test_Cache_set/Set_with_existing_key_and_NoTTL
=== CONT  Test_Cache_set/Set_with_existing_key_and_eviction_caused_by_exhausted_cost
=== CONT  Test_Cache_set/Set_with_new_key_and_PreviousOrDefaultTTL
=== CONT  Test_Cache_set/Set_with_existing_key_and_custom_TTL
=== CONT  Test_Cache_set/Set_with_existing_key_and_NoTTL
=== CONT  Test_Cache_set/Set_with_new_key_and_eviction_caused_by_exhausted_cost
=== CONT  Test_Cache_set/Set_with_new_key_and_DefaultTTL
=== CONT  Test_Cache_set/Set_with_new_key_and_NoTTL
=== CONT  Test_Cache_set/Set_with_new_key_and_no_eviction_caused_by_large_capacity
=== CONT  Test_Cache_set/Set_with_new_key_and_custom_TTL
=== CONT  Test_Cache_set/Set_with_existing_key_and_PreviousOrDefaultTTL
=== CONT  Test_Cache_set/Set_with_new_key_and_eviction_caused_by_small_capacity
=== CONT  Test_Cache_set/Set_with_existing_key_and_DefaultTTL
=== CONT  Test_Cache_set/Set_with_existing_key_and_no_eviction
--- PASS: Test_Cache_set (0.14s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_eviction_caused_by_exhausted_cost (0.00s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_custom_TTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_PreviousOrDefaultTTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_NoTTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_DefaultTTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_eviction_caused_by_exhausted_cost (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_no_eviction_caused_by_large_capacity (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_NoTTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_custom_TTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_new_key_and_eviction_caused_by_small_capacity (0.00s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_no_eviction (0.00s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_PreviousOrDefaultTTL (0.00s)
    --- PASS: Test_Cache_set/Set_with_existing_key_and_DefaultTTL (0.00s)
=== RUN   Test_Cache_OnEviction
--- PASS: Test_Cache_OnEviction (1.40s)
=== RUN   Test_NewSuppressedLoader
--- PASS: Test_NewSuppressedLoader (0.00s)
=== RUN   Test_WithVersion
=== PAUSE Test_WithVersion
=== RUN   Test_Cache_DeleteAll
--- PASS: Test_Cache_DeleteAll (0.00s)
=== RUN   Test_expirationQueue_Pop
--- PASS: Test_expirationQueue_Pop (0.00s)
=== RUN   Test_WithDisableTouchOnHit
=== PAUSE Test_WithDisableTouchOnHit
=== RUN   Test_expirationQueue_Push
--- PASS: Test_expirationQueue_Push (0.00s)
=== RUN   Test_Cache_RangeBackwards
--- PASS: Test_Cache_RangeBackwards (0.00s)
=== RUN   Test_Cache_Delete
--- PASS: Test_Cache_Delete (0.00s)
=== RUN   Test_withCostFunc
=== PAUSE Test_withCostFunc
=== RUN   Test_Item_Value
=== PAUSE Test_Item_Value
=== RUN   Test_expirationQueue_isEmpty
--- PASS: Test_expirationQueue_isEmpty (0.00s)
=== RUN   Test_expirationQueue_remove
--- PASS: Test_expirationQueue_remove (0.00s)
=== RUN   Test_Cache_Get
=== RUN   Test_Cache_Get/Get_with_call_loader_that_returns_nil_value_when_item_is_not_found
=== PAUSE Test_Cache_Get/Get_with_call_loader_that_returns_nil_value_when_item_is_not_found
=== RUN   Test_Cache_Get/Get_when_TTL_extension_is_disabled_and_item_is_found
=== PAUSE Test_Cache_Get/Get_when_TTL_extension_is_disabled_and_item_is_found
=== RUN   Test_Cache_Get/Get_without_loader_when_item_is_not_found
=== PAUSE Test_Cache_Get/Get_without_loader_when_item_is_not_found
=== RUN   Test_Cache_Get/Get_when_TTL_extension_is_disabled_by_default_and_item_is_found
=== PAUSE Test_Cache_Get/Get_when_TTL_extension_is_disabled_by_default_and_item_is_found
=== RUN   Test_Cache_Get/Get_when_item_is_found
=== PAUSE Test_Cache_Get/Get_when_item_is_found
=== RUN   Test_Cache_Get/Get_with_default_loader_that_returns_non_nil_value_when_item_is_not_found
=== PAUSE Test_Cache_Get/Get_with_default_loader_that_returns_non_nil_value_when_item_is_not_found
=== RUN   Test_Cache_Get/Get_with_default_loader_that_returns_nil_value_when_item_is_not_found
=== PAUSE Test_Cache_Get/Get_with_default_loader_that_returns_nil_value_when_item_is_not_found
=== RUN   Test_Cache_Get/Get_with_call_loader_that_returns_non_nil_value_when_item_is_not_found
=== PAUSE Test_Cache_Get/Get_with_call_loader_that_returns_non_nil_value_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_when_TTL_extension_is_disabled_and_item_is_found
=== CONT  Test_Cache_Get/Get_with_default_loader_that_returns_nil_value_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_with_call_loader_that_returns_nil_value_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_with_call_loader_that_returns_non_nil_value_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_without_loader_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_when_TTL_extension_is_disabled_by_default_and_item_is_found
=== CONT  Test_Cache_Get/Get_with_default_loader_that_returns_non_nil_value_when_item_is_not_found
=== CONT  Test_Cache_Get/Get_when_item_is_found
--- PASS: Test_Cache_Get (0.00s)
    --- PASS: Test_Cache_Get/Get_when_TTL_extension_is_disabled_and_item_is_found (0.00s)
    --- PASS: Test_Cache_Get/Get_with_call_loader_that_returns_nil_value_when_item_is_not_found (0.00s)
    --- PASS: Test_Cache_Get/Get_with_default_loader_that_returns_nil_value_when_item_is_not_found (0.00s)
    --- PASS: Test_Cache_Get/Get_with_call_loader_that_returns_non_nil_value_when_item_is_not_found (0.00s)
    --- PASS: Test_Cache_Get/Get_with_default_loader_that_returns_non_nil_value_when_item_is_not_found (0.00s)
    --- PASS: Test_Cache_Get/Get_without_loader_when_item_is_not_found (0.00s)
    --- PASS: Test_Cache_Get/Get_when_TTL_extension_is_disabled_by_default_and_item_is_found (0.00s)
    --- PASS: Test_Cache_Get/Get_when_item_is_found (0.00s)
=== RUN   Test_Item_Key
=== PAUSE Test_Item_Key
=== RUN   Test_Cache_GetAndDelete
--- PASS: Test_Cache_GetAndDelete (0.00s)
=== RUN   Test_Item_touch
=== PAUSE Test_Item_touch
=== RUN   Test_expirationQueue_Less
--- PASS: Test_expirationQueue_Less (0.00s)
=== RUN   Test_Cache_GetOrSet
--- PASS: Test_Cache_GetOrSet (0.00s)
=== RUN   Test_Cache_evict
--- PASS: Test_Cache_evict (0.00s)
=== RUN   Test_Item_ExpiresAt
=== PAUSE Test_Item_ExpiresAt
=== RUN   Test_Cache_Set
--- PASS: Test_Cache_Set (0.00s)
=== RUN   Test_Cache_Metrics
--- PASS: Test_Cache_Metrics (0.00s)
=== RUN   Test_Item_IsExpired
=== PAUSE Test_Item_IsExpired
=== RUN   Test_SuppressedLoader_Load
--- PASS: Test_SuppressedLoader_Load (0.20s)
=== CONT  Test_WithCapacity
=== CONT  Test_applyOptions
=== CONT  Test_WithDisableTouchOnHit
--- PASS: Test_WithCapacity (0.00s)
--- PASS: Test_WithDisableTouchOnHit (0.00s)
=== CONT  Test_Item_ExpiresAt
--- PASS: Test_applyOptions (0.00s)
=== CONT  Test_optionFunc_apply
=== CONT  Test_Item_update
--- PASS: Test_optionFunc_apply (0.00s)
=== CONT  Test_Item_Version
--- PASS: Test_Item_ExpiresAt (0.00s)
=== CONT  Test_withCostFunc
=== CONT  Test_WithTTL
=== CONT  Test_NewItem
=== CONT  Test_Item_Value
=== CONT  Test_Item_TTL
=== CONT  Test_newItemWithOpts
=== CONT  Test_WithMaxCost
=== CONT  Test_withVersionTracking
=== CONT  Test_WithLoader
=== CONT  Test_Item_touch
=== CONT  Test_Item_IsExpired
=== CONT  Test_Item_Key
=== RUN   Test_Item_update/with_expiration_in_an_hour
=== CONT  TestBug136
=== CONT  Test_WithVersion
--- PASS: Test_Item_Version (0.00s)
=== RUN   Test_newItemWithOpts/item_without_any_options
--- PASS: Test_WithTTL (0.00s)
--- PASS: Test_withCostFunc (0.00s)
--- PASS: Test_NewItem (0.00s)
--- PASS: Test_WithVersion (0.00s)
--- PASS: Test_Item_Value (0.00s)
--- PASS: Test_Item_TTL (0.00s)
--- PASS: Test_WithMaxCost (0.00s)
=== RUN   Test_Item_update/with_previous_or_default_ttl
--- PASS: Test_withVersionTracking (0.00s)
--- PASS: Test_WithLoader (0.00s)
--- PASS: Test_Item_touch (0.00s)
--- PASS: Test_Item_IsExpired (0.00s)
--- PASS: Test_Item_Key (0.00s)
=== RUN   Test_Item_update/with_no_ttl
=== RUN   Test_newItemWithOpts/item_with_version_tracking_disabled
=== RUN   Test_Item_update/with_version_tracking_explicitly_disabled
=== RUN   Test_newItemWithOpts/item_with_version_tracking_explicitly_enabled
=== RUN   Test_Item_update/with_version_calculation_and_version_tracking
=== RUN   Test_newItemWithOpts/item_with_cost_calculation
--- PASS: Test_Item_update (0.00s)
    --- PASS: Test_Item_update/with_expiration_in_an_hour (0.00s)
    --- PASS: Test_Item_update/with_previous_or_default_ttl (0.00s)
    --- PASS: Test_Item_update/with_no_ttl (0.00s)
    --- PASS: Test_Item_update/with_version_tracking_explicitly_disabled (0.00s)
    --- PASS: Test_Item_update/with_version_calculation_and_version_tracking (0.00s)
--- PASS: Test_newItemWithOpts (0.00s)
    --- PASS: Test_newItemWithOpts/item_without_any_options (0.00s)
    --- PASS: Test_newItemWithOpts/item_with_version_tracking_disabled (0.00s)
    --- PASS: Test_newItemWithOpts/item_with_version_tracking_explicitly_enabled (0.00s)
    --- PASS: Test_newItemWithOpts/item_with_cost_calculation (0.00s)
=== NAME  TestBug136
    cache_test.go:43:
                Error Trace:    /home/icordasc/sandbox/jellydator/ttlcache/cache_test.go:43
                Error:          Not equal:
                                expected: []string{"foo"}
                                actual  : []string{}

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,3 +1,2 @@
                                -([]string) (len=1) {
                                - (string) (len=3) "foo"
                                +([]string) {
                                 }
                Test:           TestBug136
--- FAIL: TestBug136 (0.01s)
FAIL
coverage: 99.5% of statements
FAIL    github.com/jellydator/ttlcache/v3       4.220s
-test.shuffle 1742648374779372262
testing: warning: no tests to run
PASS
coverage: [no statements]
ok      github.com/jellydator/ttlcache/v3/bench 1.019s  coverage: [no statements] [no tests to run]
FAIL

sigmavirus24 avatar Mar 22 '25 13:03 sigmavirus24

Removing the assert.Equal(t, []string{"foo"}, c.Keys()) line, the test passes without issue. Maybe this was fixed at some point after v3.3.0 was released

sigmavirus24 avatar Mar 22 '25 17:03 sigmavirus24

Couldn't reproduce @sigmavirus24 and @vsavicks cases. I believe it was fixed with https://github.com/jellydator/ttlcache/commit/62c37338e6b2e3d60cd8270834ecc15c1f8c6aff this.

Closing for now.

davseby avatar May 25 '25 13:05 davseby