Test returning to cache after tryclose
This commit is contained in:
parent
8b5a7de4ef
commit
ec7c33d820
@ -3,6 +3,7 @@ package ocache
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -12,10 +13,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type testObject struct {
|
type testObject struct {
|
||||||
name string
|
name string
|
||||||
closeErr error
|
closeErr error
|
||||||
closeCh chan struct{}
|
closeCh chan struct{}
|
||||||
tryReturn bool
|
tryReturn bool
|
||||||
|
closeCalled bool
|
||||||
|
tryCloseCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestObject(name string, tryReturn bool, closeCh chan struct{}) *testObject {
|
func NewTestObject(name string, tryReturn bool, closeCh chan struct{}) *testObject {
|
||||||
@ -27,6 +30,7 @@ func NewTestObject(name string, tryReturn bool, closeCh chan struct{}) *testObje
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *testObject) Close() (err error) {
|
func (t *testObject) Close() (err error) {
|
||||||
|
t.closeCalled = true
|
||||||
if t.closeCh != nil {
|
if t.closeCh != nil {
|
||||||
<-t.closeCh
|
<-t.closeCh
|
||||||
}
|
}
|
||||||
@ -34,6 +38,7 @@ func (t *testObject) Close() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *testObject) TryClose() (res bool, err error) {
|
func (t *testObject) TryClose() (res bool, err error) {
|
||||||
|
t.tryCloseCalled = true
|
||||||
if t.closeCh != nil {
|
if t.closeCh != nil {
|
||||||
<-t.closeCh
|
<-t.closeCh
|
||||||
return true, t.closeErr
|
return true, t.closeErr
|
||||||
@ -126,7 +131,7 @@ func TestOCache_Get(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOCache_GC(t *testing.T) {
|
func TestOCache_GC(t *testing.T) {
|
||||||
t.Run("test without close wait", func(t *testing.T) {
|
t.Run("test gc expired object", func(t *testing.T) {
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return NewTestObject(id, true, nil), nil
|
return NewTestObject(id, true, nil), nil
|
||||||
}, WithTTL(time.Millisecond*10))
|
}, WithTTL(time.Millisecond*10))
|
||||||
@ -140,7 +145,7 @@ func TestOCache_GC(t *testing.T) {
|
|||||||
c.GC()
|
c.GC()
|
||||||
assert.Equal(t, 0, c.Len())
|
assert.Equal(t, 0, c.Len())
|
||||||
})
|
})
|
||||||
t.Run("test with close wait", func(t *testing.T) {
|
t.Run("test gc tryClose true, close before get", func(t *testing.T) {
|
||||||
closeCh := make(chan struct{})
|
closeCh := make(chan struct{})
|
||||||
getCh := make(chan struct{})
|
getCh := make(chan struct{})
|
||||||
|
|
||||||
@ -173,15 +178,60 @@ func TestOCache_GC(t *testing.T) {
|
|||||||
<-getCh
|
<-getCh
|
||||||
require.Equal(t, []string{"close", "get"}, events)
|
require.Equal(t, []string{"close", "get"}, events)
|
||||||
})
|
})
|
||||||
|
t.Run("test gc tryClose false, many get", func(t *testing.T) {
|
||||||
|
timesCalled := &atomic.Int32{}
|
||||||
|
obj := NewTestObject("id", false, nil)
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
timesCalled.Add(1)
|
||||||
|
return obj, nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
|
||||||
|
val, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
assert.Equal(t, 1, c.Len())
|
||||||
|
// making ttl pass
|
||||||
|
time.Sleep(time.Millisecond * 40)
|
||||||
|
// first gc will be run after 20 secs, so calling it manually
|
||||||
|
begin := make(chan struct{})
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
once := sync.Once{}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
<-begin
|
||||||
|
c.GC()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(i int) {
|
||||||
|
once.Do(func() {
|
||||||
|
close(begin)
|
||||||
|
})
|
||||||
|
if i > 0 {
|
||||||
|
time.Sleep(time.Duration(i) * time.Millisecond)
|
||||||
|
}
|
||||||
|
_, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Wait()
|
||||||
|
require.Equal(t, timesCalled.Load(), int32(1))
|
||||||
|
require.True(t, obj.tryCloseCalled)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_OCache_Remove(t *testing.T) {
|
func Test_OCache_Remove(t *testing.T) {
|
||||||
closeCh := make(chan struct{})
|
closeCh := make(chan struct{})
|
||||||
getCh := make(chan struct{})
|
getCh := make(chan struct{})
|
||||||
|
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return NewTestObject(id, false, closeCh), nil
|
return NewTestObject(id, false, closeCh), nil
|
||||||
}, WithTTL(time.Millisecond*10))
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
|
||||||
val, err := c.Get(context.TODO(), "id")
|
val, err := c.Get(context.TODO(), "id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user