| /* |
| * 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 dubboproxy |
| |
| import ( |
| "fmt" |
| "github.com/apache/servicecomb-mesher/proxy/bootstrap" |
| "github.com/apache/servicecomb-mesher/proxy/cmd" |
| "github.com/apache/servicecomb-mesher/proxy/common" |
| mesherCommon "github.com/apache/servicecomb-mesher/proxy/common" |
| mesherRuntime "github.com/apache/servicecomb-mesher/proxy/pkg/runtime" |
| dubboclient "github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/client" |
| "github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/dubbo" |
| "github.com/go-chassis/go-chassis/v2" |
| chassisCommon "github.com/go-chassis/go-chassis/v2/core/common" |
| "github.com/go-chassis/go-chassis/v2/core/config" |
| "github.com/go-chassis/go-chassis/v2/core/config/model" |
| "github.com/go-chassis/go-chassis/v2/core/handler" |
| "github.com/go-chassis/go-chassis/v2/core/invocation" |
| "github.com/go-chassis/go-chassis/v2/core/lager" |
| "github.com/go-chassis/go-chassis/v2/core/loadbalancer" |
| "github.com/go-chassis/go-chassis/v2/core/registry" |
| "github.com/go-chassis/go-chassis/v2/third_party/forked/afex/hystrix-go/hystrix" |
| "github.com/stretchr/testify/assert" |
| "github.com/stretchr/testify/mock" |
| "os" |
| "strings" |
| "testing" |
| |
| // rate limiter handler |
| _ "github.com/go-chassis/go-chassis/v2/middleware/ratelimiter" |
| ) |
| |
| func init() { |
| lager.Init(&lager.Options{LoggerLevel: "DEBUG"}) |
| } |
| |
| func TestSetLocalServiceAddress(t *testing.T) { |
| t.Run("Run not set env EnvServicePorts", func(t *testing.T) { |
| inv := &invocation.Invocation{Protocol: "rest"} |
| cmd.Init() |
| _ = cmd.Configs.GeneratePortsMap() |
| t.Log(cmd.Configs.PortsMap) |
| err := SetLocalServiceAddress(inv) |
| assert.Error(t, err) |
| |
| // case port |
| inv.Port = "8080" |
| err = SetLocalServiceAddress(inv) |
| assert.NoError(t, err) |
| }) |
| |
| t.Run("Run with env EnvServicePorts", func(t *testing.T) { |
| inv := &invocation.Invocation{Protocol: "rest"} |
| os.Setenv(common.EnvServicePorts, "rest:8080,grpc:90") |
| cmd.Init() |
| _ = cmd.Configs.GeneratePortsMap() |
| t.Log(cmd.Configs.PortsMap) |
| err := SetLocalServiceAddress(inv) |
| assert.NoError(t, err) |
| }) |
| } |
| |
| func TestHandle(t *testing.T) { |
| t.Run("Run as Provider", func(t *testing.T) { |
| os.Setenv(common.EnvServicePorts, "dubbo:8081,rest:8080") |
| cmd.Init() |
| _ = cmd.Configs.GeneratePortsMap() |
| |
| protoMap := make(map[string]model.Protocol) |
| config.GlobalDefinition = &model.GlobalCfg{ |
| ServiceComb: model.ServiceComb{ |
| Protocols: protoMap, |
| }, |
| } |
| |
| bootstrap.RegisterFramework() |
| bootstrap.SetHandlers() |
| chassis.Init() |
| |
| consumerChain := strings.Join([]string{ |
| handler.Router, |
| //"ratelimiter-consumer", |
| //"bizkeeper-consumer", |
| //handler.Loadbalance, |
| //handler.Transport, |
| }, ",") |
| providerChain := strings.Join([]string{ |
| //handler.RateLimiterProvider, |
| //handler.Transport, |
| }, ",") |
| consumerChainMap := map[string]string{ |
| common.ChainConsumerOutgoing: consumerChain, |
| } |
| providerChainMap := map[string]string{ |
| common.ChainProviderIncoming: providerChain, |
| "default": handler.RateLimiterProvider, |
| } |
| |
| registry.DefaultContractDiscoveryService = new(MockContractDiscoveryService) |
| mesherRuntime.Role = mesherCommon.RoleSidecar |
| |
| req := dubbo.NewDubboRequest() |
| req.SetAttachment(dubbo.PathKey, "hello") |
| ctx := &dubbo.InvokeContext{req, &dubbo.DubboRsp{}, nil, "", "127.0.0.1:9090"} |
| ctx.Rsp.Init() |
| |
| // case get chain error |
| err := Handle(ctx) |
| assert.Error(t, err) |
| |
| // case get chain ok |
| handler.CreateChains(chassisCommon.Provider, providerChainMap) |
| handler.CreateChains(chassisCommon.Consumer, consumerChainMap) |
| err = Handle(ctx) |
| assert.NoError(t, err) |
| |
| handler.ChainMap = make(map[string]*handler.Chain) |
| }) |
| |
| t.Run("Run as Consumer", func(t *testing.T) { |
| //os.Setenv(common.EnvServicePorts, "rest:8080,grpc:90") |
| os.Unsetenv(common.EnvServicePorts) |
| cmd.Init() |
| _ = cmd.Configs.GeneratePortsMap() |
| |
| protoMap := make(map[string]model.Protocol) |
| config.GlobalDefinition = &model.GlobalCfg{ |
| ServiceComb: model.ServiceComb{ |
| Protocols: protoMap, |
| }, |
| } |
| |
| bootstrap.RegisterFramework() |
| bootstrap.SetHandlers() |
| chassis.Init() |
| |
| consumerChain := strings.Join([]string{ |
| handler.Router, |
| //"ratelimiter-consumer", |
| //"bizkeeper-consumer", |
| //handler.Loadbalance, |
| //handler.Transport, |
| }, ",") |
| providerChain := strings.Join([]string{ |
| //handler.RateLimiterProvider, |
| //handler.Transport, |
| }, ",") |
| consumerChainMap := map[string]string{ |
| common.ChainConsumerOutgoing: consumerChain, |
| } |
| providerChainMap := map[string]string{ |
| common.ChainProviderIncoming: providerChain, |
| "default": handler.RateLimiterProvider, |
| } |
| |
| registry.DefaultContractDiscoveryService = new(MockContractDiscoveryService) |
| mesherRuntime.Role = mesherCommon.RoleSidecar |
| |
| req := dubbo.NewDubboRequest() |
| req.SetAttachment(dubbo.PathKey, "hello") |
| ctx := &dubbo.InvokeContext{req, &dubbo.DubboRsp{}, nil, "", "127.0.0.1:9090"} |
| ctx.Rsp.Init() |
| |
| // case get chain error |
| err := Handle(ctx) |
| assert.Error(t, err) |
| |
| // case get chain ok |
| handler.CreateChains(chassisCommon.Provider, providerChainMap) |
| handler.CreateChains(chassisCommon.Consumer, consumerChainMap) |
| err = Handle(ctx) |
| assert.NoError(t, err) |
| |
| handler.ChainMap = make(map[string]*handler.Chain) |
| }) |
| } |
| |
| func Test_handleDubboRequest(t *testing.T) { |
| req := dubbo.NewDubboRequest() |
| req.SetAttachment(dubbo.PathKey, "hello") |
| ctx := &dubbo.InvokeContext{req, &dubbo.DubboRsp{}, nil, "", "127.0.0.1:9090"} |
| ctx.Rsp.Init() |
| |
| inv := &invocation.Invocation{Protocol: "rest"} |
| ir := &invocation.Response{} |
| inv.Endpoint = "127.0.0.1:8080" |
| |
| // case responese ir.Result = nil |
| handleDubboRequest(inv, ctx, ir) |
| |
| // case responese ir.Result != nil |
| ir.Result = &dubboclient.WrapResponse{Resp: &dubbo.DubboRsp{}} |
| handleDubboRequest(inv, ctx, ir) |
| |
| // Case ir.Err == hystrix.FallbackNullError |
| ir.Err = hystrix.FallbackNullError{"Error."} |
| handleDubboRequest(inv, ctx, ir) |
| // Case ir.Err == hystrix.CircuitError: |
| ir.Err = hystrix.CircuitError{"Error."} |
| handleDubboRequest(inv, ctx, ir) |
| // Case ir.Err == loadbalancer.LBError |
| ir.Err = loadbalancer.LBError{"Error."} |
| handleDubboRequest(inv, ctx, ir) |
| // Case ir.Err == other |
| ir.Err = fmt.Errorf("Other error.") |
| handleDubboRequest(inv, ctx, ir) |
| |
| // case ir == nil |
| handleDubboRequest(inv, ctx, nil) |
| |
| } |
| |
| // ContractDiscoveryService struct for disco mock |
| type MockContractDiscoveryService struct { |
| mock.Mock |
| } |
| |
| func (m *MockContractDiscoveryService) GetMicroServicesByInterface(interfaceName string) (microservices []*registry.MicroService) { |
| microservices = append(microservices, ®istry.MicroService{}) |
| return |
| } |
| |
| func (m *MockContractDiscoveryService) GetSchemaContentByInterface(interfaceName string) registry.SchemaContent { |
| return registry.SchemaContent{} |
| } |
| |
| func (m *MockContractDiscoveryService) GetSchemaContentByServiceName(svcName, version, appID, env string) []*registry.SchemaContent { |
| var sc []*registry.SchemaContent |
| sc = append(sc, ®istry.SchemaContent{ |
| Paths: map[string]map[string]registry.MethodInfo{ |
| "hello": {}, |
| }, |
| }) |
| return nil |
| } |
| |
| func (m *MockContractDiscoveryService) Close() error { |
| return nil |
| } |