@@ -16,7 +16,7 @@ use crate::generation::{frequency, Arbitrary, ArbitraryFrom};
16
16
17
17
use super :: { pick, pick_index} ;
18
18
19
- pub ( crate ) type ResultSet = Vec < Vec < Value > > ;
19
+ pub ( crate ) type ResultSet = Result < Vec < Vec < Value > > > ;
20
20
21
21
pub ( crate ) struct InteractionPlan {
22
22
pub ( crate ) plan : Vec < Interaction > ,
@@ -45,14 +45,15 @@ pub(crate) struct InteractionStats {
45
45
pub ( crate ) read_count : usize ,
46
46
pub ( crate ) write_count : usize ,
47
47
pub ( crate ) delete_count : usize ,
48
+ pub ( crate ) create_count : usize ,
48
49
}
49
50
50
51
impl Display for InteractionStats {
51
52
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
52
53
write ! (
53
54
f,
54
- "Read: {}, Write: {}, Delete: {}" ,
55
- self . read_count, self . write_count, self . delete_count
55
+ "Read: {}, Write: {}, Delete: {}, Create: {} " ,
56
+ self . read_count, self . write_count, self . delete_count, self . create_count
56
57
)
57
58
}
58
59
}
@@ -100,7 +101,9 @@ impl Interactions {
100
101
match interaction {
101
102
Interaction :: Query ( query) => match query {
102
103
Query :: Create ( create) => {
103
- env. tables . push ( create. table . clone ( ) ) ;
104
+ if !env. tables . iter ( ) . any ( |t| t. name == create. table . name ) {
105
+ env. tables . push ( create. table . clone ( ) ) ;
106
+ }
104
107
}
105
108
Query :: Insert ( insert) => {
106
109
let table = env
@@ -137,14 +140,15 @@ impl InteractionPlan {
137
140
let mut read = 0 ;
138
141
let mut write = 0 ;
139
142
let mut delete = 0 ;
143
+ let mut create = 0 ;
140
144
141
145
for interaction in & self . plan {
142
146
match interaction {
143
147
Interaction :: Query ( query) => match query {
144
148
Query :: Select ( _) => read += 1 ,
145
149
Query :: Insert ( _) => write += 1 ,
146
150
Query :: Delete ( _) => delete += 1 ,
147
- Query :: Create ( _) => { }
151
+ Query :: Create ( _) => create += 1 ,
148
152
} ,
149
153
Interaction :: Assertion ( _) => { }
150
154
Interaction :: Fault ( _) => { }
@@ -155,6 +159,7 @@ impl InteractionPlan {
155
159
read_count : read,
156
160
write_count : write,
157
161
delete_count : delete,
162
+ create_count : create,
158
163
}
159
164
}
160
165
}
@@ -172,7 +177,7 @@ impl ArbitraryFrom<SimulatorEnv> for InteractionPlan {
172
177
rng : ChaCha8Rng :: seed_from_u64 ( rng. next_u64 ( ) ) ,
173
178
} ;
174
179
175
- let num_interactions = rng . gen_range ( 0 .. env. opts . max_interactions ) ;
180
+ let num_interactions = env. opts . max_interactions ;
176
181
177
182
// First create at least one table
178
183
let create_query = Create :: arbitrary ( rng) ;
@@ -197,7 +202,7 @@ impl ArbitraryFrom<SimulatorEnv> for InteractionPlan {
197
202
}
198
203
199
204
impl Interaction {
200
- pub ( crate ) fn execute_query ( & self , conn : & mut Rc < Connection > ) -> Result < ResultSet > {
205
+ pub ( crate ) fn execute_query ( & self , conn : & mut Rc < Connection > ) -> ResultSet {
201
206
match self {
202
207
Self :: Query ( query) => {
203
208
let query_str = query. to_string ( ) ;
@@ -342,13 +347,40 @@ fn property_insert_select<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv) -> Inte
342
347
) ,
343
348
func : Box :: new ( move |stack : & Vec < ResultSet > | {
344
349
let rows = stack. last ( ) . unwrap ( ) ;
345
- rows. iter ( ) . any ( |r| r == & row)
350
+ match rows {
351
+ Ok ( rows) => rows. iter ( ) . any ( |r| r == & row) ,
352
+ Err ( _) => false ,
353
+ }
346
354
} ) ,
347
355
} ) ;
348
356
349
357
Interactions ( vec ! [ insert_query, select_query, assertion] )
350
358
}
351
359
360
+ fn property_double_create_failure < R : rand:: Rng > ( rng : & mut R , _env : & SimulatorEnv ) -> Interactions {
361
+ let create_query = Create :: arbitrary ( rng) ;
362
+ let table_name = create_query. table . name . clone ( ) ;
363
+ let cq1 = Interaction :: Query ( Query :: Create ( create_query. clone ( ) ) ) ;
364
+ let cq2 = Interaction :: Query ( Query :: Create ( create_query. clone ( ) ) ) ;
365
+
366
+ let assertion = Interaction :: Assertion ( Assertion {
367
+ message :
368
+ "creating two tables with the name should result in a failure for the second query"
369
+ . to_string ( ) ,
370
+ func : Box :: new ( move |stack : & Vec < ResultSet > | {
371
+ let last = stack. last ( ) . unwrap ( ) ;
372
+ match last {
373
+ Ok ( _) => false ,
374
+ Err ( e) => e
375
+ . to_string ( )
376
+ . contains ( & format ! ( "Table {table_name} already exists" ) ) ,
377
+ }
378
+ } ) ,
379
+ } ) ;
380
+
381
+ Interactions ( vec ! [ cq1, cq2, assertion] )
382
+ }
383
+
352
384
fn create_table < R : rand:: Rng > ( rng : & mut R , _env : & SimulatorEnv ) -> Interactions {
353
385
let create_query = Interaction :: Query ( Query :: Create ( Create :: arbitrary ( rng) ) ) ;
354
386
Interactions ( vec ! [ create_query] )
@@ -375,17 +407,21 @@ impl ArbitraryFrom<(&SimulatorEnv, InteractionStats)> for Interactions {
375
407
rng : & mut R ,
376
408
( env, stats) : & ( & SimulatorEnv , InteractionStats ) ,
377
409
) -> Self {
378
- let remaining_read =
379
- ( ( ( ( env. opts . max_interactions * env. opts . read_percent ) as f64 ) / 100.0 ) as usize )
380
- . saturating_sub ( stats. read_count ) ;
381
- let remaining_write = ( ( ( ( env. opts . max_interactions * env. opts . write_percent ) as f64 )
382
- / 100.0 ) as usize )
383
- . saturating_sub ( stats. write_count ) ;
410
+ let remaining_read = ( ( env. opts . max_interactions as f64 * env. opts . read_percent / 100.0 )
411
+ - ( stats. read_count as f64 ) )
412
+ . max ( 0.0 ) ;
413
+ let remaining_write = ( ( env. opts . max_interactions as f64 * env. opts . write_percent / 100.0 )
414
+ - ( stats. write_count as f64 ) )
415
+ . max ( 0.0 ) ;
416
+ let remaining_create = ( ( env. opts . max_interactions as f64 * env. opts . create_percent
417
+ / 100.0 )
418
+ - ( stats. create_count as f64 ) )
419
+ . max ( 0.0 ) ;
384
420
385
421
frequency (
386
422
vec ! [
387
423
(
388
- usize :: min( remaining_read, remaining_write) ,
424
+ f64 :: min( remaining_read, remaining_write) ,
389
425
Box :: new( |rng: & mut R | property_insert_select( rng, env) ) ,
390
426
) ,
391
427
(
@@ -397,10 +433,14 @@ impl ArbitraryFrom<(&SimulatorEnv, InteractionStats)> for Interactions {
397
433
Box :: new( |rng: & mut R | random_write( rng, env) ) ,
398
434
) ,
399
435
(
400
- remaining_write / 10 ,
436
+ remaining_create ,
401
437
Box :: new( |rng: & mut R | create_table( rng, env) ) ,
402
438
) ,
403
- ( 1 , Box :: new( |rng: & mut R | random_fault( rng, env) ) ) ,
439
+ ( 1.0 , Box :: new( |rng: & mut R | random_fault( rng, env) ) ) ,
440
+ (
441
+ remaining_create / 2.0 ,
442
+ Box :: new( |rng: & mut R | property_double_create_failure( rng, env) ) ,
443
+ ) ,
404
444
] ,
405
445
rng,
406
446
)
0 commit comments