-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathslowvoter_test.go
102 lines (87 loc) · 2.46 KB
/
slowvoter_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fuzzy
import (
"math/rand"
"testing"
"time"
"github.com/hashicorp/raft"
)
// 5 node cluster where 2 nodes always see a delay in getting a request vote msg.
func TestRaft_SlowSendVote(t *testing.T) {
hooks := NewSlowVoter("sv_0", "sv_1")
cluster := newRaftCluster(t, testLogWriter, "sv", 5, hooks)
s := newApplySource("SlowSendVote")
ac := cluster.ApplyN(t, time.Minute, s, 10000)
cluster.Stop(t, time.Minute)
hooks.Report(t)
cluster.VerifyLog(t, ac)
cluster.VerifyFSM(t)
}
// 5 node cluster where vote results from 3 nodes are slow to turn up.
// [they see the vote request normally, but their response is slow]
func TestRaft_SlowRecvVote(t *testing.T) {
hooks := NewSlowVoter("svr_1", "svr_4", "svr_3")
hooks.mode = SlowRecv
cluster := newRaftCluster(t, testLogWriter, "svr", 5, hooks)
s := newApplySource("SlowRecvVote")
ac := cluster.ApplyN(t, time.Minute, s, 10000)
cluster.Stop(t, time.Minute)
hooks.Report(t)
cluster.VerifyLog(t, ac)
cluster.VerifyFSM(t)
}
type SlowVoterMode int
const (
SlowSend SlowVoterMode = iota
SlowRecv
)
type SlowVoter struct {
verifier appendEntriesVerifier
slowNodes map[string]bool
delayMin time.Duration
delayMax time.Duration
mode SlowVoterMode
}
func NewSlowVoter(slowNodes ...string) *SlowVoter {
sv := SlowVoter{
slowNodes: make(map[string]bool, len(slowNodes)),
delayMin: time.Second,
delayMax: time.Second * 2,
mode: SlowSend,
}
for _, n := range slowNodes {
sv.slowNodes[n] = true
}
sv.verifier.Init()
return &sv
}
func (sv *SlowVoter) Report(t *testing.T) {
sv.verifier.Report(t)
}
func (sv *SlowVoter) PreRPC(s, t string, r *raft.RPC) error {
return nil
}
func (sv *SlowVoter) nap() {
d := sv.delayMin + time.Duration(rand.Int63n((sv.delayMax - sv.delayMin).Nanoseconds()))
time.Sleep(d)
}
func (sv *SlowVoter) PostRPC(src, target string, r *raft.RPC, res *raft.RPCResponse) error {
if sv.mode == SlowRecv && sv.slowNodes[target] {
_, ok := r.Command.(*raft.RequestVoteRequest)
if ok {
sv.nap()
}
}
return nil
}
func (sv *SlowVoter) PreRequestVote(src, target string, v *raft.RequestVoteRequest) (*raft.RequestVoteResponse, error) {
if sv.mode == SlowSend && sv.slowNodes[target] {
sv.nap()
}
return nil, nil
}
func (sv *SlowVoter) PreAppendEntries(src, target string, v *raft.AppendEntriesRequest) (*raft.AppendEntriesResponse, error) {
sv.verifier.PreAppendEntries(src, target, v)
return nil, nil
}