github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/integration/v3_grpc_inflight_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 integration 16 17 import ( 18 "context" 19 "sync" 20 "testing" 21 "time" 22 23 pb "github.com/lfch/etcd-io/api/v3/etcdserverpb" 24 "github.com/lfch/etcd-io/api/v3/v3rpc/rpctypes" 25 "github.com/lfch/etcd-io/tests/v3/framework/integration" 26 "google.golang.org/grpc" 27 "google.golang.org/grpc/codes" 28 "google.golang.org/grpc/status" 29 ) 30 31 // TestV3MaintenanceDefragmentInflightRange ensures inflight range requests 32 // does not panic the mvcc backend while defragment is running. 33 func TestV3MaintenanceDefragmentInflightRange(t *testing.T) { 34 integration.BeforeTest(t) 35 clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) 36 defer clus.Terminate(t) 37 38 cli := clus.RandClient() 39 kvc := integration.ToGRPC(cli).KV 40 if _, err := kvc.Put(context.Background(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")}); err != nil { 41 t.Fatal(err) 42 } 43 44 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 45 46 donec := make(chan struct{}) 47 go func() { 48 defer close(donec) 49 kvc.Range(ctx, &pb.RangeRequest{Key: []byte("foo")}) 50 }() 51 52 mvc := integration.ToGRPC(cli).Maintenance 53 mvc.Defragment(context.Background(), &pb.DefragmentRequest{}) 54 cancel() 55 56 <-donec 57 } 58 59 // TestV3KVInflightRangeRequests ensures that inflight requests 60 // (sent before server shutdown) are gracefully handled by server-side. 61 // They are either finished or canceled, but never crash the backend. 62 // See https://github.com/etcd-io/etcd/issues/7322 for more detail. 63 func TestV3KVInflightRangeRequests(t *testing.T) { 64 integration.BeforeTest(t) 65 clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) 66 defer clus.Terminate(t) 67 68 cli := clus.RandClient() 69 kvc := integration.ToGRPC(cli).KV 70 71 if _, err := kvc.Put(context.Background(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")}); err != nil { 72 t.Fatal(err) 73 } 74 75 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 76 77 reqN := 10 // use 500+ for fast machine 78 var wg sync.WaitGroup 79 wg.Add(reqN) 80 for i := 0; i < reqN; i++ { 81 go func() { 82 defer wg.Done() 83 _, err := kvc.Range(ctx, &pb.RangeRequest{Key: []byte("foo"), Serializable: true}, grpc.WaitForReady(true)) 84 if err != nil { 85 errCode := status.Convert(err).Code() 86 errDesc := rpctypes.ErrorDesc(err) 87 if err != nil && !(errDesc == context.Canceled.Error() || errCode == codes.Canceled || errCode == codes.Unavailable) { 88 t.Errorf("inflight request should be canceled with '%v' or code Canceled or Unavailable, got '%v' with code '%s'", context.Canceled.Error(), errDesc, errCode) 89 } 90 } 91 }() 92 } 93 94 clus.Members[0].Stop(t) 95 cancel() 96 97 wg.Wait() 98 }