-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathraft_test.go
94 lines (84 loc) · 2.04 KB
/
raft_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
package raftchunking
import (
"crypto/rand"
"io"
"reflect"
"sync"
"sync/atomic"
"testing"
"time"
"github.com/hashicorp/raft"
)
// This is similar to Raft's TestRaft_TripleNode but performs several large
// value writes in a row
func TestRaftStability_Large_Values(t *testing.T) {
// Var to store one of the node's FSMs
var someFSM *ChunkingFSM
fsmFunc := func() raft.FSM {
ret := NewChunkingFSM(&raft.MockFSM{}, nil)
if someFSM == nil {
someFSM = ret
}
return ret
}
c := raft.MakeClusterCustom(t, &raft.MakeClusterOpts{
Peers: 3,
Bootstrap: true,
Conf: raft.DefaultConfig(),
MakeFSMFunc: fsmFunc,
LongstopTimeout: 30 * time.Second,
})
defer c.Close()
// Should be one leader
c.Followers()
leader := c.Leader()
c.EnsureLeader(t, leader.Leader())
// Generate a number of large blocks of data
var dataBlocks [][]byte
for i := 0; i < 50; i++ {
data := make([]byte, 10000000)
n, err := rand.Read(data)
if err != nil && err != io.EOF {
t.Fatal(err)
}
if n != 10000000 {
t.Fatalf("expected 10000k bytes to test with, read %d", n)
}
dataBlocks = append(dataBlocks, data)
}
// Write data blocks in goroutines
var wg sync.WaitGroup
var numStarted uint32
for _, data := range dataBlocks {
// Should be able to apply
wg.Add(1)
go func() {
defer wg.Done()
atomic.AddUint32(&numStarted, 1)
for atomic.LoadUint32(&numStarted) != uint32(len(dataBlocks)) {
time.Sleep(time.Microsecond)
}
future := ChunkingApply(data, nil, 5*time.Second, leader.ApplyLog)
if err := future.Error(); err != nil {
c.FailNowf("[ERR] err: %v", err)
}
}()
}
wg.Wait()
c.EnsureSame(t)
// Verify that each log matches _some_ chunk of data. We've already
// verified the FSMs are the same so only need ot look at one
mfsm := someFSM.Underlying().(*raft.MockFSM)
for _, log := range mfsm.Logs() {
var found bool
for _, data := range dataBlocks {
if reflect.DeepEqual(log, data) {
found = true
break
}
}
if !found {
t.Fatal("did not find a block")
}
}
}