chore: add more tests (#3338)

master
Kevin Wan 1 year ago committed by GitHub
parent efa6940001
commit f6bdb6e1de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +0,0 @@
//go:build windows
package proc
func dumpGoroutines() {
}

@ -18,7 +18,11 @@ const (
debugLevel = 2 debugLevel = 2
) )
func dumpGoroutines() { type creator interface {
Create(name string) (file *os.File, err error)
}
func dumpGoroutines(ctor creator) {
command := path.Base(os.Args[0]) command := path.Base(os.Args[0])
pid := syscall.Getpid() pid := syscall.Getpid()
dumpFile := path.Join(os.TempDir(), fmt.Sprintf("%s-%d-goroutines-%s.dump", dumpFile := path.Join(os.TempDir(), fmt.Sprintf("%s-%d-goroutines-%s.dump",
@ -26,10 +30,16 @@ func dumpGoroutines() {
logx.Infof("Got dump goroutine signal, printing goroutine profile to %s", dumpFile) logx.Infof("Got dump goroutine signal, printing goroutine profile to %s", dumpFile)
if f, err := os.Create(dumpFile); err != nil { if f, err := ctor.Create(dumpFile); err != nil {
logx.Errorf("Failed to dump goroutine profile, error: %v", err) logx.Errorf("Failed to dump goroutine profile, error: %v", err)
} else { } else {
defer f.Close() defer f.Close()
pprof.Lookup(goroutineProfile).WriteTo(f, debugLevel) pprof.Lookup(goroutineProfile).WriteTo(f, debugLevel)
} }
} }
type fileCreator struct{}
func (fc fileCreator) Create(name string) (file *os.File, err error) {
return os.Create(name)
}

@ -1,6 +1,10 @@
//go:build linux || darwin
package proc package proc
import ( import (
"errors"
"os"
"strings" "strings"
"testing" "testing"
@ -9,7 +13,29 @@ import (
) )
func TestDumpGoroutines(t *testing.T) { func TestDumpGoroutines(t *testing.T) {
t.Run("real file", func(t *testing.T) {
buf := logtest.NewCollector(t) buf := logtest.NewCollector(t)
dumpGoroutines() dumpGoroutines(fileCreator{})
assert.True(t, strings.Contains(buf.String(), ".dump")) assert.True(t, strings.Contains(buf.String(), ".dump"))
})
t.Run("fake file", func(t *testing.T) {
const msg = "any message"
buf := logtest.NewCollector(t)
err := errors.New(msg)
dumpGoroutines(fakeCreator{
file: &os.File{},
err: err,
})
assert.True(t, strings.Contains(buf.String(), msg))
})
}
type fakeCreator struct {
file *os.File
err error
}
func (fc fakeCreator) Create(name string) (file *os.File, err error) {
return fc.file, fc.err
} }

@ -26,7 +26,7 @@ func init() {
v := <-signals v := <-signals
switch v { switch v {
case syscall.SIGUSR1: case syscall.SIGUSR1:
dumpGoroutines() dumpGoroutines(fileCreator{})
case syscall.SIGUSR2: case syscall.SIGUSR2:
if profiler == nil { if profiler == nil {
profiler = StartProfile() profiler = StartProfile()

@ -1,3 +1,5 @@
//go:build linux || darwin
package proc package proc
import ( import (

@ -171,11 +171,11 @@ func add(nd *node, route string, item any) error {
token := route[:i] token := route[:i]
children := nd.getChildren(token) children := nd.getChildren(token)
if child, ok := children[token]; ok { if child, ok := children[token]; ok {
if child != nil { if child == nil {
return add(child, route[i+1:], item) return errInvalidState
} }
return errInvalidState return add(child, route[i+1:], item)
} }
child := newNode(nil) child := newNode(nil)

@ -11,7 +11,7 @@ import (
type mockedRoute struct { type mockedRoute struct {
route string route string
value int value any
} }
func TestSearch(t *testing.T) { func TestSearch(t *testing.T) {
@ -187,6 +187,12 @@ func TestSearchInvalidItem(t *testing.T) {
assert.Equal(t, errEmptyItem, err) assert.Equal(t, errEmptyItem, err)
} }
func TestSearchInvalidState(t *testing.T) {
nd := newNode("0")
nd.children[0]["1"] = nil
assert.Error(t, add(nd, "1/2", "2"))
}
func BenchmarkSearchTree(b *testing.B) { func BenchmarkSearchTree(b *testing.B) {
const ( const (
avgLen = 1000 avgLen = 1000

@ -97,6 +97,9 @@ func (cc CachedConn) Exec(exec ExecFn, keys ...string) (sql.Result, error) {
} }
// ExecCtx runs given exec on given keys, and returns execution result. // ExecCtx runs given exec on given keys, and returns execution result.
// If DB operation succeeds, it will delete cache with given keys,
// if DB operation fails, it will return nil result and non-nil error,
// if DB operation succeeds but cache deletion fails, it will return result and non-nil error.
func (cc CachedConn) ExecCtx(ctx context.Context, exec ExecCtxFn, keys ...string) ( func (cc CachedConn) ExecCtx(ctx context.Context, exec ExecCtxFn, keys ...string) (
sql.Result, error) { sql.Result, error) {
res, err := exec(ctx, cc.db) res, err := exec(ctx, cc.db)
@ -104,11 +107,7 @@ func (cc CachedConn) ExecCtx(ctx context.Context, exec ExecCtxFn, keys ...string
return nil, err return nil, err
} }
if err := cc.DelCacheCtx(ctx, keys...); err != nil { return res, cc.DelCacheCtx(ctx, keys...)
return nil, err
}
return res, nil
} }
// ExecNoCache runs exec with given sql statement, without affecting cache. // ExecNoCache runs exec with given sql statement, without affecting cache.

@ -471,6 +471,7 @@ func TestCachedConnExec(t *testing.T) {
} }
func TestCachedConnExecDropCache(t *testing.T) { func TestCachedConnExecDropCache(t *testing.T) {
t.Run("drop cache", func(t *testing.T) {
r, err := miniredis.Run() r, err := miniredis.Run()
assert.Nil(t, err) assert.Nil(t, err)
defer fx.DoWithTimeout(func() error { defer fx.DoWithTimeout(func() error {
@ -496,6 +497,7 @@ func TestCachedConnExecDropCache(t *testing.T) {
return nil, errors.New("foo") return nil, errors.New("foo")
}, key) }, key)
assert.NotNil(t, err) assert.NotNil(t, err)
})
} }
func TestCachedConn_SetCacheWithExpire(t *testing.T) { func TestCachedConn_SetCacheWithExpire(t *testing.T) {

@ -42,7 +42,8 @@ func (manager *ResourceManager) Close() error {
} }
// GetResource returns the resource associated with given key. // GetResource returns the resource associated with given key.
func (manager *ResourceManager) GetResource(key string, create func() (io.Closer, error)) (io.Closer, error) { func (manager *ResourceManager) GetResource(key string, create func() (io.Closer, error)) (
io.Closer, error) {
val, err := manager.singleFlight.Do(key, func() (any, error) { val, err := manager.singleFlight.Do(key, func() (any, error) {
manager.lock.RLock() manager.lock.RLock()
resource, ok := manager.resources[key] resource, ok := manager.resources[key]

@ -53,6 +53,19 @@ func TestComboHealthManager(t *testing.T) {
assert.True(t, chm.IsReady()) assert.True(t, chm.IsReady())
}) })
t.Run("is ready verbose", func(t *testing.T) {
chm := newComboHealthManager()
hm := NewHealthManager(probeName)
assert.True(t, chm.IsReady())
chm.addProbe(hm)
assert.False(t, chm.IsReady())
hm.MarkReady()
assert.True(t, chm.IsReady())
assert.Contains(t, chm.verboseInfo(), probeName)
assert.Contains(t, chm.verboseInfo(), "is ready")
})
t.Run("concurrent add probes", func(t *testing.T) { t.Run("concurrent add probes", func(t *testing.T) {
chm := newComboHealthManager() chm := newComboHealthManager()

Loading…
Cancel
Save