From f5eadf5452d35115bc8568cb1f6170d14d74aa5d Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 7 Jun 2022 17:08:03 +0200 Subject: [PATCH] tests: Add tests for HashByRev HTTP API Signed-off-by: Marek Siarkowicz --- server/etcdserver/corrupt.go | 8 +-- tests/integration/hashkv_test.go | 109 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 tests/integration/hashkv_test.go diff --git a/server/etcdserver/corrupt.go b/server/etcdserver/corrupt.go index f1659e1ff..152cb0a91 100644 --- a/server/etcdserver/corrupt.go +++ b/server/etcdserver/corrupt.go @@ -277,6 +277,7 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { lg := s.Logger() + cc := &http.Client{Transport: s.peerRt} var resps []*peerHashKVResp for _, p := range peers { if len(p.eps) == 0 { @@ -287,7 +288,7 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { var lastErr error for _, ep := range p.eps { ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout()) - resp, lastErr := s.getPeerHashKVHTTP(ctx, ep, rev) + resp, lastErr := HashByRev(ctx, cc, ep, rev) cancel() if lastErr == nil { resps = append(resps, &peerHashKVResp{peerInfo: p, resp: resp, err: nil}) @@ -368,9 +369,8 @@ func (h *hashKVHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write(respBytes) } -// getPeerHashKVHTTP fetch hash of kv store at the given rev via http call to the given url -func (s *EtcdServer) getPeerHashKVHTTP(ctx context.Context, url string, rev int64) (*pb.HashKVResponse, error) { - cc := &http.Client{Transport: s.peerRt} +// HashByRev fetch hash of kv store at the given rev via http call to the given url +func HashByRev(ctx context.Context, cc *http.Client, url string, rev int64) (*pb.HashKVResponse, error) { hashReq := &pb.HashKVRequest{Revision: rev} hashReqBytes, err := json.Marshal(hashReq) if err != nil { diff --git a/tests/integration/hashkv_test.go b/tests/integration/hashkv_test.go new file mode 100644 index 000000000..f67a0d89c --- /dev/null +++ b/tests/integration/hashkv_test.go @@ -0,0 +1,109 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package integration + +import ( + "context" + "fmt" + "net" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/server/v3/etcdserver" + integration2 "go.etcd.io/etcd/tests/v3/framework/integration" +) + +const ( + // Use high prime + compactionCycle = 71 +) + +func TestCompactionHashHTTP(t *testing.T) { + integration2.BeforeTest(t) + + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + ctx := context.Background() + cc, err := clus.ClusterClient() + if err != nil { + t.Fatal(err) + } + + var totalRevisions int64 = 1210 + assert.Less(t, int64(1000), totalRevisions) + assert.Less(t, int64(compactionCycle*10), totalRevisions) + var rev int64 + client := &http.Client{ + Transport: &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", clus.Members[0].PeerURLs[0].Host) + }, + }, + } + for ; rev < totalRevisions; rev += compactionCycle { + testCompactionHash(ctx, t, cc, client, rev, rev+compactionCycle) + } + testCompactionHash(ctx, t, cc, client, rev, rev+totalRevisions) +} + +func testCompactionHash(ctx context.Context, t *testing.T, cc *clientv3.Client, client *http.Client, start, stop int64) { + for i := start; i <= stop; i++ { + cc.Put(ctx, pickKey(i), fmt.Sprint(i)) + } + hash1, err := etcdserver.HashByRev(ctx, client, "http://unix", stop) + assert.NoError(t, err, "error on rev %v", stop) + + _, err = cc.Compact(ctx, stop) + assert.NoError(t, err, "error on compact rev %v", stop) + + // Wait for compaction to be compacted + time.Sleep(50 * time.Millisecond) + + hash2, err := etcdserver.HashByRev(ctx, client, "http://unix", stop) + assert.NoError(t, err, "error on rev %v", stop) + assert.Equal(t, hash1, hash2, "hashes do not match on rev %v", stop) +} + +func pickKey(i int64) string { + if i%(compactionCycle*2) == 30 { + return "zenek" + } + if i%compactionCycle == 30 { + return "xavery" + } + // Use low prime number to ensure repeats without alignment + switch i % 7 { + case 0: + return "alice" + case 1: + return "bob" + case 2: + return "celine" + case 3: + return "dominik" + case 4: + return "eve" + case 5: + return "frederica" + case 6: + return "gorge" + default: + panic("Can't count") + } +}