dubbo.apache.org/dubbo-go/v3@v3.1.1/proxy/proxy_test.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package proxy 19 20 import ( 21 "context" 22 "fmt" 23 "reflect" 24 "testing" 25 ) 26 27 import ( 28 perrors "github.com/pkg/errors" 29 30 "github.com/stretchr/testify/assert" 31 ) 32 33 import ( 34 "dubbo.apache.org/dubbo-go/v3/common" 35 "dubbo.apache.org/dubbo-go/v3/common/constant" 36 "dubbo.apache.org/dubbo-go/v3/protocol" 37 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo/hessian2" 38 "dubbo.apache.org/dubbo-go/v3/protocol/invocation" 39 ) 40 41 type TestService struct { 42 MethodOne func(context.Context, int, bool, *interface{}) error 43 MethodTwo func([]interface{}) error 44 MethodThree func(int, bool) (interface{}, error) 45 MethodFour func(int, bool) (*interface{}, error) `dubbo:"methodFour"` 46 MethodFive func() error 47 MethodSix func(context.Context, string) (interface{}, error) 48 Echo func(interface{}, *interface{}) error 49 } 50 51 func (s *TestService) Reference() string { 52 return "com.test.Path" 53 } 54 55 type TestServiceInt int 56 57 func (s *TestServiceInt) Reference() string { 58 return "com.test.TestServiceInt" 59 } 60 61 func TestProxyImplement(t *testing.T) { 62 invoker := protocol.NewBaseInvoker(&common.URL{}) 63 p := NewProxy(invoker, nil, map[string]string{constant.AsyncKey: "false"}) 64 s := &TestService{} 65 p.Implement(s) 66 67 err := p.Get().(*TestService).MethodOne(nil, 0, false, nil) 68 assert.NoError(t, err) 69 70 err = p.Get().(*TestService).MethodTwo(nil) 71 assert.NoError(t, err) 72 ret, err := p.Get().(*TestService).MethodThree(0, false) 73 assert.NoError(t, err) 74 assert.Nil(t, ret) // ret is nil, because it doesn't be injection yet 75 76 ret2, err := p.Get().(*TestService).MethodFour(0, false) 77 assert.NoError(t, err) 78 assert.Equal(t, "*interface {}", reflect.TypeOf(ret2).String()) 79 err = p.Get().(*TestService).Echo(nil, nil) 80 assert.NoError(t, err) 81 82 err = p.Get().(*TestService).MethodFive() 83 assert.NoError(t, err) 84 85 // inherit & lowercase 86 p.rpc = nil 87 type S1 struct { 88 TestService 89 methodOne func(context.Context, interface{}, *struct{}) error 90 } 91 s1 := &S1{TestService: *s, methodOne: func(_ context.Context, _ interface{}, _ *struct{}) error { 92 return perrors.New("errors") 93 }} 94 p.Implement(s1) 95 err = s1.MethodOne(nil, 0, false, nil) 96 assert.NoError(t, err) 97 err = s1.methodOne(nil, nil, nil) 98 assert.EqualError(t, err, "errors") 99 100 // no struct 101 p.rpc = nil 102 it := TestServiceInt(1) 103 p.Implement(&it) 104 assert.Nil(t, p.rpc) 105 106 // return number 107 p.rpc = nil 108 type S2 struct { 109 TestService 110 MethodOne func([]interface{}) (*struct{}, int, error) 111 } 112 s2 := &S2{TestService: *s} 113 p.Implement(s2) 114 assert.Nil(t, s2.MethodOne) 115 116 // returns type 117 p.rpc = nil 118 type S3 struct { 119 TestService 120 MethodOne func(context.Context, []interface{}, *struct{}) interface{} 121 } 122 s3 := &S3{TestService: *s} 123 p.Implement(s3) 124 assert.Nil(t, s3.MethodOne) 125 } 126 127 func TestProxyImplementForContext(t *testing.T) { 128 invoker := &TestProxyInvoker{ 129 BaseInvoker: *protocol.NewBaseInvoker(&common.URL{}), 130 } 131 p := NewProxy(invoker, nil, map[string]string{constant.AsyncKey: "false"}) 132 s := &TestService{} 133 p.Implement(s) 134 attachments1 := make(map[string]interface{}, 4) 135 attachments1["k1"] = "v1" 136 attachments1["k2"] = "v2" 137 context := context.WithValue(context.Background(), constant.AttachmentKey, attachments1) 138 r, err := p.Get().(*TestService).MethodSix(context, "xxx") 139 v1 := r.(map[string]interface{}) 140 assert.NoError(t, err) 141 assert.Equal(t, v1["TestProxyInvoker"], "TestProxyInvokerValue") 142 } 143 144 type TestProxyInvoker struct { 145 protocol.BaseInvoker 146 } 147 148 func (bi *TestProxyInvoker) Invoke(_ context.Context, inv protocol.Invocation) protocol.Result { 149 rpcInv := inv.(*invocation.RPCInvocation) 150 mapV := inv.Attachments() 151 mapV["TestProxyInvoker"] = "TestProxyInvokerValue" 152 if err := hessian2.ReflectResponse(mapV, rpcInv.Reply()); err != nil { 153 fmt.Printf("hessian2.ReflectResponse(mapV:%v) = error:%v", mapV, err) 154 } 155 156 return &protocol.RPCResult{ 157 Rest: inv.Arguments(), 158 } 159 }