Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

Commit

Permalink
feature/tests: add more tests and refactor Makefile for race tests
Browse files Browse the repository at this point in the history
* Makefile refactored for racetests
* Tests coverage up
  • Loading branch information
Maksim Konovalov committed Aug 30, 2024
1 parent cf02580 commit 910ca35
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 24 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ REFACTOR:
* Ignore .tmp files
* Refactored provider creation test caused by golang-ci lint (#33)
* Router implements directly TopologyController, no proxy object is used now

* Makefile refactored for racetests
* Tests coverage up 22% -> 28%


## 0.0.11
Expand Down
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
TEST_TIMEOUT?=20s
EXTENDED_TEST_TIMEOUT=1m
GO_CMD?=go
LOCAL_BIN:=$(CURDIR)/bin
# golang-ci tag
GOLANGCI_TAG:=latest
Expand All @@ -9,16 +11,16 @@ GOLANGCI_BIN:=$(GOPATH)/bin/golangci-lint
install-lint:
ifeq ($(wildcard $(GOLANGCI_BIN)),)
$(info #Downloading swaggo latest)
go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_TAG)
$(GO_CMD) install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_TAG)
endif

test:
go test ./... -parallel=10 -timeout=$(TEST_TIMEOUT) -coverprofile=coverage.out.tmp
$(GO_CMD) test ./... -parallel=10 -timeout=$(TEST_TIMEOUT) -coverprofile=coverage.out.tmp
@cat coverage.out.tmp | grep -v "mock" > coverage.out
@rm coverage.out.tmp

cover: test
go tool cover -html=coverage.out
$(GO_CMD) tool cover -html=coverage.out

test/integration:
@$(MAKE) -C ./tests/integration test
Expand All @@ -31,3 +33,7 @@ generate/mocks:
lint: install-lint
$(GOLANGCI_BIN) run --config=.golangci.yaml ./...

testrace: BUILD_TAGS+=testonly
testrace:
@CGO_ENABLED=1 \
$(GO_CMD) test -tags='$(BUILD_TAGS)' -race -timeout=$(EXTENDED_TEST_TIMEOUT) -parallel=20
35 changes: 35 additions & 0 deletions api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package vshard_router // nolint: revive

import (
"context"
"testing"

"github.com/stretchr/testify/require"
)

var emptyRouter = &Router{
cfg: Config{
TotalBucketCount: uint64(10),
Logger: &EmptyLogger{},
},
}

func TestVshardMode_String_NotEmpty(t *testing.T) {
t.Parallel()
require.NotEmpty(t, ReadMode.String())
require.NotEmpty(t, WriteMode.String())
}

func TestRouter_RouterRouteAll(t *testing.T) {
t.Parallel()
m := emptyRouter.RouterRouteAll()
require.Empty(t, m)
}

func TestRouter_RouterCallImpl(t *testing.T) {
t.Parallel()
ctx := context.TODO()

_, _, err := emptyRouter.RouterCallImpl(ctx, 100, CallOpts{}, "test", []byte("test"))
require.Errorf(t, err, "bucket id is out of range")
}
7 changes: 7 additions & 0 deletions discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (r *Router) BucketDiscovery(ctx context.Context, bucketID uint64) (*Replica

// BucketResolve resolve bucket id to replicaset
func (r *Router) BucketResolve(ctx context.Context, bucketID uint64) (*Replicaset, error) {
if bucketID > r.cfg.TotalBucketCount {
return nil, fmt.Errorf("bucket id is out of range: %d (total %d)", bucketID, r.cfg.TotalBucketCount)
}

rs := r.routeMap[bucketID]
if rs != nil {
return rs, nil
Expand Down Expand Up @@ -167,6 +171,9 @@ func (r *Router) DiscoveryAllBuckets(ctx context.Context) error {
errGr, ctx := errgroup.WithContext(ctx)

idToReplicasetRef := r.getIDToReplicaset()
if idToReplicasetRef == nil {
return fmt.Errorf("smth went wrong; replicasets map is empty")
}

for _, rs := range idToReplicasetRef {
rs := rs
Expand Down
30 changes: 30 additions & 0 deletions discovery_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vshard_router //nolint:revive

import (
"context"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -34,3 +35,32 @@ func TestSearchLock_WaitOnSearch(t *testing.T) {

require.True(t, time.Since(lockStart) < 12*time.Millisecond && time.Since(lockStart) > 9*time.Millisecond)
}

func TestRouter_DiscoveryAllBuckets(t *testing.T) {
ctx := context.TODO()

r := Router{
cfg: Config{
TotalBucketCount: uint64(256000),
Logger: &EmptyLogger{},
},
}

err := r.DiscoveryAllBuckets(ctx)
require.Error(t, err) // replicaset map is empty
}

func TestRouter_BucketResolve_InvalidBucketID(t *testing.T) {
ctx := context.TODO()

r := Router{
cfg: Config{
TotalBucketCount: uint64(10),
Logger: &EmptyLogger{},
},
routeMap: make([]*Replicaset, 11),
}

_, err := r.BucketResolve(ctx, 20)
require.Error(t, err)
}
2 changes: 2 additions & 0 deletions providers/static/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestNewProvider(t *testing.T) {

for _, tc := range tCases {
t.Run("provider", func(t *testing.T) {
t.Parallel()
if len(tc.Source) == 0 {

require.Panics(t, func() {
Expand Down Expand Up @@ -83,6 +84,7 @@ func TestProvider_Validate(t *testing.T) {

for _, tc := range tCases {
t.Run(fmt.Sprintf("is err: %v", tc.IsErr), func(t *testing.T) {
t.Parallel()
provider := NewProvider(tc.Source)
if tc.IsErr {
require.Error(t, provider.Validate())
Expand Down
38 changes: 33 additions & 5 deletions topology_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"testing"

mockpool "github.com/KaymeKaydex/go-vshard-router/mocks/pool"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -56,13 +57,40 @@ func TestController_RemoveInstance(t *testing.T) {
func TestController_RemoveReplicaset(t *testing.T) {
ctx := context.Background()

t.Run("no such replicaset", func(t *testing.T) {
router := Router{
idToReplicaset: map[uuid.UUID]*Replicaset{},
}
uuidToRemove := uuid.New()
mPool := mockpool.NewPool(t)
mPool.On("CloseGraceful").Return(nil)

errs := router.Topology().RemoveReplicaset(ctx, uuid.New())
router := Router{
idToReplicaset: map[uuid.UUID]*Replicaset{
uuidToRemove: {conn: mPool},
},
}

t.Run("no such replicaset", func(t *testing.T) {
t.Parallel()
errs := router.Topology().RemoveReplicaset(ctx, uuid.New())
require.True(t, errors.Is(errs[0], ErrReplicasetNotExists))
})
t.Run("successfully remove", func(t *testing.T) {
t.Parallel()
errs := router.Topology().RemoveReplicaset(ctx, uuidToRemove)
require.Empty(t, errs)
})
}

func TestRouter_AddReplicaset_AlreadyExists(t *testing.T) {
ctx := context.TODO()

alreadyExistingRsUUID := uuid.New()

router := Router{
idToReplicaset: map[uuid.UUID]*Replicaset{
alreadyExistingRsUUID: {},
},
}

// Test that such replicaset already exists
err := router.AddReplicaset(ctx, ReplicasetInfo{UUID: alreadyExistingRsUUID}, []InstanceInfo{})
require.Equalf(t, ErrReplicasetExists, err, "such replicaset must already exists")
}
3 changes: 2 additions & 1 deletion vshard.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
var (
ErrInvalidConfig = fmt.Errorf("config invalid")
ErrInvalidInstanceInfo = fmt.Errorf("invalid instance info")
ErrTopologyProvider = fmt.Errorf("got error from topology provider")
)

type Router struct {
Expand Down Expand Up @@ -120,7 +121,7 @@ func NewRouter(ctx context.Context, cfg Config) (*Router, error) {
if err != nil {
router.log().Error(ctx, fmt.Sprintf("cant create new topology provider with err: %s", err))

return nil, err
return nil, fmt.Errorf("%w; cant init topology with err: %w", ErrTopologyProvider, err)
}

err = router.DiscoveryAllBuckets(ctx)
Expand Down
49 changes: 35 additions & 14 deletions vshard_shadow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,49 @@ package vshard_router_test

import (
"context"
"fmt"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/require"

vshard_router "github.com/KaymeKaydex/go-vshard-router"
vshardrouter "github.com/KaymeKaydex/go-vshard-router"
"github.com/KaymeKaydex/go-vshard-router/providers/static"
)

// Check that ErrorTopologyProvider implements TopologyProvider interface
var _ vshardrouter.TopologyProvider = (*ErrorTopologyProvider)(nil)

type ErrorTopologyProvider struct{}

func (e *ErrorTopologyProvider) Init(_ vshardrouter.TopologyController) error {
return fmt.Errorf("test error")
}
func (e *ErrorTopologyProvider) Close() {}

func TestNewRouter_ProviderError(t *testing.T) {
ctx := context.TODO()
_, err := vshardrouter.NewRouter(ctx, vshardrouter.Config{
TotalBucketCount: 256000,
TopologyProvider: &ErrorTopologyProvider{},
})

require.ErrorIs(t, err, vshardrouter.ErrTopologyProvider)
}

func TestNewRouter_EmptyReplicasets(t *testing.T) {
ctx := context.TODO()

router, err := vshard_router.NewRouter(ctx, vshard_router.Config{})
router, err := vshardrouter.NewRouter(ctx, vshardrouter.Config{})
require.Error(t, err)
require.Nil(t, router)
}

func TestNewRouter_InvalidReplicasetUUID(t *testing.T) {
ctx := context.TODO()

router, err := vshard_router.NewRouter(ctx, vshard_router.Config{
TopologyProvider: static.NewProvider(map[vshard_router.ReplicasetInfo][]vshard_router.InstanceInfo{
router, err := vshardrouter.NewRouter(ctx, vshardrouter.Config{
TopologyProvider: static.NewProvider(map[vshardrouter.ReplicasetInfo][]vshardrouter.InstanceInfo{
{
Name: "123",
}: {
Expand All @@ -39,8 +60,8 @@ func TestNewRouter_InvalidReplicasetUUID(t *testing.T) {
func TestNewRouter_InstanceAddr(t *testing.T) {
ctx := context.TODO()

router, err := vshard_router.NewRouter(ctx, vshard_router.Config{
TopologyProvider: static.NewProvider(map[vshard_router.ReplicasetInfo][]vshard_router.InstanceInfo{
router, err := vshardrouter.NewRouter(ctx, vshardrouter.Config{
TopologyProvider: static.NewProvider(map[vshardrouter.ReplicasetInfo][]vshardrouter.InstanceInfo{
{
Name: "123",
UUID: uuid.New(),
Expand All @@ -56,40 +77,40 @@ func TestNewRouter_InstanceAddr(t *testing.T) {

func TestRouterBucketIDStrCRC32(t *testing.T) {
// required values from tarantool example
require.Equal(t, uint64(103202), vshard_router.BucketIDStrCRC32("2707623829", uint64(256000)))
require.Equal(t, uint64(35415), vshard_router.BucketIDStrCRC32("2706201716", uint64(256000)))
require.Equal(t, uint64(103202), vshardrouter.BucketIDStrCRC32("2707623829", uint64(256000)))
require.Equal(t, uint64(35415), vshardrouter.BucketIDStrCRC32("2706201716", uint64(256000)))
}

func BenchmarkRouterBucketIDStrCRC32(b *testing.B) {
for i := 0; i < b.N; i++ {
vshard_router.BucketIDStrCRC32("test_bench_key", uint64(256000))
vshardrouter.BucketIDStrCRC32("test_bench_key", uint64(256000))
}
}

func TestInstanceInfo_Validate(t *testing.T) {
tCases := []struct {
Name string
II vshard_router.InstanceInfo
II vshardrouter.InstanceInfo
Valid bool
}{
{
Name: "no info",
II: vshard_router.InstanceInfo{},
II: vshardrouter.InstanceInfo{},
Valid: false,
},
{
Name: "no uuid",
II: vshard_router.InstanceInfo{Addr: "first.internal:1212"},
II: vshardrouter.InstanceInfo{Addr: "first.internal:1212"},
Valid: false,
},
{
Name: "no addr",
II: vshard_router.InstanceInfo{UUID: uuid.New()},
II: vshardrouter.InstanceInfo{UUID: uuid.New()},
Valid: false,
},
{
Name: "ok",
II: vshard_router.InstanceInfo{UUID: uuid.New(), Addr: "first.internal:1212"},
II: vshardrouter.InstanceInfo{UUID: uuid.New(), Addr: "first.internal:1212"},
Valid: true,
},
}
Expand Down

0 comments on commit 910ca35

Please sign in to comment.