Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type cache struct {
type cacheKey string

type cacheVal struct {
res *Result
res *result
err error
}

Expand All @@ -28,7 +28,7 @@ func newCache() *cache {
// GetOrSet atomic get exist values from cache or call f for set new value and return it.
// it has guarantee about only one f will execute same time for the key.
// but many f may execute simultaneously for different keys
func (c *cache) GetOrSet(key cacheKey, f FixtureFunction) (*Result, error) {
func (c *cache) GetOrSet(key cacheKey, f fixtureFunction) (*result, error) {
res, ok := c.get(key)
if ok {
return res.res, res.err
Expand Down Expand Up @@ -57,7 +57,7 @@ func (c *cache) get(key cacheKey) (cacheVal, bool) {
return val, ok
}

func (c *cache) setOnce(key cacheKey, f FixtureFunction) {
func (c *cache) setOnce(key cacheKey, f fixtureFunction) {
c.m.Lock()
setOnce := c.setLocks[key]
if setOnce == nil {
Expand All @@ -68,7 +68,7 @@ func (c *cache) setOnce(key cacheKey, f FixtureFunction) {

setOnce.Do(func() {
var err = errors.New("unexpected exit from function")
var res *Result
var res *result

// save result must be deferred because f() may stop goroutine without result
// for example by panic or GoExit
Expand Down
64 changes: 32 additions & 32 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ func TestCache_DeleteKeys(t *testing.T) {
k2 := cacheKey("k2")
k3 := cacheKey("k3")
val1 := "test1"
valFunc := func() (*Result, error) {
return NewResult(val1), nil
valFunc := func() (*result, error) {
return newResult(val1), nil
}

c.setOnce(k1, valFunc)
Expand All @@ -37,8 +37,8 @@ func TestCache_DeleteKeys(t *testing.T) {
requireEquals(t, val1, res.res.Value.(string))

val2 := "test2"
c.setOnce(k1, func() (res *Result, err error) {
return NewResult(val2), nil
c.setOnce(k1, func() (res *result, err error) {
return newResult(val2), nil
})
res, ok = c.get(k1)
requireTrue(t, ok)
Expand All @@ -47,8 +47,8 @@ func TestCache_DeleteKeys(t *testing.T) {

t.Run("mutex", func(t *testing.T) {
c := newCache()
c.setOnce("asd", func() (res *Result, err error) {
return NewResult(nil), nil
c.setOnce("asd", func() (res *result, err error) {
return newResult(nil), nil
})

c.m.RLock()
Expand Down Expand Up @@ -77,17 +77,17 @@ func TestCache_Get(t *testing.T) {
_, ok := c.get("qwe")
requireFalse(t, ok)

c.store["asd"] = cacheVal{res: NewResult("val")}
c.store["asd"] = cacheVal{res: newResult("val")}

res, ok := c.get("asd")
requireTrue(t, ok)
requireEquals(t, cacheVal{res: NewResult("val")}, res)
requireEquals(t, cacheVal{res: newResult("val")}, res)
})

t.Run("read_mutex", func(t *testing.T) {
c := newCache()
c.setOnce("asd", func() (res *Result, err error) {
return NewResult(nil), nil
c.setOnce("asd", func() (res *result, err error) {
return newResult(nil), nil
})
c.m.RLock()
_, ok := c.get("asd")
Expand All @@ -97,8 +97,8 @@ func TestCache_Get(t *testing.T) {

t.Run("write_mutex", func(t *testing.T) {
c := newCache()
c.setOnce("asd", func() (res *Result, err error) {
return NewResult(nil), nil
c.setOnce("asd", func() (res *result, err error) {
return newResult(nil), nil
})
c.m.Lock()
var ok bool
Expand All @@ -125,17 +125,17 @@ func TestCache_SetOnce(t *testing.T) {
c := newCache()
cnt := 0
key1 := cacheKey("1")
c.setOnce(key1, func() (res *Result, err error) {
c.setOnce(key1, func() (res *result, err error) {
cnt++
return NewResult(1), nil
return newResult(1), nil
})
requireEquals(t, 1, cnt)
requireEquals(t, 1, c.store[key1].res.Value)
noError(t, c.store[key1].err)

c.setOnce(key1, func() (res *Result, err error) {
c.setOnce(key1, func() (res *result, err error) {
cnt++
return NewResult(2), nil
return newResult(2), nil
})
requireEquals(t, 1, cnt)
requireEquals(t, 1, c.store[key1].res.Value)
Expand All @@ -147,13 +147,13 @@ func TestCache_SetOnce(t *testing.T) {
key1 := cacheKey("1")
key2 := cacheKey("2")
cnt := 0
c.setOnce(key1, func() (res *Result, err error) {
c.setOnce(key1, func() (res *result, err error) {
cnt++
return NewResult(1), nil
return newResult(1), nil
})
c.setOnce(key2, func() (res *Result, err error) {
c.setOnce(key2, func() (res *result, err error) {
cnt++
return NewResult(2), nil
return newResult(2), nil
})
requireEquals(t, 2, cnt)
requireEquals(t, 1, c.store[key1].res.Value)
Expand All @@ -170,9 +170,9 @@ func TestCache_SetOnce(t *testing.T) {
wg.Add(1)
go func() {
defer wg.Done()
c.setOnce(key, func() (res *Result, err error) {
c.setOnce(key, func() (res *result, err error) {
runtime.Goexit()
return NewResult(3), nil
return newResult(3), nil
})
}()
wg.Wait()
Expand All @@ -193,11 +193,11 @@ func TestCache_SetOnce(t *testing.T) {

// first
go func() {
c.setOnce(key, func() (res *Result, err error) {
c.setOnce(key, func() (res *result, err error) {
close(firstMuStarted)
<-firstMuNeedFinish

return NewResult(1), nil
return newResult(1), nil
})

close(firstMuFinished)
Expand All @@ -210,9 +210,9 @@ func TestCache_SetOnce(t *testing.T) {

var doneSecond int64
go func() {
c.setOnce(key, func() (res *Result, err error) {
c.setOnce(key, func() (res *result, err error) {
// func will not call never
return NewResult(2), nil
return newResult(2), nil
})

// must executed only after fist func finished
Expand Down Expand Up @@ -254,12 +254,12 @@ func TestCache_SetOnce(t *testing.T) {

// first
go func() {
c.setOnce(key1, func() (res *Result, err error) {
c.setOnce(key1, func() (res *result, err error) {
close(firstMuStarted)

<-firstMuNeedFinish

return NewResult(1), nil
return newResult(1), nil
})

close(firstMuFinished)
Expand All @@ -269,9 +269,9 @@ func TestCache_SetOnce(t *testing.T) {
<-firstMuStarted

// call second func in same goroutine
c.setOnce(key2, func() (res *Result, err error) {
c.setOnce(key2, func() (res *result, err error) {
// func will not call never
return NewResult(2), nil
return newResult(2), nil
})

// allow finish first func after second already finished
Expand Down Expand Up @@ -301,8 +301,8 @@ func TestCache_GetOrSetRaceCondition(_ *testing.T) {

for j := 0; j < iterations; j++ {
key := cacheKey(strconv.Itoa(rand.Intn(rndMaxBound)))
v, ok := c.GetOrSet(key, func() (res *Result, err error) {
return NewResult(1), nil
v, ok := c.GetOrSet(key, func() (res *result, err error) {
return newResult(1), nil
})
_ = v
_ = ok
Expand Down
14 changes: 5 additions & 9 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ func (e *EnvT) T() T {
return e.t
}

// CacheResult call f callback once and cache result (ok and error),
// then return same result for all calls of the callback without additional calls
// f with same options calls max once per test (or defined test scope)
// See to generic wrapper: CacheResult
func (e *EnvT) CacheResult(f FixtureFunction, options ...CacheOptions) interface{} {
func (e *EnvT) cacheResult(f fixtureFunction, options ...CacheOptions) interface{} {
var cacheOptions CacheOptions
switch len(options) {
case 0:
Expand All @@ -85,7 +81,7 @@ func (e *EnvT) CacheResult(f FixtureFunction, options ...CacheOptions) interface

// cache must be call from first-level public function
// UserFunction->EnvFunction->cache for good determine caller name
func (e *EnvT) cache(f FixtureFunction, options CacheOptions) interface{} {
func (e *EnvT) cache(f fixtureFunction, options CacheOptions) interface{} {
key, err := makeCacheKey(e.t.Name(), options, false)
if err != nil {
e.t.Fatalf("failed to create cache key: %v", err)
Expand Down Expand Up @@ -210,8 +206,8 @@ func makeCacheKeyFromFrame(params interface{}, scope CacheScope, f runtime.Frame

}

func (e *EnvT) fixtureCallWrapper(key cacheKey, f FixtureFunction, options CacheOptions) FixtureFunction {
return func() (res *Result, err error) {
func (e *EnvT) fixtureCallWrapper(key cacheKey, f fixtureFunction, options CacheOptions) fixtureFunction {
return func() (res *result, err error) {
scopeName := makeScopeName(e.t.Name(), options.Scope)

e.m.Lock()
Expand All @@ -233,7 +229,7 @@ func (e *EnvT) fixtureCallWrapper(key cacheKey, f FixtureFunction, options Cache

// force exactly least one of res, err != nil
if res == nil && err == nil {
res = NewResult(nil)
res = newResult(nil)
}
if res != nil && res.Cleanup != nil {
si.t.Cleanup(res.Cleanup)
Expand Down
8 changes: 4 additions & 4 deletions env_generic_sugar.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ func CacheResult[TRes any](env Env, f GenericFixtureFunction[TRes], options ...C
}

addSkipLevelCache(&cacheOptions)
var oldStyleFunc FixtureFunction = func() (*Result, error) {
var oldStyleFunc fixtureFunction = func() (*result, error) {
res, err := f()

var oldStyleRes *Result
var oldStyleRes *result
if res != nil {
oldStyleRes = &Result{
oldStyleRes = &result{
Value: res.Value,
ResultAdditional: res.ResultAdditional,
}
}
return oldStyleRes, err
}
res := env.CacheResult(oldStyleFunc, cacheOptions)
res := env.cacheResult(oldStyleFunc, cacheOptions)
if res == nil {
var zero TRes
return zero
Expand Down
6 changes: 3 additions & 3 deletions env_generic_sugar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestCacheResultGeneric(t *testing.T) {

cleanupCalledBack := 0

env := envMock{onCacheResult: func(opt CacheOptions, f FixtureFunction) interface{} {
env := envMock{onCacheResult: func(opt CacheOptions, f fixtureFunction) interface{} {
opt.additionlSkipExternalCalls--
requireEquals(t, inOpt, opt)
res, _ := f()
Expand Down Expand Up @@ -118,14 +118,14 @@ func TestCacheResultPanic(t *testing.T) {
}

type envMock struct {
onCacheResult func(opts CacheOptions, f FixtureFunction) interface{}
onCacheResult func(opts CacheOptions, f fixtureFunction) interface{}
}

func (e envMock) T() T {
panic("not implemented")
}

func (e envMock) CacheResult(f FixtureFunction, options ...CacheOptions) interface{} {
func (e envMock) cacheResult(f fixtureFunction, options ...CacheOptions) interface{} {
var opts CacheOptions
switch len(options) {
case 0:
Expand Down
Loading
Loading