go.etcd.io/etcd@v3.3.27+incompatible/clientv3/client_test.go (about) 1 // Copyright 2016 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package clientv3 16 17 import ( 18 "context" 19 "fmt" 20 "net" 21 "testing" 22 "time" 23 24 "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" 25 "github.com/coreos/etcd/pkg/testutil" 26 "google.golang.org/grpc" 27 ) 28 29 func TestDialCancel(t *testing.T) { 30 defer testutil.AfterTest(t) 31 32 // accept first connection so client is created with dial timeout 33 ln, err := net.Listen("unix", "dialcancel:12345") 34 if err != nil { 35 t.Fatal(err) 36 } 37 defer ln.Close() 38 39 ep := "unix://dialcancel:12345" 40 cfg := Config{ 41 Endpoints: []string{ep}, 42 DialTimeout: 30 * time.Second} 43 c, err := New(cfg) 44 if err != nil { 45 t.Fatal(err) 46 } 47 48 // connect to ipv4 black hole so dial blocks 49 c.SetEndpoints("http://254.0.0.1:12345") 50 51 // issue Get to force redial attempts 52 getc := make(chan struct{}) 53 go func() { 54 defer close(getc) 55 // Get may hang forever on grpc's Stream.Header() if its 56 // context is never canceled. 57 c.Get(c.Ctx(), "abc") 58 }() 59 60 // wait a little bit so client close is after dial starts 61 time.Sleep(100 * time.Millisecond) 62 63 donec := make(chan struct{}) 64 go func() { 65 defer close(donec) 66 c.Close() 67 }() 68 69 select { 70 case <-time.After(5 * time.Second): 71 t.Fatalf("failed to close") 72 case <-donec: 73 } 74 select { 75 case <-time.After(5 * time.Second): 76 t.Fatalf("get failed to exit") 77 case <-getc: 78 } 79 } 80 81 func TestDialTimeout(t *testing.T) { 82 defer testutil.AfterTest(t) 83 84 testCfgs := []Config{ 85 { 86 Endpoints: []string{"http://254.0.0.1:12345"}, 87 DialOptions: []grpc.DialOption{grpc.WithBlock()}, 88 DialTimeout: 2 * time.Second, 89 }, 90 { 91 Endpoints: []string{"http://254.0.0.1:12345"}, 92 DialTimeout: time.Second, 93 DialOptions: []grpc.DialOption{grpc.WithBlock()}, 94 Username: "abc", 95 Password: "def", 96 }, 97 } 98 99 for i, cfg := range testCfgs { 100 donec := make(chan error) 101 go func() { 102 // without timeout, dial continues forever on ipv4 black hole 103 c, err := New(cfg) 104 if c != nil || err == nil { 105 t.Errorf("#%d: new client should fail", i) 106 } 107 donec <- err 108 }() 109 110 time.Sleep(10 * time.Millisecond) 111 112 select { 113 case err := <-donec: 114 t.Errorf("#%d: dial didn't wait (%v)", i, err) 115 default: 116 } 117 118 select { 119 case <-time.After(5 * time.Second): 120 t.Errorf("#%d: failed to timeout dial on time", i) 121 case err := <-donec: 122 if err != context.DeadlineExceeded { 123 t.Errorf("#%d: unexpected error %v, want %v", i, err, context.DeadlineExceeded) 124 } 125 } 126 } 127 } 128 129 func TestDialNoTimeout(t *testing.T) { 130 cfg := Config{Endpoints: []string{"127.0.0.1:12345"}} 131 c, err := New(cfg) 132 if c == nil || err != nil { 133 t.Fatalf("new client with DialNoWait should succeed, got %v", err) 134 } 135 c.Close() 136 } 137 138 func TestIsHaltErr(t *testing.T) { 139 if !isHaltErr(nil, fmt.Errorf("etcdserver: some etcdserver error")) { 140 t.Errorf(`error prefixed with "etcdserver: " should be Halted by default`) 141 } 142 if isHaltErr(nil, rpctypes.ErrGRPCStopped) { 143 t.Errorf("error %v should not halt", rpctypes.ErrGRPCStopped) 144 } 145 if isHaltErr(nil, rpctypes.ErrGRPCNoLeader) { 146 t.Errorf("error %v should not halt", rpctypes.ErrGRPCNoLeader) 147 } 148 ctx, cancel := context.WithCancel(context.TODO()) 149 if isHaltErr(ctx, nil) { 150 t.Errorf("no error and active context should not be Halted") 151 } 152 cancel() 153 if !isHaltErr(ctx, nil) { 154 t.Errorf("cancel on context should be Halted") 155 } 156 }