1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package confchange
16
17 import (
18 "fmt"
19 "math/rand"
20 "reflect"
21 "testing"
22 "testing/quick"
23
24 pb "go.etcd.io/etcd/raft/v3/raftpb"
25 "go.etcd.io/etcd/raft/v3/tracker"
26 )
27
28
29
30 func TestConfChangeQuick(t *testing.T) {
31 cfg := &quick.Config{
32 MaxCount: 1000,
33 }
34
35
36
37 const infoCount = 5
38
39 runWithJoint := func(c *Changer, ccs []pb.ConfChangeSingle) error {
40 cfg, prs, err := c.EnterJoint(false , ccs...)
41 if err != nil {
42 return err
43 }
44
45
46 cfg2a, prs2a, err := c.EnterJoint(true , ccs...)
47 if err != nil {
48 return err
49 }
50 cfg2a.AutoLeave = false
51 if !reflect.DeepEqual(cfg, cfg2a) || !reflect.DeepEqual(prs, prs2a) {
52 return fmt.Errorf("cfg: %+v\ncfg2a: %+v\nprs: %+v\nprs2a: %+v",
53 cfg, cfg2a, prs, prs2a)
54 }
55 c.Tracker.Config = cfg
56 c.Tracker.Progress = prs
57 cfg2b, prs2b, err := c.LeaveJoint()
58 if err != nil {
59 return err
60 }
61
62 c.Tracker.Config = cfg
63 c.Tracker.Progress = prs
64 cfg, prs, err = c.LeaveJoint()
65 if err != nil {
66 return err
67 }
68 if !reflect.DeepEqual(cfg, cfg2b) || !reflect.DeepEqual(prs, prs2b) {
69 return fmt.Errorf("cfg: %+v\ncfg2b: %+v\nprs: %+v\nprs2b: %+v",
70 cfg, cfg2b, prs, prs2b)
71 }
72 c.Tracker.Config = cfg
73 c.Tracker.Progress = prs
74 return nil
75 }
76
77 runWithSimple := func(c *Changer, ccs []pb.ConfChangeSingle) error {
78 for _, cc := range ccs {
79 cfg, prs, err := c.Simple(cc)
80 if err != nil {
81 return err
82 }
83 c.Tracker.Config, c.Tracker.Progress = cfg, prs
84 }
85 return nil
86 }
87
88 type testFunc func(*Changer, []pb.ConfChangeSingle) error
89
90 wrapper := func(invoke testFunc) func(setup initialChanges, ccs confChanges) (*Changer, error) {
91 return func(setup initialChanges, ccs confChanges) (*Changer, error) {
92 tr := tracker.MakeProgressTracker(10)
93 c := &Changer{
94 Tracker: tr,
95 LastIndex: 10,
96 }
97
98 if err := runWithSimple(c, setup); err != nil {
99 return nil, err
100 }
101
102 err := invoke(c, ccs)
103 return c, err
104 }
105 }
106
107 var n int
108 f1 := func(setup initialChanges, ccs confChanges) *Changer {
109 c, err := wrapper(runWithSimple)(setup, ccs)
110 if err != nil {
111 t.Fatal(err)
112 }
113 if n < infoCount {
114 t.Log("initial setup:", Describe(setup...))
115 t.Log("changes:", Describe(ccs...))
116 t.Log(c.Tracker.Config)
117 t.Log(c.Tracker.Progress)
118 }
119 n++
120 return c
121 }
122 f2 := func(setup initialChanges, ccs confChanges) *Changer {
123 c, err := wrapper(runWithJoint)(setup, ccs)
124 if err != nil {
125 t.Fatal(err)
126 }
127 return c
128 }
129 err := quick.CheckEqual(f1, f2, cfg)
130 if err == nil {
131 return
132 }
133 cErr, ok := err.(*quick.CheckEqualError)
134 if !ok {
135 t.Fatal(err)
136 }
137
138 t.Error("setup:", Describe(cErr.In[0].([]pb.ConfChangeSingle)...))
139 t.Error("ccs:", Describe(cErr.In[1].([]pb.ConfChangeSingle)...))
140 t.Errorf("out1: %+v\nout2: %+v", cErr.Out1, cErr.Out2)
141 }
142
143 type confChangeTyp pb.ConfChangeType
144
145 func (confChangeTyp) Generate(rand *rand.Rand, _ int) reflect.Value {
146 return reflect.ValueOf(confChangeTyp(rand.Intn(4)))
147 }
148
149 type confChanges []pb.ConfChangeSingle
150
151 func genCC(num func() int, id func() uint64, typ func() pb.ConfChangeType) []pb.ConfChangeSingle {
152 var ccs []pb.ConfChangeSingle
153 n := num()
154 for i := 0; i < n; i++ {
155 ccs = append(ccs, pb.ConfChangeSingle{Type: typ(), NodeID: id()})
156 }
157 return ccs
158 }
159
160 func (confChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
161 num := func() int {
162 return 1 + rand.Intn(9)
163 }
164 id := func() uint64 {
165
166
167
168 return 1 + uint64(num())
169 }
170 typ := func() pb.ConfChangeType {
171 return pb.ConfChangeType(rand.Intn(len(pb.ConfChangeType_name)))
172 }
173 return reflect.ValueOf(genCC(num, id, typ))
174 }
175
176 type initialChanges []pb.ConfChangeSingle
177
178 func (initialChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
179 num := func() int {
180 return 1 + rand.Intn(5)
181 }
182 id := func() uint64 { return uint64(num()) }
183 typ := func() pb.ConfChangeType {
184 return pb.ConfChangeAddNode
185 }
186
187
188
189 ccs := append([]pb.ConfChangeSingle{{Type: pb.ConfChangeAddNode, NodeID: 1}}, genCC(num, id, typ)...)
190 return reflect.ValueOf(ccs)
191 }
192
View as plain text