trpc.group/trpc-go/trpc-go@v1.0.3/client/config_test.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package client_test
    15  
    16  import (
    17  	"context"
    18  	"errors"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  	yaml "gopkg.in/yaml.v3"
    25  
    26  	trpc "trpc.group/trpc-go/trpc-go"
    27  	"trpc.group/trpc-go/trpc-go/client"
    28  	"trpc.group/trpc-go/trpc-go/codec"
    29  	"trpc.group/trpc-go/trpc-go/filter"
    30  	"trpc.group/trpc-go/trpc-go/internal/rand"
    31  	"trpc.group/trpc-go/trpc-go/naming/registry"
    32  	"trpc.group/trpc-go/trpc-go/naming/selector"
    33  	"trpc.group/trpc-go/trpc-go/transport"
    34  )
    35  
    36  func TestConfigOptions(t *testing.T) {
    37  	clientOpts := &client.Options{}
    38  	transportOpts := &transport.RoundTripOptions{}
    39  
    40  	node := &registry.Node{
    41  		Address:  "127.0.0.1:8080",
    42  		Network:  "udp",
    43  		Protocol: "trpc",
    44  	}
    45  	clientOpts.LoadNodeConfig(node)
    46  	for _, o := range clientOpts.CallOptions {
    47  		o(transportOpts)
    48  	}
    49  	assert.Equal(t, "127.0.0.1:8080", transportOpts.Address)
    50  	assert.Equal(t, "udp", transportOpts.Network)
    51  	assert.Equal(t, trpc.DefaultClientCodec, clientOpts.Codec)
    52  
    53  	filter.Register("Monitoring", filter.NoopServerFilter, filter.NoopClientFilter)
    54  	filter.Register("Authentication", filter.NoopServerFilter, filter.NoopClientFilter)
    55  }
    56  
    57  func TestConfigNoDiscovery(t *testing.T) {
    58  	backconfig := &client.BackendConfig{
    59  		ServiceName: "trpc.test.helloworld3", // backend service name
    60  		Namespace:   "Development",
    61  		Discovery:   "no-exists",
    62  		Network:     "tcp",
    63  		Timeout:     1000,
    64  		Protocol:    "trpc",
    65  		Filter:      []string{"Monitoring", "Authentication"},
    66  	}
    67  	err := client.RegisterClientConfig("trpc.test.nodiscovery", backconfig)
    68  	assert.NotNil(t, err)
    69  }
    70  
    71  func TestConfigNoServiceRouter(t *testing.T) {
    72  	backconfig := &client.BackendConfig{
    73  		ServiceName:   "trpc.test.helloworld3", // backend service name
    74  		Namespace:     "Development",
    75  		ServiceRouter: "no-exists",
    76  		Network:       "tcp",
    77  		Timeout:       1000,
    78  		Protocol:      "trpc",
    79  		Filter:        []string{"Monitoring", "Authentication"},
    80  	}
    81  	err := client.RegisterClientConfig("trpc.test.noservicerouter", backconfig)
    82  	assert.NotNil(t, err)
    83  }
    84  
    85  func TestConfigNoBalance(t *testing.T) {
    86  	backconfig := &client.BackendConfig{
    87  		ServiceName: "trpc.test.helloworld3", // backend service name
    88  		Namespace:   "Development",
    89  		Loadbalance: "no-exists",
    90  		Network:     "tcp",
    91  		Timeout:     1000,
    92  		Protocol:    "trpc",
    93  		Filter:      []string{"Monitoring", "Authentication"},
    94  	}
    95  	err := client.RegisterClientConfig("trpc.test.nobalance", backconfig)
    96  	assert.NotNil(t, err)
    97  }
    98  
    99  type testOptionsSelector struct {
   100  	f func(*selector.Options)
   101  }
   102  
   103  var testOptionsSelectorError = errors.New("test options selector error")
   104  
   105  func (s *testOptionsSelector) Select(serviceName string, opt ...selector.Option) (*registry.Node, error) {
   106  	opts := &selector.Options{}
   107  	for _, o := range opt {
   108  		o(opts)
   109  	}
   110  	s.f(opts)
   111  	return nil, testOptionsSelectorError
   112  }
   113  
   114  func (s *testOptionsSelector) Report(node *registry.Node, cost time.Duration, err error) error {
   115  	return nil
   116  }
   117  
   118  func TestConfigCalleeMetadata(t *testing.T) {
   119  	ctx := context.Background()
   120  	reqBody := codec.Body{}
   121  	rspBody := codec.Body{}
   122  	calleeMetadata := map[string]string{
   123  		"key1": "val1",
   124  		"key2": "val2",
   125  	}
   126  	backconfig := &client.BackendConfig{
   127  		ServiceName:    "trpc.test.helloworld3", // backend service name
   128  		Namespace:      "Development",
   129  		Network:        "tcp",
   130  		Timeout:        1000,
   131  		Protocol:       "trpc",
   132  		CalleeMetadata: calleeMetadata,
   133  	}
   134  	err := client.RegisterClientConfig("trpc.test.client.metadata", backconfig)
   135  	assert.Nil(t, err)
   136  
   137  	s := &testOptionsSelector{
   138  		f: func(opts *selector.Options) {
   139  			assert.Equal(t, calleeMetadata, opts.DestinationMetadata)
   140  		},
   141  	}
   142  	selector.Register("test-options-selector", s)
   143  	cli := client.New()
   144  	assert.Equal(t, cli, client.DefaultClient)
   145  	ctx, msg := codec.WithNewMessage(ctx)
   146  	msg.WithCalleeServiceName("trpc.test.client.metadata")
   147  	err = cli.Invoke(ctx, reqBody, rspBody,
   148  		client.WithTarget("test-options-selector://trpc.test.client.metadata"),
   149  	)
   150  	require.Contains(t, err.Error(), testOptionsSelectorError.Error())
   151  }
   152  
   153  func TestConfigNoBreaker(t *testing.T) {
   154  	backconfig := &client.BackendConfig{
   155  		ServiceName:    "trpc.test.helloworld3", // backend service name
   156  		Namespace:      "Development",
   157  		Circuitbreaker: "no-exists",
   158  		Network:        "tcp",
   159  		Timeout:        1000,
   160  		Protocol:       "trpc",
   161  		Filter:         []string{"Monitoring", "Authentication"},
   162  	}
   163  	err := client.RegisterClientConfig("trpc.test.nobreaker", backconfig)
   164  	assert.NotNil(t, err)
   165  }
   166  
   167  func TestConfigNoFilter(t *testing.T) {
   168  	backconfig := &client.BackendConfig{
   169  		ServiceName: "trpc.test.helloworld3", // backend service name
   170  		Namespace:   "Development",
   171  		Network:     "tcp",
   172  		Timeout:     1000,
   173  		Protocol:    "trpc",
   174  		Filter:      []string{"Monitoring", "no-exists"},
   175  	}
   176  	err := client.RegisterClientConfig("trpc.test.nofilter", backconfig)
   177  	assert.NotNil(t, err)
   178  }
   179  
   180  func TestConfigFilter(t *testing.T) {
   181  	backconfig := &client.BackendConfig{
   182  		ServiceName: "trpc.test.helloworld3", // backend service name
   183  		Namespace:   "Development",
   184  		Network:     "tcp",
   185  		Timeout:     1000,
   186  		Protocol:    "trpc",
   187  		Filter:      []string{"Monitoring"},
   188  	}
   189  	filter.Register("Monitoring", nil, filter.NoopClientFilter)
   190  	err := client.RegisterClientConfig("trpc.test.filter", backconfig)
   191  	assert.Nil(t, err)
   192  }
   193  
   194  func TestLoadClientFilterConfigSelectorFilter(t *testing.T) {
   195  	const callee = "test_selector_filter"
   196  	require.Nil(t, client.RegisterClientConfig(callee, &client.BackendConfig{
   197  		Filter: []string{client.DefaultSelectorFilterName},
   198  	}))
   199  }
   200  
   201  func TestRegisterConfigParallel(t *testing.T) {
   202  	safeRand := rand.NewSafeRand(time.Now().UnixNano())
   203  	for i := 0; i < safeRand.Intn(100); i++ {
   204  		t.Run("Parallel", func(t *testing.T) {
   205  			t.Parallel()
   206  			backconfig := &client.BackendConfig{
   207  				ServiceName: "trpc.test.helloworld1", // backend service name
   208  				Target:      "ip://1.1.1.1:2222",     // backend address
   209  				Network:     "tcp",
   210  				Timeout:     1000,
   211  				Protocol:    "trpc",
   212  			}
   213  			conf := map[string]*client.BackendConfig{
   214  				"trpc.test.helloworld": backconfig,
   215  			}
   216  			err := client.RegisterConfig(conf)
   217  			assert.Nil(t, err)
   218  			assert.Equal(t, client.DefaultClientConfig(), conf)
   219  		})
   220  	}
   221  }
   222  
   223  func TestLoadClientConfig(t *testing.T) {
   224  	err := client.LoadClientConfig("../testdata/trpc_go.yaml")
   225  	assert.Nil(t, err)
   226  }
   227  
   228  type testTransport struct{}
   229  
   230  func (t *testTransport) RoundTrip(ctx context.Context, req []byte,
   231  	opts ...transport.RoundTripOption) ([]byte, error) {
   232  	return nil, nil
   233  }
   234  
   235  func TestConfigTransport(t *testing.T) {
   236  	t.Run("Client Config", func(t *testing.T) {
   237  		tr := &testTransport{}
   238  		transport.RegisterClientTransport("test-transport", tr)
   239  		var cfg client.BackendConfig
   240  		require.Nil(t, yaml.Unmarshal([]byte(`
   241  transport: test-transport
   242  `), &cfg))
   243  		require.Equal(t, "test-transport", cfg.Transport)
   244  		require.Nil(t, client.RegisterClientConfig("trpc.test.hello", &cfg))
   245  	})
   246  }
   247  
   248  func TestConfigStreamFilter(t *testing.T) {
   249  	filterName := "sf1"
   250  	cfg := &client.BackendConfig{}
   251  	require.Nil(t, yaml.Unmarshal([]byte(`
   252  stream_filter:
   253  - sf1
   254  `), cfg))
   255  	require.Equal(t, filterName, cfg.StreamFilter[0])
   256  	// return error if stream filter no registered
   257  	err := client.RegisterClientConfig("trpc.test.hello", cfg)
   258  	assert.NotNil(t, err)
   259  
   260  	client.RegisterStreamFilter("sf1", func(ctx context.Context, desc *client.ClientStreamDesc,
   261  		streamer client.Streamer) (client.ClientStream, error) {
   262  		return nil, nil
   263  	})
   264  	require.Nil(t, client.RegisterClientConfig("trpc.test.hello", cfg))
   265  }
   266  
   267  func TestConfig(t *testing.T) {
   268  	require.Nil(t, client.RegisterConfig(make(map[string]*client.BackendConfig)))
   269  	c := client.Config("empty")
   270  	assert.Equal(t, "", c.ServiceName)
   271  	assert.Equal(t, "tcp", c.Network)
   272  	assert.Equal(t, "trpc", c.Protocol)
   273  
   274  	backconfig := &client.BackendConfig{
   275  		ServiceName: "trpc.test.helloworld1", // backend service name
   276  		Target:      "ip://1.1.1.1:2222",     // backend address
   277  		Network:     "tcp",
   278  		Timeout:     1000,
   279  		Protocol:    "trpc",
   280  	}
   281  	conf := map[string]*client.BackendConfig{
   282  		"trpc.test.helloworld": backconfig,
   283  	}
   284  
   285  	err := client.RegisterConfig(conf)
   286  	assert.Nil(t, err)
   287  	assert.Equal(t, client.DefaultClientConfig(), conf)
   288  
   289  	require.Nil(t, client.RegisterClientConfig("trpc.test.helloworld2", backconfig))
   290  	assert.Equal(t, "trpc.test.helloworld1", client.Config("trpc.test.helloworld2").ServiceName)
   291  
   292  	c = client.Config("no-exist")
   293  	assert.Equal(t, "", c.ServiceName)
   294  	assert.Equal(t, "tcp", c.Network)
   295  	assert.Equal(t, "trpc", c.Protocol)
   296  
   297  	c = client.Config("trpc.test.helloworld")
   298  	assert.Equal(t, "trpc.test.helloworld1", c.ServiceName)
   299  	assert.Equal(t, "tcp", c.Network)
   300  	assert.Equal(t, "ip://1.1.1.1:2222", c.Target)
   301  	assert.Equal(t, 1000, c.Timeout)
   302  	assert.Equal(t, "trpc", c.Protocol)
   303  
   304  	backconfig = &client.BackendConfig{
   305  		ServiceName: "trpc.test.helloworld1", // backend service name
   306  		Network:     "tcp",
   307  		Timeout:     1000,
   308  		Protocol:    "trpc",
   309  		Compression: 1,
   310  		Password:    "xxx",
   311  		CACert:      "xxx",
   312  	}
   313  	require.Nil(t, client.RegisterClientConfig("trpc.test.helloworld3", backconfig))
   314  }
   315  
   316  func TestRegisterWildcardClient(t *testing.T) {
   317  	cfg := client.Config("*")
   318  	t.Cleanup(func() {
   319  		client.RegisterClientConfig("*", cfg)
   320  	})
   321  	client.RegisterClientConfig("*", &client.BackendConfig{
   322  		DisableServiceRouter: true,
   323  	})
   324  
   325  	ch := make(chan *client.Options, 1)
   326  	c := client.New()
   327  	ctx, _ := codec.EnsureMessage(context.Background())
   328  	require.Nil(t, c.Invoke(ctx, nil, nil, client.WithFilter(
   329  		func(ctx context.Context, _, _ interface{}, _ filter.ClientHandleFunc) error {
   330  			ch <- client.OptionsFromContext(ctx)
   331  			// Skip next.
   332  			return nil
   333  		})))
   334  	opts := <-ch
   335  	require.True(t, opts.DisableServiceRouter)
   336  }