| /* |
| * 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 proxy |
| |
| import ( |
| "context" |
| "fmt" |
| "reflect" |
| "testing" |
| ) |
| |
| import ( |
| perrors "github.com/pkg/errors" |
| "github.com/stretchr/testify/assert" |
| ) |
| |
| import ( |
| "dubbo.apache.org/dubbo-go/v3/common" |
| "dubbo.apache.org/dubbo-go/v3/common/constant" |
| "dubbo.apache.org/dubbo-go/v3/protocol" |
| "dubbo.apache.org/dubbo-go/v3/protocol/dubbo/hessian2" |
| "dubbo.apache.org/dubbo-go/v3/protocol/invocation" |
| ) |
| |
| type TestService struct { |
| MethodOne func(context.Context, int, bool, *interface{}) error |
| MethodTwo func([]interface{}) error |
| MethodThree func(int, bool) (interface{}, error) |
| MethodFour func(int, bool) (*interface{}, error) `dubbo:"methodFour"` |
| MethodFive func() error |
| MethodSix func(context.Context, string) (interface{}, error) |
| Echo func(interface{}, *interface{}) error |
| } |
| |
| func (s *TestService) Reference() string { |
| return "com.test.Path" |
| } |
| |
| type TestServiceInt int |
| |
| func (s *TestServiceInt) Reference() string { |
| return "com.test.TestServiceInt" |
| } |
| |
| func TestProxyImplement(t *testing.T) { |
| invoker := protocol.NewBaseInvoker(&common.URL{}) |
| p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"}) |
| s := &TestService{} |
| p.Implement(s) |
| |
| err := p.Get().(*TestService).MethodOne(nil, 0, false, nil) |
| assert.NoError(t, err) |
| |
| err = p.Get().(*TestService).MethodTwo(nil) |
| assert.NoError(t, err) |
| ret, err := p.Get().(*TestService).MethodThree(0, false) |
| assert.NoError(t, err) |
| assert.Nil(t, ret) // ret is nil, because it doesn't be injection yet |
| |
| ret2, err := p.Get().(*TestService).MethodFour(0, false) |
| assert.NoError(t, err) |
| assert.Equal(t, "*interface {}", reflect.TypeOf(ret2).String()) |
| err = p.Get().(*TestService).Echo(nil, nil) |
| assert.NoError(t, err) |
| |
| err = p.Get().(*TestService).MethodFive() |
| assert.NoError(t, err) |
| |
| // inherit & lowercase |
| p.rpc = nil |
| type S1 struct { |
| TestService |
| methodOne func(context.Context, interface{}, *struct{}) error |
| } |
| s1 := &S1{TestService: *s, methodOne: func(_ context.Context, _ interface{}, _ *struct{}) error { |
| return perrors.New("errors") |
| }} |
| p.Implement(s1) |
| err = s1.MethodOne(nil, 0, false, nil) |
| assert.NoError(t, err) |
| err = s1.methodOne(nil, nil, nil) |
| assert.EqualError(t, err, "errors") |
| |
| // no struct |
| p.rpc = nil |
| it := TestServiceInt(1) |
| p.Implement(&it) |
| assert.Nil(t, p.rpc) |
| |
| // return number |
| p.rpc = nil |
| type S2 struct { |
| TestService |
| MethodOne func([]interface{}) (*struct{}, int, error) |
| } |
| s2 := &S2{TestService: *s} |
| p.Implement(s2) |
| assert.Nil(t, s2.MethodOne) |
| |
| // returns type |
| p.rpc = nil |
| type S3 struct { |
| TestService |
| MethodOne func(context.Context, []interface{}, *struct{}) interface{} |
| } |
| s3 := &S3{TestService: *s} |
| p.Implement(s3) |
| assert.Nil(t, s3.MethodOne) |
| } |
| |
| func TestProxyImplementForContext(t *testing.T) { |
| invoker := &TestProxyInvoker{ |
| BaseInvoker: *protocol.NewBaseInvoker(&common.URL{}), |
| } |
| p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"}) |
| s := &TestService{} |
| p.Implement(s) |
| attachments1 := make(map[string]interface{}, 4) |
| attachments1["k1"] = "v1" |
| attachments1["k2"] = "v2" |
| context := context.WithValue(context.Background(), constant.AttachmentKey, attachments1) |
| r, err := p.Get().(*TestService).MethodSix(context, "xxx") |
| v1 := r.(map[string]interface{}) |
| assert.NoError(t, err) |
| assert.Equal(t, v1["TestProxyInvoker"], "TestProxyInvokerValue") |
| } |
| |
| type TestProxyInvoker struct { |
| protocol.BaseInvoker |
| } |
| |
| func (bi *TestProxyInvoker) Invoke(_ context.Context, inv protocol.Invocation) protocol.Result { |
| rpcInv := inv.(*invocation.RPCInvocation) |
| mapV := inv.Attachments() |
| mapV["TestProxyInvoker"] = "TestProxyInvokerValue" |
| if err := hessian2.ReflectResponse(mapV, rpcInv.Reply()); err != nil { |
| fmt.Printf("hessian2.ReflectResponse(mapV:%v) = error:%v", mapV, err) |
| } |
| |
| return &protocol.RPCResult{ |
| Rest: inv.Arguments(), |
| } |
| } |