-
Notifications
You must be signed in to change notification settings - Fork 14
/
fuzz_unreliable_network_test.go
105 lines (91 loc) · 3.03 KB
/
fuzz_unreliable_network_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
103
104
105
package e2e
import (
"math/rand"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/0xPolygon/pbft-consensus/e2e/helper"
"github.com/0xPolygon/pbft-consensus/e2e/transport"
)
func TestFuzz_Unreliable_Network(t *testing.T) {
helper.IsFuzzEnabled(t)
t.Parallel()
rand.Seed(time.Now().Unix())
nodesCount := 20 + rand.Intn(11) // vary nodes [20,30]
maxFaulty := nodesCount/3 - 1
maxHeight := uint64(40)
currentHeight := uint64(0)
jitterMax := 300 * time.Millisecond
hook := transport.NewPartition(jitterMax)
config := &ClusterConfig{
Count: nodesCount,
Name: "network_unreliable",
Prefix: "prt",
RoundTimeout: helper.GetPredefinedTimeout(2 * time.Second),
}
c := NewPBFTCluster(t, config, hook)
t.Logf("Starting cluster with %d nodes, max faulty %d.\n", nodesCount, maxFaulty)
c.Start()
defer c.Stop()
for {
currentHeight += 5
var minorityPartition []string
var majorityPartition []string
// create 2 partition with random number of nodes
// minority with no more that maxFaulty and majority with rest of the nodes
pSize := 1 + rand.Intn(maxFaulty)
for i := 0; i < pSize; i++ {
minorityPartition = append(minorityPartition, "prt_"+strconv.Itoa(i))
}
for i := pSize; i < nodesCount; i++ {
majorityPartition = append(majorityPartition, "prt_"+strconv.Itoa(i))
}
t.Logf("Partitions ratio %d/%d\n", len(majorityPartition), len(minorityPartition))
hook.Partition(minorityPartition, majorityPartition)
t.Logf("Checking for height %v, started with nodes %d\n", currentHeight, nodesCount)
err := c.WaitForHeight(currentHeight, 10*time.Minute, majorityPartition)
if err != nil {
t.Fatal(err)
}
// randomly drop if possible nodes from the partition pick one number
dropN := rand.Intn(maxFaulty - pSize + 1)
t.Logf("Dropping: %v nodes.\n", dropN)
currentHeight += 5
// stop N nodes from majority partition
for i := 0; i < dropN; i++ {
c.nodes["prt_"+strconv.Itoa(pSize+i)].Stop()
}
var runningMajorityNodes []string
var stoppedNodes []string
for _, v := range c.nodes {
if v.IsRunning() {
for _, bp := range majorityPartition {
if bp == v.name { // is part of the bigPartition
runningMajorityNodes = append(runningMajorityNodes, v.name)
}
}
} else {
stoppedNodes = append(stoppedNodes, v.name)
}
}
// check all running nodes in majority partition for the block height
t.Logf("Checking for height %v, started with nodes %d\n", currentHeight, nodesCount)
err = c.WaitForHeight(currentHeight, 10*time.Minute, runningMajorityNodes)
assert.NoError(t, err)
// restart network for this iteration
hook.Reset()
for _, stopped := range stoppedNodes {
c.nodes[stopped].Start()
}
if currentHeight >= maxHeight {
break
}
}
hook.Reset()
// all nodes in the network should be synced after starting all nodes and partition restart
finalHeight := maxHeight + 10
t.Logf("Checking final height %v, nodes: %d\n", finalHeight, nodesCount)
err := c.WaitForHeight(finalHeight, 20*time.Minute)
assert.NoError(t, err)
}