@@ -56,33 +56,48 @@ func TestMatcherWildcards(t *testing.T) {
56
56
57
57
// Tests the matcher pipeline on a single continuous workflow without interrupts.
58
58
func TestMatcherContinuous (t * testing.T ) {
59
- testMatcherDiffBatches (t , [][]bloomIndexes {{{10 , 20 , 30 }}}, 100000 , false , 75 )
60
- testMatcherDiffBatches (t , [][]bloomIndexes {{{32 , 3125 , 100 }}, {{40 , 50 , 10 }}}, 100000 , false , 81 )
61
- testMatcherDiffBatches (t , [][]bloomIndexes {{{4 , 8 , 11 }, {7 , 8 , 17 }}, {{9 , 9 , 12 }, {15 , 20 , 13 }}, {{18 , 15 , 15 }, {12 , 10 , 4 }}}, 10000 , false , 36 )
59
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{10 , 20 , 30 }}}, 0 , 100000 , false , 75 )
60
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{32 , 3125 , 100 }}, {{40 , 50 , 10 }}}, 0 , 100000 , false , 81 )
61
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{4 , 8 , 11 }, {7 , 8 , 17 }}, {{9 , 9 , 12 }, {15 , 20 , 13 }}, {{18 , 15 , 15 }, {12 , 10 , 4 }}}, 0 , 10000 , false , 36 )
62
62
}
63
63
64
64
// Tests the matcher pipeline on a constantly interrupted and resumed work pattern
65
65
// with the aim of ensuring data items are requested only once.
66
66
func TestMatcherIntermittent (t * testing.T ) {
67
- testMatcherDiffBatches (t , [][]bloomIndexes {{{10 , 20 , 30 }}}, 100000 , true , 75 )
68
- testMatcherDiffBatches (t , [][]bloomIndexes {{{32 , 3125 , 100 }}, {{40 , 50 , 10 }}}, 100000 , true , 81 )
69
- testMatcherDiffBatches (t , [][]bloomIndexes {{{4 , 8 , 11 }, {7 , 8 , 17 }}, {{9 , 9 , 12 }, {15 , 20 , 13 }}, {{18 , 15 , 15 }, {12 , 10 , 4 }}}, 10000 , true , 36 )
67
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{10 , 20 , 30 }}}, 0 , 100000 , true , 75 )
68
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{32 , 3125 , 100 }}, {{40 , 50 , 10 }}}, 0 , 100000 , true , 81 )
69
+ testMatcherDiffBatches (t , [][]bloomIndexes {{{4 , 8 , 11 }, {7 , 8 , 17 }}, {{9 , 9 , 12 }, {15 , 20 , 13 }}, {{18 , 15 , 15 }, {12 , 10 , 4 }}}, 0 , 10000 , true , 36 )
70
70
}
71
71
72
72
// Tests the matcher pipeline on random input to hopefully catch anomalies.
73
73
func TestMatcherRandom (t * testing.T ) {
74
74
for i := 0 ; i < 10 ; i ++ {
75
- testMatcherBothModes (t , makeRandomIndexes ([]int {1 }, 50 ), 10000 , 0 )
76
- testMatcherBothModes (t , makeRandomIndexes ([]int {3 }, 50 ), 10000 , 0 )
77
- testMatcherBothModes (t , makeRandomIndexes ([]int {2 , 2 , 2 }, 20 ), 10000 , 0 )
78
- testMatcherBothModes (t , makeRandomIndexes ([]int {5 , 5 , 5 }, 50 ), 10000 , 0 )
79
- testMatcherBothModes (t , makeRandomIndexes ([]int {4 , 4 , 4 }, 20 ), 10000 , 0 )
75
+ testMatcherBothModes (t , makeRandomIndexes ([]int {1 }, 50 ), 0 , 10000 , 0 )
76
+ testMatcherBothModes (t , makeRandomIndexes ([]int {3 }, 50 ), 0 , 10000 , 0 )
77
+ testMatcherBothModes (t , makeRandomIndexes ([]int {2 , 2 , 2 }, 20 ), 0 , 10000 , 0 )
78
+ testMatcherBothModes (t , makeRandomIndexes ([]int {5 , 5 , 5 }, 50 ), 0 , 10000 , 0 )
79
+ testMatcherBothModes (t , makeRandomIndexes ([]int {4 , 4 , 4 }, 20 ), 0 , 10000 , 0 )
80
80
}
81
81
}
82
82
83
+ // Tests that the matcher can properly find matches if the starting block is
84
+ // shifter from a multiple of 8. This is needed to cover an optimisation with
85
+ // bitset matching https://github.com/ethereum/go-ethereum/issues/15309.
86
+ func TestMatcherShifted (t * testing.T ) {
87
+ // Block 0 always matches in the tests, skip ahead of first 8 blocks with the
88
+ // start to get a potential zero byte in the matcher bitset.
89
+
90
+ // To keep the second bitset byte zero, the filter must only match for the first
91
+ // time in block 16, so doing an all-16 bit filter should suffice.
92
+
93
+ // To keep the starting block non divisible by 8, block number 9 is the first
94
+ // that would introduce a shift and not match block 0.
95
+ testMatcherBothModes (t , [][]bloomIndexes {{{16 , 16 , 16 }}}, 9 , 64 , 0 )
96
+ }
97
+
83
98
// Tests that matching on everything doesn't crash (special case internally).
84
99
func TestWildcardMatcher (t * testing.T ) {
85
- testMatcherBothModes (t , nil , 10000 , 0 )
100
+ testMatcherBothModes (t , nil , 0 , 10000 , 0 )
86
101
}
87
102
88
103
// makeRandomIndexes generates a random filter system, composed on multiple filter
@@ -104,9 +119,9 @@ func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes {
104
119
// testMatcherDiffBatches runs the given matches test in single-delivery and also
105
120
// in batches delivery mode, verifying that all kinds of deliveries are handled
106
121
// correctly withn.
107
- func testMatcherDiffBatches (t * testing.T , filter [][]bloomIndexes , blocks uint64 , intermittent bool , retrievals uint32 ) {
108
- singleton := testMatcher (t , filter , blocks , intermittent , retrievals , 1 )
109
- batched := testMatcher (t , filter , blocks , intermittent , retrievals , 16 )
122
+ func testMatcherDiffBatches (t * testing.T , filter [][]bloomIndexes , start , blocks uint64 , intermittent bool , retrievals uint32 ) {
123
+ singleton := testMatcher (t , filter , start , blocks , intermittent , retrievals , 1 )
124
+ batched := testMatcher (t , filter , start , blocks , intermittent , retrievals , 16 )
110
125
111
126
if singleton != batched {
112
127
t .Errorf ("filter = %v blocks = %v intermittent = %v: request count mismatch, %v in signleton vs. %v in batched mode" , filter , blocks , intermittent , singleton , batched )
@@ -115,9 +130,9 @@ func testMatcherDiffBatches(t *testing.T, filter [][]bloomIndexes, blocks uint64
115
130
116
131
// testMatcherBothModes runs the given matcher test in both continuous as well as
117
132
// in intermittent mode, verifying that the request counts match each other.
118
- func testMatcherBothModes (t * testing.T , filter [][]bloomIndexes , blocks uint64 , retrievals uint32 ) {
119
- continuous := testMatcher (t , filter , blocks , false , retrievals , 16 )
120
- intermittent := testMatcher (t , filter , blocks , true , retrievals , 16 )
133
+ func testMatcherBothModes (t * testing.T , filter [][]bloomIndexes , start , blocks uint64 , retrievals uint32 ) {
134
+ continuous := testMatcher (t , filter , start , blocks , false , retrievals , 16 )
135
+ intermittent := testMatcher (t , filter , start , blocks , true , retrievals , 16 )
121
136
122
137
if continuous != intermittent {
123
138
t .Errorf ("filter = %v blocks = %v: request count mismatch, %v in continuous vs. %v in intermittent mode" , filter , blocks , continuous , intermittent )
@@ -126,7 +141,7 @@ func testMatcherBothModes(t *testing.T, filter [][]bloomIndexes, blocks uint64,
126
141
127
142
// testMatcher is a generic tester to run the given matcher test and return the
128
143
// number of requests made for cross validation between different modes.
129
- func testMatcher (t * testing.T , filter [][]bloomIndexes , blocks uint64 , intermittent bool , retrievals uint32 , maxReqCount int ) uint32 {
144
+ func testMatcher (t * testing.T , filter [][]bloomIndexes , start , blocks uint64 , intermittent bool , retrievals uint32 , maxReqCount int ) uint32 {
130
145
// Create a new matcher an simulate our explicit random bitsets
131
146
matcher := NewMatcher (testSectionSize , nil )
132
147
matcher .filters = filter
@@ -145,14 +160,14 @@ func testMatcher(t *testing.T, filter [][]bloomIndexes, blocks uint64, intermitt
145
160
quit := make (chan struct {})
146
161
matches := make (chan uint64 , 16 )
147
162
148
- session , err := matcher .Start (context .Background (), 0 , blocks - 1 , matches )
163
+ session , err := matcher .Start (context .Background (), start , blocks - 1 , matches )
149
164
if err != nil {
150
165
t .Fatalf ("failed to stat matcher session: %v" , err )
151
166
}
152
167
startRetrievers (session , quit , & requested , maxReqCount )
153
168
154
169
// Iterate over all the blocks and verify that the pipeline produces the correct matches
155
- for i := uint64 ( 0 ) ; i < blocks ; i ++ {
170
+ for i := start ; i < blocks ; i ++ {
156
171
if expMatch3 (filter , i ) {
157
172
match , ok := <- matches
158
173
if ! ok {
0 commit comments