From b1f51ad0c864c11d5c85867c9edb6ee096d85146 Mon Sep 17 00:00:00 2001 From: Mulavar <978007503@qq.com> Date: Thu, 24 Jun 2021 11:18:27 +0800 Subject: [PATCH] make the package v3router/judger test coverage rate reach 80% (#1260) * make the package v3router/judger test coverage rate reach 80% * add router_chain unit test * refactor imports and some code * remove blank lines Co-authored-by: dongjianhui --- .../judger/attachment_match_judger.go | 55 +++++-------- .../judger/attachment_match_judger_test.go | 15 ++-- .../judger/list_string_match_judger_test.go | 40 ++++++++++ .../v3router/judger/method_match_judger.go | 1 + .../judger/method_match_judger_test.go | 77 +++++++++++++++++++ .../judger/url_label_match_judge_test.go | 41 ++++++++++ cluster/router/v3router/router_chain.go | 10 ++- cluster/router/v3router/router_chain_test.go | 53 +++++++++++++ config/uniform_router_config.go | 2 +- 9 files changed, 251 insertions(+), 43 deletions(-) create mode 100644 cluster/router/v3router/judger/list_string_match_judger_test.go create mode 100644 cluster/router/v3router/judger/method_match_judger_test.go create mode 100644 cluster/router/v3router/judger/url_label_match_judge_test.go diff --git a/cluster/router/v3router/judger/attachment_match_judger.go b/cluster/router/v3router/judger/attachment_match_judger.go index cb4d3eaa95..31f46e05cf 100644 --- a/cluster/router/v3router/judger/attachment_match_judger.go +++ b/cluster/router/v3router/judger/attachment_match_judger.go @@ -29,45 +29,30 @@ type AttachmentMatchJudger struct { // nolint func (amj *AttachmentMatchJudger) Judge(invocation protocol.Invocation) bool { invAttaMap := invocation.Attachments() - if amj.EagleeyeContext != nil { - for k, v := range amj.EagleeyeContext { - invAttaValue, ok := invAttaMap[k] - if !ok { - if v.Empty == "" { - return false - } - continue - } - // exist this key - str, ok := invAttaValue.(string) - if !ok { - return false - } - strJudger := NewStringMatchJudger(v) - if !strJudger.Judge(str) { - return false - } - } + if amj.EagleeyeContext != nil && !judge(amj.EagleeyeContext, invAttaMap) { + return false } - if amj.DubboContext != nil { - for k, v := range amj.DubboContext { - invAttaValue, ok := invAttaMap[k] - if !ok { - if v.Empty == "" { - return false - } - continue - } - // exist this key - str, ok := invAttaValue.(string) - if !ok { - return false - } - strJudger := NewStringMatchJudger(v) - if !strJudger.Judge(str) { + return amj.DubboContext == nil || judge(amj.DubboContext, invAttaMap) +} + +func judge(condition map[string]*config.StringMatch, invAttaMap map[string]interface{}) bool { + for k, v := range condition { + invAttaValue, ok := invAttaMap[k] + if !ok { + if v.Empty == "" { return false } + continue + } + // exist this key + str, ok := invAttaValue.(string) + if !ok { + return false + } + strJudger := NewStringMatchJudger(v) + if !strJudger.Judge(str) { + return false } } diff --git a/cluster/router/v3router/judger/attachment_match_judger_test.go b/cluster/router/v3router/judger/attachment_match_judger_test.go index 7e6b324947..26a8d5ed59 100644 --- a/cluster/router/v3router/judger/attachment_match_judger_test.go +++ b/cluster/router/v3router/judger/attachment_match_judger_test.go @@ -31,19 +31,24 @@ import ( ) func TestAttachmentMatchJudger(t *testing.T) { - dubboCtxMap := make(map[string]*config.StringMatch) + conditionMap := make(map[string]*config.StringMatch) dubboIvkMap := make(map[string]interface{}) - dubboCtxMap["test-key"] = &config.StringMatch{ + conditionMap["test-key"] = &config.StringMatch{ Exact: "abc", } dubboIvkMap["test-key"] = "abc" assert.True(t, NewAttachmentMatchJudger(&config.DubboAttachmentMatch{ - DubboContext: dubboCtxMap, + DubboContext: conditionMap, + }).Judge(invocation.NewRPCInvocation("method", nil, dubboIvkMap))) + assert.True(t, NewAttachmentMatchJudger(&config.DubboAttachmentMatch{ + EagleeyeContext: conditionMap, }).Judge(invocation.NewRPCInvocation("method", nil, dubboIvkMap))) dubboIvkMap["test-key"] = "abd" assert.False(t, NewAttachmentMatchJudger(&config.DubboAttachmentMatch{ - DubboContext: dubboCtxMap, + DubboContext: conditionMap, + }).Judge(invocation.NewRPCInvocation("method", nil, dubboIvkMap))) + assert.False(t, NewAttachmentMatchJudger(&config.DubboAttachmentMatch{ + EagleeyeContext: conditionMap, }).Judge(invocation.NewRPCInvocation("method", nil, dubboIvkMap))) - } diff --git a/cluster/router/v3router/judger/list_string_match_judger_test.go b/cluster/router/v3router/judger/list_string_match_judger_test.go new file mode 100644 index 0000000000..1816b9503f --- /dev/null +++ b/cluster/router/v3router/judger/list_string_match_judger_test.go @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package judger + +import ( + "testing" +) + +import ( + "github.com/stretchr/testify/assert" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/config" +) + +func TestListStringMatchJudger(t *testing.T) { + assert.True(t, newListStringMatchJudger(&config.ListStringMatch{ + Oneof: []*config.StringMatch{{Exact: "abd"}}, + }).Judge("abd")) + + assert.False(t, newListStringMatchJudger(&config.ListStringMatch{ + Oneof: []*config.StringMatch{{Exact: "abc"}}, + }).Judge("abd")) +} diff --git a/cluster/router/v3router/judger/method_match_judger.go b/cluster/router/v3router/judger/method_match_judger.go index edf8fa0b4b..e069ef9cca 100644 --- a/cluster/router/v3router/judger/method_match_judger.go +++ b/cluster/router/v3router/judger/method_match_judger.go @@ -57,6 +57,7 @@ func (mmj *MethodMatchJudger) Judge(invocation protocol.Invocation) bool { if !newListStringMatchJudger(v.StrValue).Judge(value.String()) { return false } + // FIXME int invoke Float may cause panic case "float", "int": // todo now numbers Must not be zero, else it will ignore this match if !newListDoubleMatchJudger(v.NumValue).Judge(value.Float()) { diff --git a/cluster/router/v3router/judger/method_match_judger_test.go b/cluster/router/v3router/judger/method_match_judger_test.go new file mode 100644 index 0000000000..71e90aacb5 --- /dev/null +++ b/cluster/router/v3router/judger/method_match_judger_test.go @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package judger + +import ( + "reflect" + "testing" +) + +import ( + "github.com/stretchr/testify/assert" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/config" + "dubbo.apache.org/dubbo-go/v3/protocol/invocation" +) + +func TestMethodMatchJudger(t *testing.T) { + methodArgs := make([]*config.DubboMethodArg, 0) + methodArgs = append(methodArgs, &config.DubboMethodArg{ + Index: 1, + Type: "string", + StrValue: &config.ListStringMatch{Oneof: []*config.StringMatch{{Exact: "hello world"}}}, + NumValue: nil, + BoolValue: nil, + }) + methodArgs = append(methodArgs, &config.DubboMethodArg{ + Index: 2, + Type: "bool", + StrValue: nil, + NumValue: nil, + BoolValue: &config.BoolMatch{Exact: true}, + }) + methodArgs = append(methodArgs, &config.DubboMethodArg{ + Index: 3, + Type: "float64", + StrValue: nil, + NumValue: &config.ListDoubleMatch{Oneof: []*config.DoubleMatch{{Exact: 10}}}, + BoolValue: nil, + }) + + methodMatch := &config.DubboMethodMatch{ + NameMatch: &config.StringMatch{Exact: "Greet"}, + Argc: 3, + Args: methodArgs, + Argp: nil, + Headers: nil, + } + + stringValue := reflect.ValueOf("hello world") + boolValue := reflect.ValueOf(true) + numValue := reflect.ValueOf(10.0) + ivc := invocation.NewRPCInvocationWithOptions( + invocation.WithMethodName("Greet"), + invocation.WithParameterValues([]reflect.Value{stringValue, boolValue, numValue}), + ) + + assert.False(t, NewMethodMatchJudger(&config.DubboMethodMatch{NameMatch: &config.StringMatch{Exact: "Great"}}).Judge(ivc)) + assert.False(t, NewMethodMatchJudger(&config.DubboMethodMatch{NameMatch: &config.StringMatch{Exact: "Greet"}, Argc: 1}).Judge(ivc)) + assert.True(t, NewMethodMatchJudger(methodMatch).Judge(ivc)) +} diff --git a/cluster/router/v3router/judger/url_label_match_judge_test.go b/cluster/router/v3router/judger/url_label_match_judge_test.go new file mode 100644 index 0000000000..bb4b4679dd --- /dev/null +++ b/cluster/router/v3router/judger/url_label_match_judge_test.go @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package judger + +import ( + "testing" +) + +import ( + "github.com/stretchr/testify/assert" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common" +) + +func TestJudgeUrlLabel(t *testing.T) { + url := common.NewURLWithOptions(common.WithParamsValue("a", "A")) + + labels := make(map[string]string) + labels["a"] = "A" + assert.True(t, JudgeUrlLabel(url, labels)) + + labels["a"] = "B" + assert.False(t, JudgeUrlLabel(url, labels)) +} diff --git a/cluster/router/v3router/router_chain.go b/cluster/router/v3router/router_chain.go index 1ae21304ff..dc14c7325d 100644 --- a/cluster/router/v3router/router_chain.go +++ b/cluster/router/v3router/router_chain.go @@ -95,7 +95,7 @@ func (r *RouterChain) Process(event *config_center.ConfigChangeEvent) { logger.Error("newVSValue.ObjectMeta.Annotations has no key named kubectl.kubernetes.io/last-applied-configuration") return } - logger.Debugf("json file = %v\n", newVSJsonValue) + logger.Debugf("new virtual service json value = \n%v\n", newVSJsonValue) newVirtualServiceConfig := &config.VirtualServiceConfig{} if err := json.Unmarshal([]byte(newVSJsonValue), newVirtualServiceConfig); err != nil { logger.Error("on process json data unmarshal error = ", err) @@ -148,7 +148,7 @@ func (r *RouterChain) Process(event *config_center.ConfigChangeEvent) { return } default: - logger.Error("unknow unsupported event key:", event.Key) + logger.Error("unknown unsupported event key:", event.Key) } } @@ -180,6 +180,7 @@ func parseFromConfigToRouters(virtualServiceConfig, destinationRuleConfig []byte vsDecoder := yaml.NewDecoder(strings.NewReader(string(virtualServiceConfig))) drDecoder := yaml.NewDecoder(strings.NewReader(string(destinationRuleConfig))) + // parse virtual service for { virtualServiceCfg := &config.VirtualServiceConfig{} @@ -195,6 +196,7 @@ func parseFromConfigToRouters(virtualServiceConfig, destinationRuleConfig []byte virtualServiceConfigList = append(virtualServiceConfigList, virtualServiceCfg) } + // parse destination rule for { destRuleCfg := &config.DestinationRuleConfig{} err := drDecoder.Decode(destRuleCfg) @@ -205,10 +207,14 @@ func parseFromConfigToRouters(virtualServiceConfig, destinationRuleConfig []byte logger.Error("parseFromConfigTo destination rule err = ", err) return nil, err } + + // name -> labels destRuleCfgMap := make(map[string]map[string]string) for _, v := range destRuleCfg.Spec.SubSets { destRuleCfgMap[v.Name] = v.Labels } + + // host -> name -> labels destRuleConfigsMap[destRuleCfg.Spec.Host] = destRuleCfgMap } diff --git a/cluster/router/v3router/router_chain_test.go b/cluster/router/v3router/router_chain_test.go index 7293963d1c..4ce4eef3b0 100644 --- a/cluster/router/v3router/router_chain_test.go +++ b/cluster/router/v3router/router_chain_test.go @@ -22,6 +22,16 @@ import ( "testing" ) +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/cluster/router/v3router/k8s_api" + "dubbo.apache.org/dubbo-go/v3/config" + "dubbo.apache.org/dubbo-go/v3/config_center" +) + import ( "github.com/stretchr/testify/assert" ) @@ -206,3 +216,46 @@ func TestRouterChain_Route(t *testing.T) { assert.Equal(t, 0, len(result)) //todo test find target invoker } + +func TestRouterChain_Process(t *testing.T) { + vsJson := `{"apiVersion":"service.dubbo.apache.org/v1alpha2", "kind":"VirtualService", "name":"demo-route"}` + + rc := &RouterChain{} + mockVirtualServiceConfig := &config.VirtualServiceConfig{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + "kubectl.kubernetes.io/last-applied-configuration": vsJson, + }, + }, + } + + // test virtual service config chage event + mockVirtualServiceChangeEvent := &config_center.ConfigChangeEvent{ + Key: k8s_api.VirtualServiceEventKey, + Value: mockVirtualServiceConfig, + ConfigType: 0, + } + rc.Process(mockVirtualServiceChangeEvent) + + // test destination rule config chage event + destJson := `{"apiVersion":"service.dubbo.apache.org/v1alpha2", "kind":"VirtualService", "name":"demo-route"}` + mockDestinationRuleConfig := &config.DestinationRuleConfig{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + "kubectl.kubernetes.io/last-applied-configuration": destJson, + }, + }, + } + mockDestinationRuleChangeEvent := &config_center.ConfigChangeEvent{ + Key: k8s_api.DestinationRuleEventKey, + Value: mockDestinationRuleConfig, + ConfigType: 0, + } + rc.Process(mockDestinationRuleChangeEvent) + + // test unknown event type + mockUnsupportedEvent := &config_center.ConfigChangeEvent{ + Key: "unknown", + } + rc.Process(mockUnsupportedEvent) +} diff --git a/config/uniform_router_config.go b/config/uniform_router_config.go index e18c07c082..fa5d02db19 100644 --- a/config/uniform_router_config.go +++ b/config/uniform_router_config.go @@ -25,7 +25,7 @@ import ( // nolint type MetaDataStruct struct { - Name string `yaml:"name"` + Name string `yaml:"name" json:"name"` } // VirtualService Config Definition