...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package rafttest
16
17 import (
18 "bufio"
19 "fmt"
20 "math"
21 "strings"
22
23 "go.etcd.io/etcd/raft/v3"
24 pb "go.etcd.io/etcd/raft/v3/raftpb"
25 )
26
27
28 type InteractionOpts struct {
29 OnConfig func(*raft.Config)
30 }
31
32
33 type Node struct {
34 *raft.RawNode
35 Storage
36
37 Config *raft.Config
38 History []pb.Snapshot
39 }
40
41
42
43 type InteractionEnv struct {
44 Options *InteractionOpts
45 Nodes []Node
46 Messages []pb.Message
47
48 Output *RedirectLogger
49 }
50
51
52 func NewInteractionEnv(opts *InteractionOpts) *InteractionEnv {
53 if opts == nil {
54 opts = &InteractionOpts{}
55 }
56 return &InteractionEnv{
57 Options: opts,
58 Output: &RedirectLogger{
59 Builder: &strings.Builder{},
60 },
61 }
62 }
63
64 func (env *InteractionEnv) withIndent(f func()) {
65 orig := env.Output.Builder
66 env.Output.Builder = &strings.Builder{}
67 f()
68
69 scanner := bufio.NewScanner(strings.NewReader(env.Output.Builder.String()))
70 for scanner.Scan() {
71 orig.WriteString(" " + scanner.Text() + "\n")
72 }
73 env.Output.Builder = orig
74 }
75
76
77
78
79 type Storage interface {
80 raft.Storage
81 SetHardState(state pb.HardState) error
82 ApplySnapshot(pb.Snapshot) error
83 Compact(newFirstIndex uint64) error
84 Append([]pb.Entry) error
85 }
86
87
88
89 func defaultRaftConfig(id uint64, applied uint64, s raft.Storage) *raft.Config {
90 return &raft.Config{
91 ID: id,
92 Applied: applied,
93 ElectionTick: 3,
94 HeartbeatTick: 1,
95 Storage: s,
96 MaxSizePerMsg: math.MaxUint64,
97 MaxInflightMsgs: math.MaxInt32,
98 }
99 }
100
101 func defaultEntryFormatter(b []byte) string {
102 return fmt.Sprintf("%q", b)
103 }
104
View as plain text