Annotation of embedaddon/sqlite3/test/randexpr1.tcl, revision 1.1.1.1

1.1       misho       1: # Run this TCL script to generate thousands of test cases containing
                      2: # complicated expressions.
                      3: #
                      4: # The generated tests are intended to verify expression evaluation
                      5: # in SQLite against expression evaluation TCL.  
                      6: #
                      7: 
                      8: # Terms of the $intexpr list each contain two sub-terms.
                      9: #
                     10: #     *  An SQL expression template
                     11: #     *  The equivalent TCL expression
                     12: #
                     13: # EXPR is replaced by an integer subexpression.  BOOL is replaced
                     14: # by a boolean subexpression.
                     15: #
                     16: set intexpr {
                     17:   {11 wide(11)}
                     18:   {13 wide(13)}
                     19:   {17 wide(17)}
                     20:   {19 wide(19)}
                     21:   {a $a}
                     22:   {b $b}
                     23:   {c $c}
                     24:   {d $d}
                     25:   {e $e}
                     26:   {f $f}
                     27:   {t1.a $a}
                     28:   {t1.b $b}
                     29:   {t1.c $c}
                     30:   {t1.d $d}
                     31:   {t1.e $e}
                     32:   {t1.f $f}
                     33:   {(EXPR) (EXPR)}
                     34:   {{ -EXPR} {-EXPR}}
                     35:   {+EXPR +EXPR}
                     36:   {~EXPR ~EXPR}
                     37:   {EXPR+EXPR EXPR+EXPR}
                     38:   {EXPR-EXPR EXPR-EXPR}
                     39:   {EXPR*EXPR EXPR*EXPR}
                     40:   {EXPR+EXPR EXPR+EXPR}
                     41:   {EXPR-EXPR EXPR-EXPR}
                     42:   {EXPR*EXPR EXPR*EXPR}
                     43:   {EXPR+EXPR EXPR+EXPR}
                     44:   {EXPR-EXPR EXPR-EXPR}
                     45:   {EXPR*EXPR EXPR*EXPR}
                     46:   {{EXPR | EXPR} {EXPR | EXPR}}
                     47:   {(abs(EXPR)/abs(EXPR)) (abs(EXPR)/abs(EXPR))}
                     48:   {
                     49:     {case when BOOL then EXPR else EXPR end}
                     50:     {((BOOL)?EXPR:EXPR)}
                     51:   }
                     52:   {
                     53:     {case when BOOL then EXPR when BOOL then EXPR else EXPR end}
                     54:     {((BOOL)?EXPR:((BOOL)?EXPR:EXPR))}
                     55:   }
                     56:   {
                     57:     {case EXPR when EXPR then EXPR else EXPR end}
                     58:     {(((EXPR)==(EXPR))?EXPR:EXPR)}
                     59:   }
                     60:   {
                     61:     {(select AGG from t1)}
                     62:     {(AGG)}
                     63:   }
                     64:   {
                     65:     {coalesce((select max(EXPR) from t1 where BOOL),EXPR)}
                     66:     {[coalesce_subquery [expr {EXPR}] [expr {BOOL}] [expr {EXPR}]]}
                     67:   }
                     68:   {
                     69:     {coalesce((select EXPR from t1 where BOOL),EXPR)}
                     70:     {[coalesce_subquery [expr {EXPR}] [expr {BOOL}] [expr {EXPR}]]}
                     71:   }
                     72: }
                     73: 
                     74: # The $boolexpr list contains terms that show both an SQL boolean
                     75: # expression and its equivalent TCL.
                     76: #
                     77: set boolexpr {
                     78:   {EXPR=EXPR   ((EXPR)==(EXPR))}
                     79:   {EXPR<EXPR   ((EXPR)<(EXPR))}
                     80:   {EXPR>EXPR   ((EXPR)>(EXPR))}
                     81:   {EXPR<=EXPR  ((EXPR)<=(EXPR))}
                     82:   {EXPR>=EXPR  ((EXPR)>=(EXPR))}
                     83:   {EXPR<>EXPR  ((EXPR)!=(EXPR))}
                     84:   {
                     85:     {EXPR between EXPR and EXPR}
                     86:     {[betweenop [expr {EXPR}] [expr {EXPR}] [expr {EXPR}]]}
                     87:   }
                     88:   {
                     89:     {EXPR not between EXPR and EXPR}
                     90:     {(![betweenop [expr {EXPR}] [expr {EXPR}] [expr {EXPR}]])}
                     91:   }
                     92:   {
                     93:     {EXPR in (EXPR,EXPR,EXPR)}
                     94:     {([inop [expr {EXPR}] [expr {EXPR}] [expr {EXPR}] [expr {EXPR}]])}
                     95:   }
                     96:   {
                     97:     {EXPR not in (EXPR,EXPR,EXPR)}
                     98:     {(![inop [expr {EXPR}] [expr {EXPR}] [expr {EXPR}] [expr {EXPR}]])}
                     99:   }
                    100:   {
                    101:     {EXPR in (select EXPR from t1 union select EXPR from t1)}
                    102:     {[inop [expr {EXPR}] [expr {EXPR}] [expr {EXPR}]]}
                    103:   }
                    104:   {
                    105:     {EXPR in (select AGG from t1 union select AGG from t1)}
                    106:     {[inop [expr {EXPR}] [expr {AGG}] [expr {AGG}]]}
                    107:   }
                    108:   {
                    109:     {exists(select 1 from t1 where BOOL)}
                    110:     {(BOOL)}
                    111:   }
                    112:   {
                    113:     {not exists(select 1 from t1 where BOOL)}
                    114:     {!(BOOL)}
                    115:   }
                    116:   {{not BOOL}  !BOOL}
                    117:   {{BOOL and BOOL} {BOOL tcland BOOL}}
                    118:   {{BOOL or BOOL}  {BOOL || BOOL}}
                    119:   {{BOOL and BOOL} {BOOL tcland BOOL}}
                    120:   {{BOOL or BOOL}  {BOOL || BOOL}}
                    121:   {(BOOL) (BOOL)}
                    122:   {(BOOL) (BOOL)}
                    123: }
                    124: 
                    125: # Aggregate expressions
                    126: #
                    127: set aggexpr {
                    128:   {count(*) wide(1)}
                    129:   {{count(distinct EXPR)} {[one {EXPR}]}}
                    130:   {{cast(avg(EXPR) AS integer)} (EXPR)}
                    131:   {min(EXPR) (EXPR)}
                    132:   {max(EXPR) (EXPR)}
                    133:   {(AGG) (AGG)}
                    134:   {{ -AGG} {-AGG}}
                    135:   {+AGG +AGG}
                    136:   {~AGG ~AGG}
                    137:   {abs(AGG)  abs(AGG)}
                    138:   {AGG+AGG   AGG+AGG}
                    139:   {AGG-AGG   AGG-AGG}
                    140:   {AGG*AGG   AGG*AGG}
                    141:   {{AGG | AGG}  {AGG | AGG}}
                    142:   {
                    143:     {case AGG when AGG then AGG else AGG end}
                    144:     {(((AGG)==(AGG))?AGG:AGG)}
                    145:   }
                    146: }
                    147: 
                    148: # Convert a string containing EXPR, AGG, and BOOL into a string
                    149: # that contains nothing but X, Y, and Z.
                    150: #
                    151: proc extract_vars {a} {
                    152:   regsub -all {EXPR} $a X a
                    153:   regsub -all {AGG} $a Y a
                    154:   regsub -all {BOOL} $a Z a
                    155:   regsub -all {[^XYZ]} $a {} a
                    156:   return $a
                    157: }
                    158: 
                    159: 
                    160: # Test all templates to make sure the number of EXPR, AGG, and BOOL
                    161: # expressions match.
                    162: #
                    163: foreach term [concat $aggexpr $intexpr $boolexpr] {
                    164:   foreach {a b} $term break
                    165:   if {[extract_vars $a]!=[extract_vars $b]} {
                    166:     error "mismatch: $term"
                    167:   }
                    168: }
                    169: 
                    170: # Generate a random expression according to the templates given above.
                    171: # If the argument is EXPR or omitted, then an integer expression is
                    172: # generated.  If the argument is BOOL then a boolean expression is
                    173: # produced.
                    174: #
                    175: proc generate_expr {{e EXPR}} {
                    176:   set tcle $e
                    177:   set ne [llength $::intexpr]
                    178:   set nb [llength $::boolexpr]
                    179:   set na [llength $::aggexpr]
                    180:   set div 2
                    181:   set mx 50
                    182:   set i 0
                    183:   while {1} {
                    184:     set cnt 0
                    185:     set re [lindex $::intexpr [expr {int(rand()*$ne)}]]
                    186:     incr cnt [regsub {EXPR} $e [lindex $re 0] e]
                    187:     regsub {EXPR} $tcle [lindex $re 1] tcle
                    188:     set rb [lindex $::boolexpr [expr {int(rand()*$nb)}]]
                    189:     incr cnt [regsub {BOOL} $e [lindex $rb 0] e]
                    190:     regsub {BOOL} $tcle [lindex $rb 1] tcle
                    191:     set ra [lindex $::aggexpr [expr {int(rand()*$na)}]]
                    192:     incr cnt [regsub {AGG} $e [lindex $ra 0] e]
                    193:     regsub {AGG} $tcle [lindex $ra 1] tcle
                    194: 
                    195:     if {$cnt==0} break
                    196:     incr i $cnt
                    197: 
                    198:     set v1 [extract_vars $e]
                    199:     if {$v1!=[extract_vars $tcle]} {
                    200:       exit
                    201:     }
                    202: 
                    203:     if {$i+[string length $v1]>=$mx} {
                    204:       set ne [expr {$ne/$div}]
                    205:       set nb [expr {$nb/$div}]
                    206:       set na [expr {$na/$div}]
                    207:       set div 1
                    208:       set mx [expr {$mx*1000}]
                    209:     }
                    210:   }
                    211:   regsub -all { tcland } $tcle { \&\& } tcle
                    212:   return [list $e $tcle]
                    213: }
                    214: 
                    215: # Implementation of routines used to implement the IN and BETWEEN
                    216: # operators.
                    217: proc inop {lhs args} {
                    218:   foreach a $args {
                    219:     if {$a==$lhs} {return 1}
                    220:   }
                    221:   return 0
                    222: }
                    223: proc betweenop {lhs first second} {
                    224:   return [expr {$lhs>=$first && $lhs<=$second}]
                    225: }
                    226: proc coalesce_subquery {a b e} {
                    227:   if {$b} {
                    228:     return $a
                    229:   } else {
                    230:     return $e
                    231:   }
                    232: }
                    233: proc one {args} {
                    234:   return 1
                    235: }
                    236: 
                    237: # Begin generating the test script:
                    238: #
                    239: puts {# 2008 December 16
                    240: #
                    241: # The author disclaims copyright to this source code.  In place of
                    242: # a legal notice, here is a blessing:
                    243: #
                    244: #    May you do good and not evil.
                    245: #    May you find forgiveness for yourself and forgive others.
                    246: #    May you share freely, never taking more than you give.
                    247: #
                    248: #***********************************************************************
                    249: # This file implements regression tests for SQLite library.
                    250: #
                    251: # This file tests randomly generated SQL expressions.  The expressions
                    252: # are generated by a TCL script.  The same TCL script also computes the
                    253: # correct value of the expression.  So, from one point of view, this
                    254: # file verifies the expression evaluation logic of SQLite against the
                    255: # expression evaluation logic of TCL.
                    256: #
                    257: # An early version of this script is how bug #3541 was detected.
                    258: #
                    259: # $Id: randexpr1.tcl,v 1.1 2008/12/15 16:33:30 drh Exp $
                    260: set testdir [file dirname $argv0]
                    261: source $testdir/tester.tcl
                    262: 
                    263: # Create test data
                    264: #
                    265: do_test randexpr1-1.1 {
                    266:   db eval {
                    267:     CREATE TABLE t1(a,b,c,d,e,f);
                    268:     INSERT INTO t1 VALUES(100,200,300,400,500,600);
                    269:     SELECT * FROM t1
                    270:   }
                    271: } {100 200 300 400 500 600}
                    272: }
                    273: 
                    274: # Test data for TCL evaluation.
                    275: #
                    276: set a [expr {wide(100)}]
                    277: set b [expr {wide(200)}]
                    278: set c [expr {wide(300)}]
                    279: set d [expr {wide(400)}]
                    280: set e [expr {wide(500)}]
                    281: set f [expr {wide(600)}]
                    282: 
                    283: # A procedure to generate a test case.
                    284: #
                    285: set tn 0
                    286: proc make_test_case {sql result} {
                    287:   global tn
                    288:   incr tn
                    289:   puts "do_test randexpr-2.$tn {\n  db eval {$sql}\n} {$result}"
                    290: }
                    291: 
                    292: # Generate many random test cases.
                    293: #
                    294: expr srand(0)
                    295: for {set i 0} {$i<1000} {incr i} {
                    296:   while {1} {
                    297:     foreach {sqle tcle} [generate_expr EXPR] break;
                    298:     if {[catch {expr $tcle} ans]} {
                    299:       #puts stderr [list $tcle]
                    300:       #puts stderr ans=$ans
                    301:       if {![regexp {divide by zero} $ans]} exit
                    302:       continue
                    303:     }
                    304:     set len [string length $sqle]
                    305:     if {$len<100 || $len>2000} continue
                    306:     if {[info exists seen($sqle)]} continue
                    307:     set seen($sqle) 1
                    308:     break
                    309:   }
                    310:   while {1} {
                    311:     foreach {sqlb tclb} [generate_expr BOOL] break;
                    312:     if {[catch {expr $tclb} bans]} {
                    313:       #puts stderr [list $tclb]
                    314:       #puts stderr bans=$bans
                    315:       if {![regexp {divide by zero} $bans]} exit
                    316:       continue
                    317:     }
                    318:     break
                    319:   }
                    320:   if {$bans} {
                    321:     make_test_case "SELECT $sqle FROM t1 WHERE $sqlb" $ans
                    322:     make_test_case "SELECT $sqle FROM t1 WHERE NOT ($sqlb)" {}
                    323:   } else {
                    324:     make_test_case "SELECT $sqle FROM t1 WHERE $sqlb" {}
                    325:     make_test_case "SELECT $sqle FROM t1 WHERE NOT ($sqlb)" $ans
                    326:   }
                    327:   if {[regexp { \| } $sqle]} {
                    328:     regsub -all { \| } $sqle { \& } sqle
                    329:     regsub -all { \| } $tcle { \& } tcle
                    330:     if {[catch {expr $tcle} ans]==0} {
                    331:       if {$bans} {
                    332:         make_test_case "SELECT $sqle FROM t1 WHERE $sqlb" $ans
                    333:       } else {
                    334:         make_test_case "SELECT $sqle FROM t1 WHERE NOT ($sqlb)" $ans
                    335:       }
                    336:     }
                    337:   }
                    338: }
                    339: 
                    340: # Terminate the test script
                    341: #
                    342: puts {finish_test}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>