4
4
"context"
5
5
"errors"
6
6
"fmt"
7
+ "net/http"
8
+ _ "net/http/pprof"
9
+ "runtime"
7
10
"testing"
8
11
9
12
"github.com/stretchr/testify/require"
@@ -52,30 +55,106 @@ func initTestCtx(injectStores bool) sdk.Context {
52
55
return ctx
53
56
}
54
57
58
+ func generateTasks (count int ) []* deliverTxTask {
59
+ var res []* deliverTxTask
60
+ for i := 0 ; i < count ; i ++ {
61
+ res = append (res , & deliverTxTask {Index : i })
62
+ }
63
+ return res
64
+ }
65
+
55
66
func TestProcessAll (t * testing.T ) {
67
+ runtime .SetBlockProfileRate (1 )
68
+
69
+ go func () {
70
+ http .ListenAndServe ("localhost:6060" , nil )
71
+ }()
72
+
56
73
tests := []struct {
57
74
name string
58
75
workers int
59
76
runs int
77
+ before func (ctx sdk.Context )
60
78
requests []* sdk.DeliverTxEntry
61
79
deliverTxFunc mockDeliverTxFunc
62
80
addStores bool
63
81
expectedErr error
64
82
assertions func (t * testing.T , ctx sdk.Context , res []types.ResponseDeliverTx )
65
83
}{
66
84
{
67
- name : "Test every tx accesses same key" ,
85
+ name : "Test zero txs does not hang" ,
86
+ workers : 20 ,
87
+ runs : 10 ,
88
+ addStores : true ,
89
+ requests : requestList (0 ),
90
+ deliverTxFunc : func (ctx sdk.Context , req types.RequestDeliverTx ) types.ResponseDeliverTx {
91
+ panic ("should not deliver" )
92
+ },
93
+ assertions : func (t * testing.T , ctx sdk.Context , res []types.ResponseDeliverTx ) {
94
+ require .Len (t , res , 0 )
95
+ },
96
+ expectedErr : nil ,
97
+ },
98
+ {
99
+ name : "Test tx writing to a store that another tx is iterating" ,
68
100
workers : 50 ,
69
- runs : 50 ,
101
+ runs : 1 ,
102
+ requests : requestList (500 ),
70
103
addStores : true ,
71
- requests : requestList (100 ),
104
+ before : func (ctx sdk.Context ) {
105
+ kv := ctx .MultiStore ().GetKVStore (testStoreKey )
106
+ // initialize 100 test values in the base kv store so iterating isn't too fast
107
+ for i := 0 ; i < 10 ; i ++ {
108
+ kv .Set ([]byte (fmt .Sprintf ("%d" , i )), []byte (fmt .Sprintf ("%d" , i )))
109
+ }
110
+ },
111
+ deliverTxFunc : func (ctx sdk.Context , req types.RequestDeliverTx ) types.ResponseDeliverTx {
112
+ kv := ctx .MultiStore ().GetKVStore (testStoreKey )
113
+ if ctx .TxIndex ()% 2 == 0 {
114
+ // For even-indexed transactions, write to the store
115
+ kv .Set (req .Tx , req .Tx )
116
+ return types.ResponseDeliverTx {
117
+ Info : "write" ,
118
+ }
119
+ } else {
120
+ // For odd-indexed transactions, iterate over the store
121
+
122
+ // just write so we have more writes going on
123
+ kv .Set (req .Tx , req .Tx )
124
+ iterator := kv .Iterator (nil , nil )
125
+ defer iterator .Close ()
126
+ for ; iterator .Valid (); iterator .Next () {
127
+ // Do nothing, just iterate
128
+ }
129
+ return types.ResponseDeliverTx {
130
+ Info : "iterate" ,
131
+ }
132
+ }
133
+ },
134
+ assertions : func (t * testing.T , ctx sdk.Context , res []types.ResponseDeliverTx ) {
135
+ for idx , response := range res {
136
+ if idx % 2 == 0 {
137
+ require .Equal (t , "write" , response .Info )
138
+ } else {
139
+ require .Equal (t , "iterate" , response .Info )
140
+ }
141
+ }
142
+ },
143
+ expectedErr : nil ,
144
+ },
145
+ {
146
+ name : "Test no overlap txs" ,
147
+ workers : 20 ,
148
+ runs : 10 ,
149
+ addStores : true ,
150
+ requests : requestList (1000 ),
72
151
deliverTxFunc : func (ctx sdk.Context , req types.RequestDeliverTx ) types.ResponseDeliverTx {
73
152
// all txs read and write to the same key to maximize conflicts
74
153
kv := ctx .MultiStore ().GetKVStore (testStoreKey )
75
- val := string (kv .Get (itemKey ))
76
154
77
155
// write to the store with this tx's index
78
- kv .Set (itemKey , req .Tx )
156
+ kv .Set (req .Tx , req .Tx )
157
+ val := string (kv .Get (req .Tx ))
79
158
80
159
// return what was read from the store (final attempt should be index-1)
81
160
return types.ResponseDeliverTx {
@@ -84,26 +163,22 @@ func TestProcessAll(t *testing.T) {
84
163
},
85
164
assertions : func (t * testing.T , ctx sdk.Context , res []types.ResponseDeliverTx ) {
86
165
for idx , response := range res {
87
- if idx == 0 {
88
- require .Equal (t , "" , response .Info )
89
- } else {
90
- // the info is what was read from the kv store by the tx
91
- // each tx writes its own index, so the info should be the index of the previous tx
92
- require .Equal (t , fmt .Sprintf ("%d" , idx - 1 ), response .Info )
93
- }
166
+ require .Equal (t , fmt .Sprintf ("%d" , idx ), response .Info )
167
+ }
168
+ store := ctx .MultiStore ().GetKVStore (testStoreKey )
169
+ for i := 0 ; i < len (res ); i ++ {
170
+ val := store .Get ([]byte (fmt .Sprintf ("%d" , i )))
171
+ require .Equal (t , []byte (fmt .Sprintf ("%d" , i )), val )
94
172
}
95
- // confirm last write made it to the parent store
96
- latest := ctx .MultiStore ().GetKVStore (testStoreKey ).Get (itemKey )
97
- require .Equal (t , []byte (fmt .Sprintf ("%d" , len (res )- 1 )), latest )
98
173
},
99
174
expectedErr : nil ,
100
175
},
101
176
{
102
- name : "Test few workers many txs " ,
103
- workers : 5 ,
104
- runs : 10 ,
177
+ name : "Test every tx accesses same key " ,
178
+ workers : 50 ,
179
+ runs : 1 ,
105
180
addStores : true ,
106
- requests : requestList (50 ),
181
+ requests : requestList (1000 ),
107
182
deliverTxFunc : func (ctx sdk.Context , req types.RequestDeliverTx ) types.ResponseDeliverTx {
108
183
// all txs read and write to the same key to maximize conflicts
109
184
kv := ctx .MultiStore ().GetKVStore (testStoreKey )
@@ -136,9 +211,9 @@ func TestProcessAll(t *testing.T) {
136
211
{
137
212
name : "Test no stores on context should not panic" ,
138
213
workers : 50 ,
139
- runs : 1 ,
214
+ runs : 10 ,
140
215
addStores : false ,
141
- requests : requestList (50 ),
216
+ requests : requestList (10 ),
142
217
deliverTxFunc : func (ctx sdk.Context , req types.RequestDeliverTx ) types.ResponseDeliverTx {
143
218
return types.ResponseDeliverTx {
144
219
Info : fmt .Sprintf ("%d" , ctx .TxIndex ()),
@@ -167,6 +242,10 @@ func TestProcessAll(t *testing.T) {
167
242
s := NewScheduler (tt .workers , ti , tt .deliverTxFunc )
168
243
ctx := initTestCtx (tt .addStores )
169
244
245
+ if tt .before != nil {
246
+ tt .before (ctx )
247
+ }
248
+
170
249
res , err := s .ProcessAll (ctx , tt .requests )
171
250
require .Len (t , res , len (tt .requests ))
172
251
0 commit comments