diff --git a/clientv3/integration/kv_test.go b/clientv3/integration/kv_test.go index 712b64347..e28a1cdd3 100644 --- a/clientv3/integration/kv_test.go +++ b/clientv3/integration/kv_test.go @@ -648,16 +648,47 @@ func TestKVGetCancel(t *testing.T) { } } -// TestKVPutStoppedServerAndClose ensures closing after a failed Put works. -func TestKVPutStoppedServerAndClose(t *testing.T) { +// TestKVGetStoppedServerAndClose ensures closing after a failed Get works. +func TestKVGetStoppedServerAndClose(t *testing.T) { defer testutil.AfterTest(t) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) + cli := clus.Client(0) clus.Members[0].Stop(t) ctx, cancel := context.WithTimeout(context.TODO(), time.Second) + // this Get fails and triggers an asynchronous connection retry + _, err := cli.Get(ctx, "abc") + cancel() + if !strings.Contains(err.Error(), "context deadline") { + t.Fatal(err) + } +} + +// TestKVPutStoppedServerAndClose ensures closing after a failed Put works. +func TestKVPutStoppedServerAndClose(t *testing.T) { + defer testutil.AfterTest(t) + + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + cli := clus.Client(0) + clus.Members[0].Stop(t) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Second) + // get retries on all errors. + // so here we use it to eat the potential broken pipe error for the next put. + // grpc client might see a broken pipe error when we issue the get request before + // grpc finds out the original connection is down due to the member shutdown. + _, err := cli.Get(ctx, "abc") + cancel() + if !strings.Contains(err.Error(), "context deadline") { + t.Fatal(err) + } + // this Put fails and triggers an asynchronous connection retry - _, err := cli.Put(ctx, "abc", "123") + _, err = cli.Put(ctx, "abc", "123") cancel() if !strings.Contains(err.Error(), "context deadline") { t.Fatal(err)