gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/grpc/pickfirst_test.go (about)

     1  /*
     2   *
     3   * Copyright 2017 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * 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  
    19  package grpc
    20  
    21  import (
    22  	"context"
    23  	"gitee.com/zhaochuninhefei/gmgo/grpc/credentials/insecure"
    24  	"math"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"gitee.com/zhaochuninhefei/gmgo/grpc/codes"
    30  	"gitee.com/zhaochuninhefei/gmgo/grpc/resolver"
    31  	"gitee.com/zhaochuninhefei/gmgo/grpc/resolver/manual"
    32  	"gitee.com/zhaochuninhefei/gmgo/grpc/status"
    33  )
    34  
    35  func errorDesc(err error) string {
    36  	if s, ok := status.FromError(err); ok {
    37  		return s.Message()
    38  	}
    39  	return err.Error()
    40  }
    41  
    42  func (s) TestOneBackendPickfirst(t *testing.T) {
    43  	r := manual.NewBuilderWithScheme("whatever")
    44  
    45  	numServers := 1
    46  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
    47  	defer scleanup()
    48  
    49  	cc, err := Dial(r.Scheme()+":///test.server",
    50  		// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
    51  		//WithInsecure(),
    52  		WithTransportCredentials(insecure.NewCredentials()),
    53  		WithResolvers(r),
    54  		// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
    55  		//WithCodec(testCodec{}))
    56  		WithDefaultCallOptions(ForceCodec(testCodec{})))
    57  	if err != nil {
    58  		t.Fatalf("failed to dial: %v", err)
    59  	}
    60  	defer func(cc *ClientConn) {
    61  		_ = cc.Close()
    62  	}(cc)
    63  	// The first RPC should fail because there's no address.
    64  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
    65  	defer cancel()
    66  	req := "port"
    67  	var reply string
    68  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
    69  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
    70  	}
    71  
    72  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}}})
    73  	// The second RPC should succeed.
    74  	for i := 0; i < 1000; i++ {
    75  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
    76  			return
    77  		}
    78  		time.Sleep(time.Millisecond)
    79  	}
    80  	t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port)
    81  }
    82  
    83  func (s) TestBackendsPickfirst(t *testing.T) {
    84  	r := manual.NewBuilderWithScheme("whatever")
    85  
    86  	numServers := 2
    87  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
    88  	defer scleanup()
    89  
    90  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
    91  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
    92  	//cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r), WithCodec(testCodec{}))
    93  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
    94  	if err != nil {
    95  		t.Fatalf("failed to dial: %v", err)
    96  	}
    97  	defer func(cc *ClientConn) {
    98  		_ = cc.Close()
    99  	}(cc)
   100  	// The first RPC should fail because there's no address.
   101  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   102  	defer cancel()
   103  	req := "port"
   104  	var reply string
   105  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   106  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   107  	}
   108  
   109  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}})
   110  	// The second RPC should succeed with the first server.
   111  	for i := 0; i < 1000; i++ {
   112  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
   113  			return
   114  		}
   115  		time.Sleep(time.Millisecond)
   116  	}
   117  	t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port)
   118  }
   119  
   120  func (s) TestNewAddressWhileBlockingPickfirst(t *testing.T) {
   121  	r := manual.NewBuilderWithScheme("whatever")
   122  
   123  	numServers := 1
   124  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
   125  	defer scleanup()
   126  
   127  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
   128  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
   129  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
   130  	if err != nil {
   131  		t.Fatalf("failed to dial: %v", err)
   132  	}
   133  	defer func(cc *ClientConn) {
   134  		_ = cc.Close()
   135  	}(cc)
   136  	// The first RPC should fail because there's no address.
   137  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   138  	defer cancel()
   139  	req := "port"
   140  	var reply string
   141  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   142  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   143  	}
   144  
   145  	var wg sync.WaitGroup
   146  	for i := 0; i < 3; i++ {
   147  		wg.Add(1)
   148  		go func() {
   149  			defer wg.Done()
   150  			// This RPC blocks until NewAddress is called.
   151  			_ = cc.Invoke(context.Background(), "/foo/bar", &req, &reply)
   152  		}()
   153  	}
   154  	time.Sleep(50 * time.Millisecond)
   155  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}}})
   156  	wg.Wait()
   157  }
   158  
   159  func (s) TestCloseWithPendingRPCPickfirst(t *testing.T) {
   160  	r := manual.NewBuilderWithScheme("whatever")
   161  
   162  	numServers := 1
   163  	_, scleanup := startServers(t, numServers, math.MaxInt32)
   164  	defer scleanup()
   165  
   166  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
   167  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
   168  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
   169  	if err != nil {
   170  		t.Fatalf("failed to dial: %v", err)
   171  	}
   172  	defer func(cc *ClientConn) {
   173  		_ = cc.Close()
   174  	}(cc)
   175  	// The first RPC should fail because there's no address.
   176  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   177  	defer cancel()
   178  	req := "port"
   179  	var reply string
   180  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   181  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   182  	}
   183  
   184  	var wg sync.WaitGroup
   185  	for i := 0; i < 3; i++ {
   186  		wg.Add(1)
   187  		go func() {
   188  			defer wg.Done()
   189  			// This RPC blocks until NewAddress is called.
   190  			_ = cc.Invoke(context.Background(), "/foo/bar", &req, &reply)
   191  		}()
   192  	}
   193  	time.Sleep(50 * time.Millisecond)
   194  	_ = cc.Close()
   195  	wg.Wait()
   196  }
   197  
   198  func (s) TestOneServerDownPickfirst(t *testing.T) {
   199  	r := manual.NewBuilderWithScheme("whatever")
   200  
   201  	numServers := 2
   202  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
   203  	defer scleanup()
   204  
   205  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
   206  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
   207  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
   208  	if err != nil {
   209  		t.Fatalf("failed to dial: %v", err)
   210  	}
   211  	defer func(cc *ClientConn) {
   212  		_ = cc.Close()
   213  	}(cc)
   214  	// The first RPC should fail because there's no address.
   215  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   216  	defer cancel()
   217  	req := "port"
   218  	var reply string
   219  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   220  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   221  	}
   222  
   223  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}})
   224  	// The second RPC should succeed with the first server.
   225  	for i := 0; i < 1000; i++ {
   226  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
   227  			break
   228  		}
   229  		time.Sleep(time.Millisecond)
   230  	}
   231  
   232  	servers[0].stop()
   233  	for i := 0; i < 1000; i++ {
   234  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port {
   235  			return
   236  		}
   237  		time.Sleep(time.Millisecond)
   238  	}
   239  	t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port)
   240  }
   241  
   242  func (s) TestAllServersDownPickfirst(t *testing.T) {
   243  	r := manual.NewBuilderWithScheme("whatever")
   244  
   245  	numServers := 2
   246  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
   247  	defer scleanup()
   248  
   249  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
   250  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
   251  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
   252  	if err != nil {
   253  		t.Fatalf("failed to dial: %v", err)
   254  	}
   255  	defer func(cc *ClientConn) {
   256  		_ = cc.Close()
   257  	}(cc)
   258  	// The first RPC should fail because there's no address.
   259  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   260  	defer cancel()
   261  	req := "port"
   262  	var reply string
   263  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   264  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   265  	}
   266  
   267  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}})
   268  	// The second RPC should succeed with the first server.
   269  	for i := 0; i < 1000; i++ {
   270  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
   271  			break
   272  		}
   273  		time.Sleep(time.Millisecond)
   274  	}
   275  
   276  	for i := 0; i < numServers; i++ {
   277  		servers[i].stop()
   278  	}
   279  	for i := 0; i < 1000; i++ {
   280  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); status.Code(err) == codes.Unavailable {
   281  			return
   282  		}
   283  		time.Sleep(time.Millisecond)
   284  	}
   285  	t.Fatalf("EmptyCall() = _, %v, want _, error with code unavailable", err)
   286  }
   287  
   288  func (s) TestAddressesRemovedPickfirst(t *testing.T) {
   289  	r := manual.NewBuilderWithScheme("whatever")
   290  
   291  	numServers := 3
   292  	servers, scleanup := startServers(t, numServers, math.MaxInt32)
   293  	defer scleanup()
   294  
   295  	// WithInsecure() is deprecated, use WithTransportCredentials and insecure.NewCredentials() instead.
   296  	// WithCodec() is deprecated, use WithDefaultCallOptions(ForceCodec(_)) instead.
   297  	cc, err := Dial(r.Scheme()+":///test.server", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r), WithDefaultCallOptions(ForceCodec(testCodec{})))
   298  	if err != nil {
   299  		t.Fatalf("failed to dial: %v", err)
   300  	}
   301  	defer func(cc *ClientConn) {
   302  		_ = cc.Close()
   303  	}(cc)
   304  	// The first RPC should fail because there's no address.
   305  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   306  	defer cancel()
   307  	req := "port"
   308  	var reply string
   309  	if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded {
   310  		t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err)
   311  	}
   312  
   313  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}, {Addr: servers[2].addr}}})
   314  	for i := 0; i < 1000; i++ {
   315  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
   316  			break
   317  		}
   318  		time.Sleep(time.Millisecond)
   319  	}
   320  	for i := 0; i < 20; i++ {
   321  		if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port {
   322  			t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port)
   323  		}
   324  		time.Sleep(10 * time.Millisecond)
   325  	}
   326  
   327  	// Remove server[0].
   328  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[1].addr}, {Addr: servers[2].addr}}})
   329  	for i := 0; i < 1000; i++ {
   330  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port {
   331  			break
   332  		}
   333  		time.Sleep(time.Millisecond)
   334  	}
   335  	for i := 0; i < 20; i++ {
   336  		if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port {
   337  			t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port)
   338  		}
   339  		time.Sleep(10 * time.Millisecond)
   340  	}
   341  
   342  	// Append server[0], nothing should change.
   343  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[1].addr}, {Addr: servers[2].addr}, {Addr: servers[0].addr}}})
   344  	for i := 0; i < 20; i++ {
   345  		if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port {
   346  			t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port)
   347  		}
   348  		time.Sleep(10 * time.Millisecond)
   349  	}
   350  
   351  	// Remove server[1].
   352  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[2].addr}, {Addr: servers[0].addr}}})
   353  	for i := 0; i < 1000; i++ {
   354  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[2].port {
   355  			break
   356  		}
   357  		time.Sleep(time.Millisecond)
   358  	}
   359  	for i := 0; i < 20; i++ {
   360  		if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[2].port {
   361  			t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 2, err, servers[2].port)
   362  		}
   363  		time.Sleep(10 * time.Millisecond)
   364  	}
   365  
   366  	// Remove server[2].
   367  	r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: servers[0].addr}}})
   368  	for i := 0; i < 1000; i++ {
   369  		if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port {
   370  			break
   371  		}
   372  		time.Sleep(time.Millisecond)
   373  	}
   374  	for i := 0; i < 20; i++ {
   375  		if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port {
   376  			t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port)
   377  		}
   378  		time.Sleep(10 * time.Millisecond)
   379  	}
   380  }