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  }