tests: Add tests for HashByRev HTTP API

Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
dependabot/go_modules/go.uber.org/atomic-1.10.0
Marek Siarkowicz 2022-06-07 17:08:03 +02:00
parent 1581eef888
commit f5eadf5452
2 changed files with 113 additions and 4 deletions

View File

@ -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 {

View File

@ -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")
}
}