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