From d4efbb9b229bda0f923273b13de68b3d92711135 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 15:19:10 +0300 Subject: [PATCH 01/14] metadata: allow to Set/Del multiple items Signed-off-by: Vasiliy Tolstov --- metadata/metadata.go | 30 +++++++++++++++--------------- metadata/metadata_test.go | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/metadata/metadata.go b/metadata/metadata.go index f3f1c2cf..5cb23b9b 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -76,16 +76,23 @@ func (md Metadata) Get(key string) (string, bool) { } // Set is used to store value in metadata -func (md Metadata) Set(key, val string) { - md[textproto.CanonicalMIMEHeaderKey(key)] = val +func (md Metadata) Set(kv ...string) { + if len(kv)%2 == 1 { + kv = kv[:len(kv)-1] + } + for idx := 0; idx < len(kv); idx += 2 { + md[textproto.CanonicalMIMEHeaderKey(kv[idx])] = kv[idx+1] + } } // Del is used to remove value from metadata -func (md Metadata) Del(key string) { - // fast path - delete(md, key) - // slow path - delete(md, textproto.CanonicalMIMEHeaderKey(key)) +func (md Metadata) Del(keys ...string) { + for _, key := range keys { + // fast path + delete(md, key) + // slow path + delete(md, textproto.CanonicalMIMEHeaderKey(key)) + } } // Copy makes a copy of the metadata @@ -129,13 +136,6 @@ func Pairs(kv ...string) (Metadata, bool) { return nil, false } md := New(len(kv) / 2) - var k string - for i, v := range kv { - if i%2 == 0 { - k = v - continue - } - md.Set(k, v) - } + md.Set(kv...) return md, true } diff --git a/metadata/metadata_test.go b/metadata/metadata_test.go index f566d520..eccea7a7 100644 --- a/metadata/metadata_test.go +++ b/metadata/metadata_test.go @@ -5,6 +5,21 @@ import ( "testing" ) +func TestMetadataSetMultiple(t *testing.T) { + md := New(4) + md.Set("key1", "val1", "key2", "val2", "key3") + + if v, ok := md.Get("key1"); !ok || v != "val1" { + t.Fatalf("invalid kv %#+v", md) + } + if v, ok := md.Get("key2"); !ok || v != "val2" { + t.Fatalf("invalid kv %#+v", md) + } + if _, ok := md.Get("key3"); ok { + t.Fatalf("invalid kv %#+v", md) + } +} + func TestAppend(t *testing.T) { ctx := context.Background() ctx = AppendIncomingContext(ctx, "key1", "val1", "key2", "val2") From 20e40ccdfd5b7b97270e072d362da23193514e62 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 15:41:30 +0300 Subject: [PATCH 02/14] api: improve coverage Signed-off-by: Vasiliy Tolstov --- api/api_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/api/api_test.go b/api/api_test.go index b576fd0a..79e95250 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -3,10 +3,27 @@ package api import ( "strings" "testing" + + "go.unistack.org/micro/v3/metadata" + "go.unistack.org/micro/v3/server" ) +func TestDecode(t *testing.T) { + md := metadata.New(0) + md.Set("host", "localhost", "method", "GET", "path", "/") + ep := Decode(md) + if md == nil { + t.Fatalf("failed to decode md %#+v", md) + } else if len(ep.Host) != 1 || len(ep.Method) != 1 || len(ep.Path) != 1 { + t.Fatalf("ep invalid after decode %#+v", ep) + } + if ep.Host[0] != "localhost" || ep.Method[0] != "GET" || ep.Path[0] != "/" { + t.Fatalf("ep invalid after decode %#+v", ep) + } +} + //nolint:gocyclo -func TestEncoding(t *testing.T) { +func TestEncode(t *testing.T) { testData := []*Endpoint{ nil, { @@ -150,3 +167,79 @@ func TestValidate(t *testing.T) { t.Fatalf("invalid pcre %v", epPcreInvalid.Path[0]) } } + +func TestWithEndpoint(t *testing.T) { + ep := &Endpoint{ + Name: "Foo.Bar", + Description: "A test endpoint", + Handler: "meta", + Host: []string{"foo.com"}, + Method: []string{"GET"}, + Path: []string{"/test/{id}"}, + } + o := WithEndpoint(ep) + opts := server.NewHandlerOptions(o) + if opts.Metadata == nil { + t.Fatalf("WithEndpoint not works %#+v", opts) + } + md, ok := opts.Metadata[ep.Name] + if !ok { + t.Fatalf("WithEndpoint not works %#+v", opts) + } + if v, ok := md.Get("Endpoint"); !ok || v != "Foo.Bar" { + t.Fatalf("WithEndpoint not works %#+v", md) + } +} + +func TestValidateNilErr(t *testing.T) { + var ep *Endpoint + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateMissingNameErr(t *testing.T) { + ep := &Endpoint{} + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateMissingHandlerErr(t *testing.T) { + ep := &Endpoint{Name: "test"} + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateRegexpStartErr(t *testing.T) { + ep := &Endpoint{Name: "test", Handler: "test"} + ep.Path = []string{"^/"} + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateRegexpEndErr(t *testing.T) { + ep := &Endpoint{Name: "test", Handler: "test", Path: []string{""}} + ep.Path[0] = "/$" + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateRegexpNonErr(t *testing.T) { + ep := &Endpoint{Name: "test", Handler: "test", Path: []string{""}} + ep.Path[0] = "^/(.*)$" + if err := Validate(ep); err != nil { + t.Fatalf("Validate not works") + } +} + +func TestValidateRegexpErr(t *testing.T) { + ep := &Endpoint{Name: "test", Handler: "test", Path: []string{""}} + ep.Path[0] = "^/(.$" + if err := Validate(ep); err == nil { + t.Fatalf("Validate not works") + } +} From 8ff312e71da6b052081d49f2438d4db24b411763 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 15:51:08 +0300 Subject: [PATCH 03/14] broker: improve coverage Signed-off-by: Vasiliy Tolstov --- broker/context_test.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/broker/context_test.go b/broker/context_test.go index 65337cfe..cd4feb5e 100644 --- a/broker/context_test.go +++ b/broker/context_test.go @@ -7,16 +7,31 @@ import ( func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), brokerKey{}, NewBroker()) - c, ok := FromContext(ctx) if c == nil || !ok { t.Fatal("FromContext not works") } } +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + func TestNewContext(t *testing.T) { ctx := NewContext(context.TODO(), NewBroker()) + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewBroker()) c, ok := FromContext(ctx) if c == nil || !ok { t.Fatal("NewContext not works") From 80d342a72a1f1a032e667ee3ff49da5c7289923d Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 15:59:38 +0300 Subject: [PATCH 04/14] client: improve coverage Signed-off-by: Vasiliy Tolstov --- client/context_test.go | 16 +++++++++++ client/noop.go | 61 +++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/client/context_test.go b/client/context_test.go index 3f29ace5..e562529e 100644 --- a/client/context_test.go +++ b/client/context_test.go @@ -14,9 +14,25 @@ func TestFromContext(t *testing.T) { } } +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + func TestNewContext(t *testing.T) { ctx := NewContext(context.TODO(), NewClient()) + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewClient()) c, ok := FromContext(ctx) if c == nil || !ok { t.Fatal("NewContext not works") diff --git a/client/noop.go b/client/noop.go index bdded98e..dfcf9025 100644 --- a/client/noop.go +++ b/client/noop.go @@ -9,6 +9,7 @@ import ( "go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v3/metadata" + "go.unistack.org/micro/v3/selector" ) // DefaultCodecs will be used to encode/decode data @@ -233,18 +234,7 @@ func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opt callOpts.Address = []string{n.opts.Proxy} } - // lookup the route to send the reques to - // TODO apply any filtering here - routes, err := n.opts.Lookup(ctx, req, callOpts) - if err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) - } - - // balance the list of nodes - next, err := callOpts.Selector.Select(routes) - if err != nil { - return err - } + var next selector.Next // return errors.New("go.micro.client", "request timeout", 408) call := func(i int) error { @@ -259,6 +249,22 @@ func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opt time.Sleep(t) } + if next == nil { + var routes []string + // lookup the route to send the reques to + // TODO apply any filtering here + routes, err = n.opts.Lookup(ctx, req, callOpts) + if err != nil { + return errors.InternalServerError("go.micro.client", err.Error()) + } + + // balance the list of nodes + next, err = callOpts.Selector.Select(routes) + if err != nil { + return err + } + } + node := next() // make the call @@ -323,6 +329,8 @@ func (n *noopClient) NewMessage(topic string, msg interface{}, opts ...MessageOp } func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) { + var err error + // make a copy of call opts callOpts := n.opts.CallOptions for _, o := range opts { @@ -374,18 +382,7 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption callOpts.Address = []string{n.opts.Proxy} } - // lookup the route to send the reques to - // TODO apply any filtering here - routes, err := n.opts.Lookup(ctx, req, callOpts) - if err != nil { - return nil, errors.InternalServerError("go.micro.client", err.Error()) - } - - // balance the list of nodes - next, err := callOpts.Selector.Select(routes) - if err != nil { - return nil, err - } + var next selector.Next call := func(i int) (Stream, error) { // call backoff first. Someone may want an initial start delay @@ -399,6 +396,22 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption time.Sleep(t) } + if next == nil { + var routes []string + // lookup the route to send the reques to + // TODO apply any filtering here + routes, err = n.opts.Lookup(ctx, req, callOpts) + if err != nil { + return nil, errors.InternalServerError("go.micro.client", err.Error()) + } + + // balance the list of nodes + next, err = callOpts.Selector.Select(routes) + if err != nil { + return nil, err + } + } + node := next() stream, cerr := n.stream(ctx, node, req, callOpts) From 6ac7b53d75f98e8928cb499910a4d7475ac20fdd Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:04:48 +0300 Subject: [PATCH 05/14] server: improve coverage Signed-off-by: Vasiliy Tolstov --- server/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/context_test.go b/server/context_test.go index 7afbdb3f..a479c203 100644 --- a/server/context_test.go +++ b/server/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewServer()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), serverKey{}, NewServer()) From 1181e9dc5e0d9bcd58127e05e0ccc85230068c63 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:04:57 +0300 Subject: [PATCH 06/14] tracer: improve coverage Signed-off-by: Vasiliy Tolstov --- tracer/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tracer/context_test.go b/tracer/context_test.go index 203ce38a..06fa9015 100644 --- a/tracer/context_test.go +++ b/tracer/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewTracer()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), tracerKey{}, NewTracer()) From 8b6bdb857baad473b41c468936c5220f23499dd8 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:03 +0300 Subject: [PATCH 07/14] store: improve coverage Signed-off-by: Vasiliy Tolstov --- store/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/store/context_test.go b/store/context_test.go index 53af8027..bc9973b5 100644 --- a/store/context_test.go +++ b/store/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewStore()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), storeKey{}, NewStore()) From dbfcfcd288698f27b979af68a0596a4838667156 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:12 +0300 Subject: [PATCH 08/14] router: improve coverage Signed-off-by: Vasiliy Tolstov --- router/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/router/context_test.go b/router/context_test.go index 2f330352..f16a172d 100644 --- a/router/context_test.go +++ b/router/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewRouter()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), routerKey{}, NewRouter()) From f9ecb9b0568f19049b1aee707c7c9185e983693c Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:18 +0300 Subject: [PATCH 09/14] register: improve coverage Signed-off-by: Vasiliy Tolstov --- register/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/register/context_test.go b/register/context_test.go index e6160dad..614a0b08 100644 --- a/register/context_test.go +++ b/register/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewRegister()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), registerKey{}, NewRegister()) From d26e9d642b89c330281840787fb60aeade50958b Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:28 +0300 Subject: [PATCH 10/14] meter: improve coverage Signed-off-by: Vasiliy Tolstov --- meter/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/meter/context_test.go b/meter/context_test.go index 2e7d2510..7059c598 100644 --- a/meter/context_test.go +++ b/meter/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewMeter()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), meterKey{}, NewMeter()) From 4ab7f19ef05707ee320129e2fc70083e731ad19d Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:36 +0300 Subject: [PATCH 11/14] logger: improve coverage Signed-off-by: Vasiliy Tolstov --- logger/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/logger/context_test.go b/logger/context_test.go index 20ed4131..7d636818 100644 --- a/logger/context_test.go +++ b/logger/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewLogger()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), loggerKey{}, NewLogger()) From 9af23e3e746c4fd441e0158d0dc4ac5ff6135147 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:42 +0300 Subject: [PATCH 12/14] metadata: improve coverage Signed-off-by: Vasiliy Tolstov --- metadata/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/metadata/context_test.go b/metadata/context_test.go index c13e3875..deaa020a 100644 --- a/metadata/context_test.go +++ b/metadata/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, New(0)) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), mdKey{}, &rawMetadata{New(0)}) From aefc398b710f02c45ec2115491dcf1c9a3db6f93 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:51 +0300 Subject: [PATCH 13/14] flow: improve coverage Signed-off-by: Vasiliy Tolstov --- flow/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/flow/context_test.go b/flow/context_test.go index b767789f..03262697 100644 --- a/flow/context_test.go +++ b/flow/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewFlow()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), flowKey{}, NewFlow()) From c26ad51e25e7a484e4d3c53511788190481f46b4 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 May 2022 16:05:56 +0300 Subject: [PATCH 14/14] config: improve coverage Signed-off-by: Vasiliy Tolstov --- config/context_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/config/context_test.go b/config/context_test.go index e1e1d3f3..2976dcbc 100644 --- a/config/context_test.go +++ b/config/context_test.go @@ -5,6 +5,24 @@ import ( "testing" ) +func TestFromNilContext(t *testing.T) { + // nolint: staticcheck + c, ok := FromContext(nil) + if ok || c != nil { + t.Fatal("FromContext not works") + } +} + +func TestNewNilContext(t *testing.T) { + // nolint: staticcheck + ctx := NewContext(nil, NewConfig()) + + c, ok := FromContext(ctx) + if c == nil || !ok { + t.Fatal("NewContext not works") + } +} + func TestFromContext(t *testing.T) { ctx := context.WithValue(context.TODO(), configKey{}, NewConfig())