thresholdstate_test.go raw
1 package blockchain
2
3 import (
4 "testing"
5
6 "github.com/p9c/p9/pkg/chainhash"
7 )
8
9 // TestThresholdStateStringer tests the stringified output for the ThresholdState type.
10 func TestThresholdStateStringer(t *testing.T) {
11 t.Parallel()
12 tests := []struct {
13 in ThresholdState
14 want string
15 }{
16 {ThresholdDefined, "ThresholdDefined"},
17 {ThresholdStarted, "ThresholdStarted"},
18 {ThresholdLockedIn, "ThresholdLockedIn"},
19 {ThresholdActive, "ThresholdActive"},
20 {ThresholdFailed, "ThresholdFailed"},
21 {0xff, "Unknown ThresholdState (255)"},
22 }
23 // Detect additional threshold states that don't have the stringer added.
24 if len(tests)-1 != int(numThresholdsStates) {
25 t.Errorf("It appears a threshold statewas added without " +
26 "adding an associated stringer test",
27 )
28 }
29 t.Logf("Running %d tests", len(tests))
30 for i, test := range tests {
31 result := test.in.String()
32 if result != test.want {
33 t.Errorf("String #%d\n got: %s want: %s", i, result,
34 test.want,
35 )
36 continue
37 }
38 }
39 }
40
41 // TestThresholdStateCache ensure the threshold state cache works as intended including adding entries, updating
42 // existing entries, and flushing.
43 func TestThresholdStateCache(t *testing.T) {
44 t.Parallel()
45 tests := []struct {
46 name string
47 numEntries int
48 state ThresholdState
49 }{
50 {name: "2 entries defined", numEntries: 2, state: ThresholdDefined},
51 {name: "7 entries started", numEntries: 7, state: ThresholdStarted},
52 {name: "10 entries active", numEntries: 10, state: ThresholdActive},
53 {name: "5 entries locked in", numEntries: 5, state: ThresholdLockedIn},
54 {name: "3 entries failed", numEntries: 3, state: ThresholdFailed},
55 }
56 nextTest:
57 for _, test := range tests {
58 cache := &newThresholdCaches(1)[0]
59 for i := 0; i < test.numEntries; i++ {
60 var hash chainhash.Hash
61 hash[0] = uint8(i + 1)
62 // Ensure the hash isn't available in the cache already.
63 _, ok := cache.Lookup(&hash)
64 if ok {
65 t.Errorf("Lookup (%s): has entry for hash %v",
66 test.name, hash,
67 )
68 continue nextTest
69 }
70 // Ensure hash that was added to the cache reports it's available and the state is the expected value.
71 cache.Update(&hash, test.state)
72 state, ok := cache.Lookup(&hash)
73 if !ok {
74 t.Errorf("Lookup (%s): missing entry for hash "+
75 "%v", test.name, hash,
76 )
77 continue nextTest
78 }
79 if state != test.state {
80 t.Errorf("Lookup (%s): state mismatch - got "+
81 "%v, want %v", test.name, state,
82 test.state,
83 )
84 continue nextTest
85 }
86 // Ensure adding an existing hash with the same state doesn't break the existing entry.
87 cache.Update(&hash, test.state)
88 state, ok = cache.Lookup(&hash)
89 if !ok {
90 t.Errorf("Lookup (%s): missing entry after "+
91 "second add for hash %v", test.name,
92 hash,
93 )
94 continue nextTest
95 }
96 if state != test.state {
97 t.Errorf("Lookup (%s): state mismatch after "+
98 "second add - got %v, want %v",
99 test.name, state, test.state,
100 )
101 continue nextTest
102 }
103 // Ensure adding an existing hash with a different state updates the existing entry.
104 newState := ThresholdFailed
105 if newState == test.state {
106 newState = ThresholdStarted
107 }
108 cache.Update(&hash, newState)
109 state, ok = cache.Lookup(&hash)
110 if !ok {
111 t.Errorf("Lookup (%s): missing entry after "+
112 "state change for hash %v", test.name,
113 hash,
114 )
115 continue nextTest
116 }
117 if state != newState {
118 t.Errorf("Lookup (%s): state mismatch after "+
119 "state change - got %v, want %v",
120 test.name, state, newState,
121 )
122 continue nextTest
123 }
124 }
125 }
126 }
127