@@ -16,12 +16,12 @@ import (
16
16
//go:generate go run ./cmd/generate
17
17
18
18
// openers contains the known datastore implementations.
19
- var openers map [string ]func (string ) ds.TxnDatastore
19
+ var openers map [string ]func (string ) ds.Datastore
20
20
21
21
// AddOpener allows registration of a new driver for fuzzing.
22
- func AddOpener (name string , opener func (loc string ) ds.TxnDatastore ) {
22
+ func AddOpener (name string , opener func (loc string ) ds.Datastore ) {
23
23
if openers == nil {
24
- openers = make (map [string ]func (string ) ds.TxnDatastore )
24
+ openers = make (map [string ]func (string ) ds.Datastore )
25
25
}
26
26
openers [name ] = opener
27
27
}
@@ -32,14 +32,16 @@ var Threads int
32
32
33
33
func init () {
34
34
if openers == nil {
35
- openers = make (map [string ]func (string ) ds.TxnDatastore )
35
+ openers = make (map [string ]func (string ) ds.Datastore )
36
36
}
37
37
Threads = 1
38
38
}
39
39
40
40
// RunState encapulates the state of a given fuzzing run
41
41
type RunState struct {
42
- inst ds.TxnDatastore
42
+ inst ds.Datastore
43
+ // opMax signals which operations the instance supports.
44
+ opMax op
43
45
inputChannels []chan <- byte
44
46
wg sync.WaitGroup
45
47
Cancel context.CancelFunc
@@ -50,10 +52,18 @@ type RunState struct {
50
52
}
51
53
52
54
// DB returns the datastore being driven by this instance
53
- func (r * RunState ) DB () ds.TxnDatastore {
55
+ func (r * RunState ) DB () ds.Datastore {
54
56
return r .inst
55
57
}
56
58
59
+ // TxnDB returns the transaciton database if the store under test supports transactions
60
+ func (r * RunState ) TxnDB () ds.TxnDatastore {
61
+ if txdb , ok := r .inst .(ds.TxnDatastore ); ok {
62
+ return txdb
63
+ }
64
+ return nil
65
+ }
66
+
57
67
type threadState struct {
58
68
op
59
69
keyReady bool
@@ -78,6 +88,11 @@ func Open(driver string, location string, cleanup bool) (*RunState, error) {
78
88
79
89
state := RunState {}
80
90
state .inst = opener (location )
91
+ state .opMax = opMax
92
+ // don't attempt transaction operations on non-txn datastores.
93
+ if state .TxnDB () == nil {
94
+ state .opMax = opNewTX
95
+ }
81
96
state .keyCache [0 ] = ds .NewKey ("/" )
82
97
state .cachedKeys = 1
83
98
@@ -146,7 +161,7 @@ func FuzzDB(driver string, location string, cleanup bool, data []byte) int {
146
161
147
162
// FuzzStream does the same as fuzz but with streaming input
148
163
func FuzzStream (driver string , location string , cleanup bool , data io.Reader ) error {
149
- inst , err := Open ("badger" , "tmp" , true )
164
+ inst , err := Open (driver , location , cleanup )
150
165
if err != nil {
151
166
return err
152
167
}
@@ -185,10 +200,10 @@ const (
185
200
opQuery
186
201
opPut
187
202
opDelete
203
+ opSync
188
204
opNewTX
189
205
opCommitTX
190
206
opDiscardTX
191
- opSync
192
207
opMax
193
208
)
194
209
@@ -214,7 +229,7 @@ func threadDriver(ctx context.Context, runState *RunState, cmnds chan byte) {
214
229
215
230
func nextState (s * threadState , c byte ) error {
216
231
if s .op == opNone {
217
- s .op = op (c ) % opMax
232
+ s .op = op (c ) % s . RunState . opMax
218
233
return nil
219
234
} else if s .op == opGet {
220
235
if ! s .keyReady {
@@ -267,11 +282,13 @@ func nextState(s *threadState, c byte) error {
267
282
return nil
268
283
} else if s .op == opNewTX {
269
284
if s .txn == nil {
270
- s .txn , _ = s .RunState .inst .NewTransaction (((c & 1 ) == 1 ))
271
- if (c & 1 ) != 1 { // read+write
272
- s .writer = s .txn
285
+ if tdb := s .RunState .TxnDB (); tdb != nil {
286
+ s .txn , _ = tdb .NewTransaction (((c & 1 ) == 1 ))
287
+ if (c & 1 ) != 1 { // read+write
288
+ s .writer = s .txn
289
+ }
290
+ s .reader = s .txn
273
291
}
274
- s .reader = s .txn
275
292
}
276
293
reset (s )
277
294
return nil
0 commit comments