Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
2020-10-30 23:27:33 +03:00
parent 9609706c86
commit 848ffcb6d7
9 changed files with 704 additions and 54 deletions

View File

@@ -0,0 +1,83 @@
// +build ignore
package gobreaker
import (
"context"
"testing"
"github.com/sony/gobreaker"
"github.com/unistack-org/micro/registry/memory"
"github.com/unistack-org/micro/v3/client"
"github.com/unistack-org/micro/v3/errors"
"github.com/unistack-org/micro/v3/router"
)
func TestBreaker(t *testing.T) {
// setup
r := memory.NewRegistry()
c := client.NewClient(
// set the selector
client.Router(rrouter.NewRouter(router.Registry(registry))),
// add the breaker wrapper
client.Wrap(NewClientWrapper()),
)
req := c.NewRequest("test.service", "Test.Method", map[string]string{
"foo": "bar",
}, client.WithContentType("application/json"))
var rsp map[string]interface{}
// Force to point of trip
for i := 0; i < 6; i++ {
c.Call(context.TODO(), req, rsp)
}
err := c.Call(context.TODO(), req, rsp)
if err == nil {
t.Error("Expecting tripped breaker, got nil error")
}
merr := err.(*errors.Error)
if merr.Code != 502 {
t.Errorf("Expecting tripped breaker, got %v", err)
}
}
func TestCustomBreaker(t *testing.T) {
// setup
r := memory.NewRegistry()
c := client.NewClient(
// set the selector
client.Router(rrouter.NewRouter(router.Registry(registry))),
// add the breaker wrapper
client.Wrap(NewCustomClientWrapper(
gobreaker.Settings{},
BreakService,
)),
)
req := c.NewRequest("test.service", "Test.Method", map[string]string{
"foo": "bar",
}, client.WithContentType("application/json"))
var rsp map[string]interface{}
// Force to point of trip
for i := 0; i < 6; i++ {
c.Call(context.TODO(), req, rsp)
}
err := c.Call(context.TODO(), req, rsp)
if err == nil {
t.Error("Expecting tripped breaker, got nil error")
}
merr := err.(*errors.Error)
if merr.Code != 502 {
t.Errorf("Expecting tripped breaker, got %v", err)
}
}

View File

@@ -0,0 +1,46 @@
// +build ignore
package hystrix
import (
"context"
"testing"
"github.com/afex/hystrix-go/hystrix"
rrouter "github.com/unistack-org/micro-router-registry"
"github.com/unistack-org/micro/registry/memory"
"github.com/unistack-org/micro/v3/client"
"github.com/unistack-org/micro/v3/router"
)
func TestBreaker(t *testing.T) {
// setup
registry := memory.NewRegistry()
c := client.NewClient(
// set the selector
client.Router(rrouter.NewRouter(router.Registry(registry))),
// add the breaker wrapper
client.Wrap(NewClientWrapper()),
)
req := c.NewRequest("test.service", "Test.Method", map[string]string{
"foo": "bar",
}, client.WithContentType("application/json"))
var rsp map[string]interface{}
// Force to point of trip
for i := 0; i < (hystrix.DefaultVolumeThreshold * 3); i++ {
c.Call(context.TODO(), req, rsp)
}
err := c.Call(context.TODO(), req, rsp)
if err == nil {
t.Error("Expecting tripped breaker, got nil error")
}
if err.Error() != "hystrix: circuit open" {
t.Errorf("Expecting tripped breaker, got %v", err)
}
}

View File

@@ -0,0 +1,133 @@
// +build ignore
package ratelimit
import (
"context"
"fmt"
"testing"
"time"
"github.com/juju/ratelimit"
bmemory "github.com/unistack-org/micro-broker-memory"
tmemory "github.com/unistack-org/micro-network-transport-memory"
rmemory "github.com/unistack-org/micro-registry-memory"
rrouter "github.com/unistack-org/micro-router-registry"
"github.com/unistack-org/micro/v3/client"
"github.com/unistack-org/micro/v3/errors"
"github.com/unistack-org/micro/v3/router"
"github.com/unistack-org/micro/v3/server"
)
type testHandler struct{}
type TestRequest struct{}
type TestResponse struct{}
func (t *testHandler) Method(ctx context.Context, req *TestRequest, rsp *TestResponse) error {
return nil
}
func TestRateClientLimit(t *testing.T) {
// setup
r := rmemory.NewRegistry()
tr := tmemory.NewTransport()
testRates := []int{1, 10, 20}
for _, limit := range testRates {
b := ratelimit.NewBucketWithRate(float64(limit), int64(limit))
c := client.NewClient(
client.Router(rrouter.NewRouter(router.Registry(registry))),
client.Transport(tr),
// add the breaker wrapper
client.Wrap(NewClientWrapper(b, false)),
)
req := c.NewRequest(
"test.service",
"Test.Method",
&TestRequest{},
client.WithContentType("application/json"),
)
rsp := TestResponse{}
for j := 0; j < limit; j++ {
err := c.Call(context.TODO(), req, &rsp)
e := errors.Parse(err.Error())
if e.Code == 429 {
t.Errorf("Unexpected rate limit error: %v", err)
}
}
err := c.Call(context.TODO(), req, rsp)
e := errors.Parse(err.Error())
if e.Code != 429 {
t.Errorf("Expected rate limit error, got: %v", err)
}
}
}
func TestRateServerLimit(t *testing.T) {
// setup
testRates := []int{1, 5, 6, 10}
for _, limit := range testRates {
r := rmemory.NewRegistry()
b := bmemory.NewBroker()
tr := tmemory.NewTransport()
_ = b
br := ratelimit.NewBucketWithRate(float64(limit), int64(limit))
c := client.NewClient(
client.Router(rrouter.NewRouter(router.Registry(registry))),
client.Transport(tr))
name := fmt.Sprintf("test.service.%d", limit)
srv := server.NewServer(
server.Name(name),
// add registry
server.Registry(r),
server.Transport(tr),
// add broker
//server.Broker(b),
// add the breaker wrapper
server.WrapHandler(NewHandlerWrapper(br, false)),
)
type Test struct {
*testHandler
}
srv.Handle(
srv.NewHandler(&Test{new(testHandler)}),
)
if err := srv.Start(); err != nil {
t.Fatalf("Unexpected error starting server: %v", err)
}
req := c.NewRequest(name, "Test.Method", &TestRequest{}, client.WithContentType("application/json"))
rsp := TestResponse{}
for j := 0; j < limit; j++ {
if err := c.Call(context.TODO(), req, &rsp); err != nil {
t.Fatalf("Unexpected request error: %v", err)
}
}
err := c.Call(context.TODO(), req, &rsp)
if err == nil {
t.Fatalf("Expected rate limit error, got nil: rate %d, err %v", limit, err)
}
e := errors.Parse(err.Error())
if e.Code != 429 {
t.Fatalf("Expected rate limit error, got %v", err)
}
srv.Stop()
// artificial test delay
time.Sleep(500 * time.Millisecond)
}
}

View File

@@ -0,0 +1,208 @@
// +build ignore
package datadog
import (
"context"
"sync"
"testing"
"github.com/stretchr/testify/assert"
rrouter "github.com/unistack-org/micro-router-registry"
"github.com/unistack-org/micro/registry/memory"
"github.com/unistack-org/micro/v3/client"
microerr "github.com/unistack-org/micro/v3/errors"
"github.com/unistack-org/micro/v3/router"
"github.com/unistack-org/micro/v3/server"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
cli "github.com/unistack-org/micro/v3/client"
srv "github.com/unistack-org/micro/v3/server"
)
type Test interface {
Method(ctx context.Context, in *TestRequest, opts ...client.CallOption) (*TestResponse, error)
}
type TestRequest struct {
IsError bool
}
type TestResponse struct {
Message string
}
type testHandler struct{}
func (t *testHandler) Method(ctx context.Context, req *TestRequest, rsp *TestResponse) error {
if req.IsError {
return microerr.BadRequest("bad", "test error")
}
rsp.Message = "passed"
return nil
}
func TestClient(t *testing.T) {
// setup
assert := assert.New(t)
for name, tt := range map[string]struct {
message string
isError bool
wantMessage string
wantStatus string
}{
"OK": {
message: "passed",
isError: false,
wantMessage: "passed",
wantStatus: "OK",
},
"Invalid": {
message: "",
isError: true,
wantMessage: "",
wantStatus: "InvalidArgument",
},
} {
t.Run(name, func(t *testing.T) {
mt := mocktracer.Start()
defer mt.Stop()
registry := memory.NewRegistry()
serverName := "micro.server.name"
serverID := "id-1234567890"
serverVersion := "1.0.0"
c := cli.NewClient(
client.Router(rrouter.NewRouter(router.Registry(registry))),
client.WrapCall(NewCallWrapper()),
)
s := srv.NewServer(
server.Name(serverName),
server.Version(serverVersion),
server.Id(serverID),
server.Registry(registry),
server.WrapSubscriber(NewSubscriberWrapper()),
server.WrapHandler(NewHandlerWrapper()),
)
defer s.Stop()
type Test struct {
*testHandler
}
s.Handle(s.NewHandler(&Test{new(testHandler)}))
if err := s.Start(); err != nil {
t.Fatalf("Unexpected error starting server: %v", err)
}
span, ctx := StartSpanFromContext(context.Background(), "root", tracer.ServiceName("root"), tracer.ResourceName("root"))
req := c.NewRequest(serverName, "Test.Method", &TestRequest{IsError: tt.isError}, client.WithContentType("application/json"))
rsp := TestResponse{}
err := c.Call(ctx, req, &rsp)
if tt.isError {
assert.Error(err)
} else {
assert.NoError(err)
}
assert.Equal(rsp.Message, tt.message)
span.Finish()
spans := mt.FinishedSpans()
assert.Len(spans, 3)
var serverSpan, clientSpan, rootSpan mocktracer.Span
for _, s := range spans {
// order of traces in buffer is not garanteed
switch s.OperationName() {
case "micro.server":
serverSpan = s
case "micro.client":
clientSpan = s
case "root":
rootSpan = s
}
}
assert.NotNil(serverSpan)
assert.NotNil(clientSpan)
assert.NotNil(rootSpan)
assert.Equal(rootSpan.TraceID(), clientSpan.TraceID())
assert.Equal(serverSpan.Tag(tagStatus), tt.wantStatus)
assert.Equal("Test.Method", serverSpan.Tag(ext.ResourceName))
assert.Equal(rootSpan.TraceID(), serverSpan.TraceID())
})
}
}
func TestRace(t *testing.T) {
// setup
assert := assert.New(t)
mt := mocktracer.Start()
defer mt.Stop()
registry := memory.NewRegistry()
serverName := "micro.server.name"
serverID := "id-1234567890"
serverVersion := "1.0.0"
c := cli.NewClient(
client.Router(rrouter.NewRouter(router.Registry(registry))),
client.WrapCall(NewCallWrapper()),
)
s := srv.NewServer(
server.Name(serverName),
server.Version(serverVersion),
server.Id(serverID),
server.Registry(registry),
server.WrapSubscriber(NewSubscriberWrapper()),
server.WrapHandler(NewHandlerWrapper()),
)
defer s.Stop()
type Test struct {
*testHandler
}
s.Handle(s.NewHandler(&Test{new(testHandler)}))
if err := s.Start(); err != nil {
t.Fatalf("Unexpected error starting server: %v", err)
}
span, ctx := StartSpanFromContext(context.Background(), "root", tracer.ServiceName("root"), tracer.ResourceName("root"))
num := 100
var wg sync.WaitGroup
wg.Add(num)
for i := 0; i < num; i++ {
func() {
go func(i int) {
defer wg.Done()
req := c.NewRequest(serverName, "Test.Method", &TestRequest{IsError: false}, client.WithContentType("application/json"))
rsp := TestResponse{}
err := c.Call(ctx, req, &rsp)
assert.NoError(err)
}(i)
}()
}
wg.Wait()
span.Finish()
spans := mt.FinishedSpans()
assert.Len(spans, (num*2)+1)
}