Annotation of embedaddon/sqlite3/test/randexpr1.tcl, revision 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>