Skip to content

Commit

Permalink
add more coverage tests (#2)
Browse files Browse the repository at this point in the history
* test add for coverage to pool, memcached, hr & ref "disable meth" for logger

* fix use slices instead golang.org/x/exp/slices
   - zero value on delete elem (nil panic)

* test add coverage test for node provider

* fix gets deadnodes in node provider

* test add for memcached

* fix node provider test

* Apply Code Coverage Badge

---------

Co-authored-by: Yosh11 <[email protected]>
  • Loading branch information
Yosh11 and Yosh11 authored Feb 1, 2024
1 parent ad8cfc8 commit 344df93
Show file tree
Hide file tree
Showing 15 changed files with 938 additions and 47 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ jobs:

- name: Test
run: |
go test -v -cover ./... -coverprofile coverage.out -coverpkg ./...
go test -v -cover ./... -coverprofile coverage.out
go tool cover -func coverage.out -o coverage.out
- name: Go Coverage Badge
uses: tj-actions/coverage-badge-go@v1
if: ${{ runner.os == 'linux' }}
with:
green: 70
green: 80
filename: coverage.out

- uses: stefanzweifel/git-auto-commit-action@v5
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
<img src="https://github.com/aliexpressru/gomemcached/raw/main/assets/logo.png" width="300"/>

[![License](https://img.shields.io/github/license/gogf/gf.svg?style=flat)](https://github.com/aliexpressru/gomemcached)

[![Gomemcached](https://goreportcard.com/badge/github.com/aliexpressru/gomemcached)](https://goreportcard.com/report/github.com/aliexpressru/gomemcached)
[![Godoc](https://godoc.org/github.com/aliexpressru/gomemcached?status.svg)](https://pkg.go.dev/github.com/aliexpressru/gomemcached)
![Coverage](https://img.shields.io/badge/Coverage-69.8%25-yellow)

[![Tag](https://img.shields.io/github/v/tag/aliexpressru/gomemcached?color=%23ff8936&logo=fitbit&style=flat-square)](https://github.com/aliexpressru/gomemcached/tags)
![Coverage](https://img.shields.io/badge/Coverage-90.9%25-brightgreen)
</div>

___
Expand Down
28 changes: 28 additions & 0 deletions consistenthash/hashring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,34 @@ func TestHashRing_RemoveInterface(t *testing.T) {
assert.Equal(t, 2, node.(*mockNode).id)
}

func Test_innerRepr(t *testing.T) {
type args struct {
node any
}
tests := []struct {
name string
args args
want string
}{
{
name: "localhost:11211",
args: args{node: "localhost:11211"},
want: fmt.Sprintf("%d:%v", prime, "localhost:11211"),
},
{
name: "127.0.0.1:11211",
args: args{node: "127.0.0.1:11211"},
want: fmt.Sprintf("%d:%v", prime, "127.0.0.1:11211"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := innerRepr(tt.args.node)
assert.Equal(t, tt.want, out, "innerRepr: returned wrong format")
})
}
}

func getKeysBeforeAndAfterFailure(t *testing.T, prefix string, index int) (map[int]string, map[int]string) {
ch := NewHashRing()
for i := 0; i < keySize; i++ {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.16.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
Expand All @@ -30,6 +31,12 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
Expand All @@ -49,5 +56,6 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
30 changes: 18 additions & 12 deletions logger/zap.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logger

import (
"os"
"sync/atomic"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand All @@ -10,7 +11,7 @@ import (
var (
// global logger instance.
global *zap.SugaredLogger
disableLogger bool
disableLogger atomic.Bool
defaultLevel = zap.NewAtomicLevelAt(zap.DebugLevel)
generationArgs = []any{"@gen", "1"}
)
Expand All @@ -31,7 +32,12 @@ func GetLogger() *zap.SugaredLogger {

// DisableLogger turn off all logs, globally.
func DisableLogger() {
disableLogger = true
disableLogger.Store(true)
}

// LoggerIsDisable checks the status of the logger (true - disabled, false - enabled)
func LoggerIsDisable() bool {
return disableLogger.Load()
}

func newSugaredLogger(level zapcore.LevelEnabler, options ...zap.Option) *zap.SugaredLogger {
Expand Down Expand Up @@ -75,70 +81,70 @@ func capitalLevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {

// Debug ...
func Debug(args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Debug(args...)
}
}

// Debugf ...
func Debugf(format string, args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Debugf(format, args...)
}
}

// Info ...
func Info(args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Info(args...)
}
}

// Infof ...
func Infof(format string, args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Infof(format, args...)
}
}

// Warn ...
func Warn(args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Warn(args...)
}
}

// Warnf ...
func Warnf(format string, args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Warnf(format, args...)
}
}

// Error ...
func Error(args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Error(args...)
}
}

// Errorf ...
func Errorf(format string, args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Errorf(format, args...)
}
}

// Fatal ...
func Fatal(args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Fatal(args...)
}
}

// Fatalf ...
func Fatalf(format string, args ...any) {
if log := GetLogger(); !disableLogger {
if log := GetLogger(); !LoggerIsDisable() {
log.Fatalf(format, args...)
}
}
12 changes: 12 additions & 0 deletions memcached/constants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ func TestOpCode_changeOnQuiet(t *testing.T) {
args: args{def: GETQ},
want: GETQ,
},
{
name: GETQ.String(),
o: GETQ,
args: args{def: GETQ},
want: GETQ,
},
{
name: "unknown opcode",
o: OpCode(0x1b),
args: args{def: GETQ},
want: GETQ,
},
{
name: SET.String(),
o: SET,
Expand Down
26 changes: 22 additions & 4 deletions memcached/memcached.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type (
// It is safe for unlocked use by multiple concurrent goroutines.
Client struct {
ctx context.Context
nw *network
cfg *config

// opaque - a unique identifier for the request, used to associate the request with its corresponding response.
Expand Down Expand Up @@ -114,6 +115,12 @@ type (
authData []byte
}

network struct {
dial func(network string, address string) (net.Conn, error)
dialTimeout func(network string, address string, timeout time.Duration) (net.Conn, error)
lookupHost func(host string) (addrs []string, err error)
}

config struct {
// HeadlessServiceAddress Headless service to lookup all the memcached ip addresses.
HeadlessServiceAddress string `envconfig:"MEMCACHED_HEADLESS_SERVICE_ADDRESS"`
Expand Down Expand Up @@ -151,6 +158,13 @@ func InitFromEnv(opts ...Option) (*Client, error) {
opt(op)
}

if op.Client.nw == nil {
op.Client.nw = &network{
dial: net.Dial,
dialTimeout: net.DialTimeout,
lookupHost: net.LookupHost,
}
}
if op.Client.hr == nil {
op.Client.hr = consistenthash.NewHashRing()
}
Expand Down Expand Up @@ -181,6 +195,11 @@ func newForTests(servers ...string) (*Client, error) {
opaque: new(uint32),
hr: hr,
disableMemcachedDiagnostic: true,
nw: &network{
dial: net.Dial,
dialTimeout: net.DialTimeout,
lookupHost: net.LookupHost,
},
}

return cm, nil
Expand All @@ -190,7 +209,7 @@ func newFromConfig(op *options) (*Client, error) {
if op.cfg != nil && !(op.cfg.HeadlessServiceAddress != "" || len(op.cfg.Servers) != 0) {
return nil, fmt.Errorf("%w, you must fill in either MEMCACHED_HEADLESS_SERVICE_ADDRESS or MEMCACHED_SERVERS", ErrNotConfigured)
}
nodes, err := getNodes(op.cfg)
nodes, err := getNodes(op.nw.lookupHost, op.cfg)
if err != nil {
return nil, fmt.Errorf("%w, %s", ErrInvalidAddr, err.Error())
}
Expand All @@ -208,7 +227,6 @@ func newFromConfig(op *options) (*Client, error) {
if !mc.disableNodeProvider {
mc.initNodesProvider()
}

return mc, nil
}

Expand Down Expand Up @@ -379,7 +397,7 @@ func (cte *ConnectTimeoutError) Error() string {

func (c *Client) dial(addr net.Addr) (net.Conn, error) {
if c.netTimeout() > 0 {
nc, err := net.DialTimeout(addr.Network(), addr.String(), c.netTimeout())
nc, err := c.nw.dialTimeout(addr.Network(), addr.String(), c.netTimeout())
if err != nil {
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
Expand All @@ -389,7 +407,7 @@ func (c *Client) dial(addr net.Addr) (net.Conn, error) {
}
return nc, nil
}
return net.Dial(addr.Network(), addr.String())
return c.nw.dial(addr.Network(), addr.String())
}

func (c *Client) getConnForNode(node any) (*conn, error) {
Expand Down
Loading

0 comments on commit 344df93

Please sign in to comment.