From b15f6bf9787fba23ffa5c30213c7a2842a79200a Mon Sep 17 00:00:00 2001 From: Wei Fu Date: Wed, 5 Oct 2022 22:55:12 +0800 Subject: [PATCH] integration: deflaking TestMaintenanceSnapshotCancel/Timeout Since http2 spec defines the receive windows's size and max size of frame in the stream, the underlayer - gRPC client can pre-read data from server even if the application layer hasn't read it yet. And the initialized cluster has 20KiB snapshot, which can be pre-read by underlayer. We should increase the snapshot's size, just in case that the io.Copy won't return the canceled or timeout error. Fixes: #14477 Signed-off-by: Wei Fu --- .../integration/clientv3/maintenance_test.go | 22 ++++++++++++++++++- tests/integration/clientv3/util.go | 19 +++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/integration/clientv3/maintenance_test.go b/tests/integration/clientv3/maintenance_test.go index a6290823f..9a067f3f8 100644 --- a/tests/integration/clientv3/maintenance_test.go +++ b/tests/integration/clientv3/maintenance_test.go @@ -31,7 +31,7 @@ import ( "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/api/v3/version" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/server/v3/lease" "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/mvcc" @@ -156,6 +156,16 @@ func TestMaintenanceSnapshotCancel(t *testing.T) { // reading snapshot with canceled context should error out ctx, cancel := context.WithCancel(context.Background()) + + // Since http2 spec defines the receive windows's size and max size of + // frame in the stream, the underlayer - gRPC client can pre-read data + // from server even if the application layer hasn't read it yet. + // + // And the initialized cluster has 20KiB snapshot, which can be + // pre-read by underlayer. We should increase the snapshot's size here, + // just in case that io.Copy won't return the canceled error. + populateDataIntoCluster(t, clus, 3, 1024*1024) + rc1, err := clus.RandClient().Snapshot(ctx) if err != nil { t.Fatal(err) @@ -200,6 +210,16 @@ func testMaintenanceSnapshotTimeout(t *testing.T, snapshot func(context.Context, // reading snapshot with deadline exceeded should error out ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() + + // Since http2 spec defines the receive windows's size and max size of + // frame in the stream, the underlayer - gRPC client can pre-read data + // from server even if the application layer hasn't read it yet. + // + // And the initialized cluster has 20KiB snapshot, which can be + // pre-read by underlayer. We should increase the snapshot's size here, + // just in case that io.Copy won't return the timeout error. + populateDataIntoCluster(t, clus, 3, 1024*1024) + rc2, err := snapshot(ctx, clus.RandClient()) if err != nil { t.Fatal(err) diff --git a/tests/integration/clientv3/util.go b/tests/integration/clientv3/util.go index 26ee793c9..63b377e31 100644 --- a/tests/integration/clientv3/util.go +++ b/tests/integration/clientv3/util.go @@ -16,11 +16,13 @@ package clientv3test import ( "context" + "fmt" "strings" "testing" "time" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" + integration2 "go.etcd.io/etcd/tests/v3/framework/integration" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -101,3 +103,18 @@ func IsUnavailable(err error) bool { code := ev.Code() return code == codes.Unavailable } + +// populateDataIntoCluster populates the key-value pairs into cluster and the +// key will be named by testing.T.Name()-index. +func populateDataIntoCluster(t *testing.T, cluster *integration2.Cluster, numKeys int, valueSize int) { + ctx := context.Background() + + for i := 0; i < numKeys; i++ { + _, err := cluster.RandClient().Put(ctx, + fmt.Sprintf("%s-%v", t.Name(), i), strings.Repeat("a", valueSize)) + + if err != nil { + t.Errorf("populating data expected no error, but got %v", err) + } + } +}