diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/analyzer1.test | 5 | ||||
-rw-r--r-- | test/corruptI.test | 2 | ||||
-rw-r--r-- | test/e_walauto.test | 1 | ||||
-rw-r--r-- | test/extraquick.test | 16 | ||||
-rw-r--r-- | test/filectrl.test | 1 | ||||
-rw-r--r-- | test/fts3d.test | 2 | ||||
-rw-r--r-- | test/fts4incr.test | 4 | ||||
-rw-r--r-- | test/fts4unicode.test | 14 | ||||
-rw-r--r-- | test/fuzzcheck.c | 44 | ||||
-rw-r--r-- | test/fuzzdata1.db | bin | 4199424 -> 4398080 bytes | |||
-rw-r--r-- | test/fuzzdata3.db | bin | 10724352 -> 11777024 bytes | |||
-rw-r--r-- | test/in.test | 20 | ||||
-rw-r--r-- | test/index5.test | 6 | ||||
-rw-r--r-- | test/index6.test | 19 | ||||
-rw-r--r-- | test/join.test | 26 | ||||
-rw-r--r-- | test/permutations.test | 17 | ||||
-rw-r--r-- | test/progress.test | 1 | ||||
-rw-r--r-- | test/releasetest.tcl | 7 | ||||
-rw-r--r-- | test/select7.test | 20 | ||||
-rw-r--r-- | test/select8.test | 1 | ||||
-rw-r--r-- | test/shared4.test | 1 | ||||
-rw-r--r-- | test/speedtest1.c | 20 | ||||
-rw-r--r-- | test/sqldiff1.test | 5 | ||||
-rw-r--r-- | test/table.test | 16 | ||||
-rw-r--r-- | test/tester.tcl | 220 | ||||
-rw-r--r-- | test/vtab1.test | 3 | ||||
-rw-r--r-- | test/whereG.test | 37 |
27 files changed, 415 insertions, 93 deletions
diff --git a/test/analyzer1.test b/test/analyzer1.test index 7da564ea2..ac46704fb 100644 --- a/test/analyzer1.test +++ b/test/analyzer1.test @@ -24,6 +24,11 @@ if {$tcl_platform(platform)=="windows"} { } else { set PROG "./sqlite3_analyzer" } +if {![file exe $PROG]} { + puts "analyzer1 cannot run because $PROG is not available" + finish_test + return +} db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db diff --git a/test/corruptI.test b/test/corruptI.test index 2d4a481c7..64323d960 100644 --- a/test/corruptI.test +++ b/test/corruptI.test @@ -204,7 +204,7 @@ do_execsql_test 6.0 { } {} do_test 6.1 { db close - hexio_write test.db 616 EAFFFFFF0202 + hexio_write test.db 616 8FFFFFFF7F02 sqlite3 db test.db breakpoint execsql { DELETE FROM t1 WHERE rowid=2 } diff --git a/test/e_walauto.test b/test/e_walauto.test index a1f4eb707..093b13f94 100644 --- a/test/e_walauto.test +++ b/test/e_walauto.test @@ -171,7 +171,6 @@ foreach {tn code} { # set ::busy_callback_count 0 proc busy_callback {args} { - puts Hello incr ::busy_callback_count return 0 } diff --git a/test/extraquick.test b/test/extraquick.test new file mode 100644 index 000000000..f453564e7 --- /dev/null +++ b/test/extraquick.test @@ -0,0 +1,16 @@ +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file runs most of the tests run by veryquick.test except for those +# that take a long time. +# + +set testdir [file dirname $argv0] +source $testdir/permutations.test + +run_test_suite extraquick + +finish_test diff --git a/test/filectrl.test b/test/filectrl.test index 1d878bf96..28fecee92 100644 --- a/test/filectrl.test +++ b/test/filectrl.test @@ -39,7 +39,6 @@ do_test filectrl-1.5 { do_test filectrl-1.6 { sqlite3 db test.db set fn [file_control_tempfilename db] - puts -nonewline \[$fn\] set fn } {/etilqs_/} db close diff --git a/test/fts3d.test b/test/fts3d.test index 5c04ead0a..83af4d2a3 100644 --- a/test/fts3d.test +++ b/test/fts3d.test @@ -213,7 +213,7 @@ do_test fts3d-4.matches { {0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \ {0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}] -puts [db eval {SELECT c FROM t1 } ] +db eval {SELECT c FROM t1 } check_terms_all fts3d-4.1 {a four is test that this was} check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]} check_doclist_all fts3d-4.1.2 four {} diff --git a/test/fts4incr.test b/test/fts4incr.test index 17212efce..92104888b 100644 --- a/test/fts4incr.test +++ b/test/fts4incr.test @@ -47,7 +47,9 @@ foreach {tn q res} { do_execsql_test 2.$tn.$s $q $res set t($s) [lindex [time [list execsql $q] 100] 0] } - puts "with optimization: $t(0) without: $t(1)" + if {0} { + puts "with optimization: $t(0) without: $t(1)" + } } do_test 2.1 { diff --git a/test/fts4unicode.test b/test/fts4unicode.test index f237119a1..500cfcdca 100644 --- a/test/fts4unicode.test +++ b/test/fts4unicode.test @@ -362,11 +362,17 @@ ifcapable icu { lappend tokenizers icu } # Some tests to check that the tokenizers can both identify white-space # codepoints. All codepoints tested below are of type "Zs" in the # UnicodeData.txt file. +# +# Note that codepoint 6158 has changed from Zs to Cf in recent versions +# of UnicodeData.txt. So take that into account for the "icu" tests. +# foreach T $tokenizers { do_isspace_test 6.$T.1 $T 32 do_isspace_test 6.$T.2 $T 160 do_isspace_test 6.$T.3 $T 5760 - do_isspace_test 6.$T.4 $T 6158 + if {$T!="icu"} { + do_isspace_test 6.$T.4 $T 6158 + } do_isspace_test 6.$T.5 $T 8192 do_isspace_test 6.$T.6 $T 8193 do_isspace_test 6.$T.7 $T 8194 @@ -382,7 +388,11 @@ foreach T $tokenizers { do_isspace_test 6.$T.17 $T 8287 do_isspace_test 6.$T.18 $T 12288 - do_isspace_test 6.$T.19 $T {32 160 5760 6158} + if {$T!="icu"} { + do_isspace_test 6.$T.19 $T {32 160 5760 6158} + } else { + do_isspace_test 6.$T.19 $T {32 160 5760 8192} + } do_isspace_test 6.$T.20 $T {8192 8193 8194 8195} do_isspace_test 6.$T.21 $T {8196 8197 8198 8199} do_isspace_test 6.$T.22 $T {8200 8201 8202 8239} diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 6dc2a6e7f..f637e6463 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -10,8 +10,8 @@ ** ************************************************************************* ** -** This is a utility program designed to aid running regressions tests -** on SQLite library using data from an external fuzzer, such as American +** This is a utility program designed to aid running regressions tests on +** the SQLite library using data from an external fuzzer, such as American ** Fuzzy Lop (AFL) (http://lcamtuf.coredump.cx/afl/). ** ** This program reads content from an SQLite database file with the following @@ -25,16 +25,44 @@ ** sqlid INTEGER PRIMARY KEY, -- SQL script id ** sqltext TEXT -- Text of SQL statements to run ** ); +** CREATE TABLE IF NOT EXISTS readme( +** msg TEXT -- Human-readable description of this test collection +** ); ** ** For each database file in the DB table, the SQL text in the XSQL table -** is run against that database. This program is looking for crashes, -** assertion faults, and/or memory leaks. No attempt is made to verify -** the output. The assumption is that either all of the database files -** or all of the SQL statements are malformed inputs, generated by a fuzzer, -** that need to be checked to make sure they do not present a security risk. +** is run against that database. All README.MSG values are printed prior +** to the start of the test (unless the --quiet option is used). If the +** DB table is empty, then all entries in XSQL are run against an empty +** in-memory database. +** +** This program is looking for crashes, assertion faults, and/or memory leaks. +** No attempt is made to verify the output. The assumption is that either all +** of the database files or all of the SQL statements are malformed inputs, +** generated by a fuzzer, that need to be checked to make sure they do not +** present a security risk. ** ** This program also includes some command-line options to help with -** creation and maintenance of the source content database. +** creation and maintenance of the source content database. The command +** +** ./fuzzcheck database.db --load-sql FILE... +** +** Loads all FILE... arguments into the XSQL table. The --load-db option +** works the same but loads the files into the DB table. The -m option can +** be used to initialize the README table. The "database.db" file is created +** if it does not previously exist. Example: +** +** ./fuzzcheck new.db --load-sql *.sql +** ./fuzzcheck new.db --load-db *.db +** ./fuzzcheck new.db -m 'New test cases' +** +** The three commands above will create the "new.db" file and initialize all +** tables. Then do "./fuzzcheck new.db" to run the tests. +** +** DEBUGGING HINTS: +** +** If fuzzcheck does crash, it can be run in the debugger and the content +** of the global variable g.zTextName[] will identify the specific XSQL and +** DB values that were running when the crash occurred. */ #include <stdio.h> #include <stdlib.h> diff --git a/test/fuzzdata1.db b/test/fuzzdata1.db Binary files differindex 222e598a4..4b4a6b574 100644 --- a/test/fuzzdata1.db +++ b/test/fuzzdata1.db diff --git a/test/fuzzdata3.db b/test/fuzzdata3.db Binary files differindex 376459f2d..34ff5f975 100644 --- a/test/fuzzdata3.db +++ b/test/fuzzdata3.db diff --git a/test/in.test b/test/in.test index de38c2245..3a42e84b9 100644 --- a/test/in.test +++ b/test/in.test @@ -450,28 +450,42 @@ do_test in-12.10 { SELECT a FROM t3 UNION ALL SELECT a, b FROM t2 ); } -} {1 {only a single result allowed for a SELECT that is part of an expression}} +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} do_test in-12.11 { catchsql { SELECT * FROM t2 WHERE a IN ( SELECT a FROM t3 UNION SELECT a, b FROM t2 ); } -} {1 {only a single result allowed for a SELECT that is part of an expression}} +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} do_test in-12.12 { catchsql { SELECT * FROM t2 WHERE a IN ( SELECT a FROM t3 EXCEPT SELECT a, b FROM t2 ); } -} {1 {only a single result allowed for a SELECT that is part of an expression}} +} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}} do_test in-12.13 { catchsql { SELECT * FROM t2 WHERE a IN ( SELECT a FROM t3 INTERSECT SELECT a, b FROM t2 ); } +} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}} +do_test in-12.14 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a, b FROM t3 UNION ALL SELECT a, b FROM t2 + ); + } } {1 {only a single result allowed for a SELECT that is part of an expression}} +do_test in-12.15 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a, b FROM t3 UNION ALL SELECT a FROM t2 + ); + } +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} }; #ifcapable compound diff --git a/test/index5.test b/test/index5.test index e369d7571..4c0aa0431 100644 --- a/test/index5.test +++ b/test/index5.test @@ -67,8 +67,10 @@ do_test 1.3 { } set iPrev $iNext } - puts -nonewline \ - " (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)" + if {0} { + puts -nonewline \ + " (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)" + } expr {$nForward > 2*($nBackward + $nNoncont)} } {1} diff --git a/test/index6.test b/test/index6.test index 69fae49fe..e15820290 100644 --- a/test/index6.test +++ b/test/index6.test @@ -327,4 +327,23 @@ do_execsql_test index6-8.2 { 3 three value 3 } +# 2015-06-11. Assertion fault found by AFL +# +do_execsql_test index6-9.1 { + CREATE TABLE t9(a int, b int, c int); + CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20); + INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5),(NULL,7,3); + UPDATE t9 SET b=c WHERE a in (10,12,20); + SELECT a,b,c,'|' FROM t9 ORDER BY a; +} {{} 7 3 | 1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |} +do_execsql_test index6-9.2 { + DROP TABLE t9; + CREATE TABLE t9(a int, b int, c int, PRIMARY KEY(a)) WITHOUT ROWID; + CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20); + INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5); + UPDATE t9 SET b=c WHERE a in (10,12,20); + SELECT a,b,c,'|' FROM t9 ORDER BY a; +} {1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |} + + finish_test diff --git a/test/join.test b/test/join.test index 4c83fa6b3..2b6951213 100644 --- a/test/join.test +++ b/test/join.test @@ -687,4 +687,30 @@ ifcapable pragma&&compileoption_diags { } } + +#------------------------------------------------------------------------- +# Test a problem with reordering tables following a LEFT JOIN. +# +do_execsql_test join-13.0 { + CREATE TABLE aa(a); + CREATE TABLE bb(b); + CREATE TABLE cc(c); + + INSERT INTO aa VALUES(45); + INSERT INTO cc VALUES(45); + INSERT INTO cc VALUES(45); +} + +do_execsql_test join-13.1 { + SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a; +} {45 {} 45 45 {} 45} + +# In the following, the order of [cc] and [bb] must not be exchanged, even +# though this would be helpful if the query used an inner join. +do_execsql_test join-13.2 { + CREATE INDEX ccc ON cc(c); + SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a; +} {45 {} 45 45 {} 45} + + finish_test diff --git a/test/permutations.test b/test/permutations.test index 05c4ff92b..9881efb71 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -96,7 +96,7 @@ if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test - mallocAll.test rtree.test full.test + mallocAll.test rtree.test full.test extraquick.test }] set allquicktests [test_set $alltests -exclude { @@ -146,11 +146,22 @@ if {[info exists ::env(TEST_FAILURE)]} { lappend ::testsuitelist xxx test_suite "veryquick" -prefix "" -description { - "Very" quick test suite. Runs in less than 5 minutes on a workstation. + "Very" quick test suite. Runs in minutes on a workstation. This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* +] + +test_suite "extraquick" -prefix "" -description { + "Extra" quick test suite. Runs in a few minutes on a workstation. + This test suite is the same as the "veryquick" tests, except that + slower tests are omitted. +} -files [ + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* \ + wal3.test fts4merge* sort2.test mmap1.test walcrash* \ + percentile.test where8m.test walcksum.test savepoint3.test \ + fuzzer1.test fuzzer3.test fts3expr3.test ] test_suite "mmap" -prefix "mm-" -description { diff --git a/test/progress.test b/test/progress.test index 993426aa2..f6d722924 100644 --- a/test/progress.test +++ b/test/progress.test @@ -164,7 +164,6 @@ do_test progress-1.7 { } set ::res [list] - explain {SELECT a, b, c FROM abc} db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c db progress 5 "expr 1" diff --git a/test/releasetest.tcl b/test/releasetest.tcl index a120ddf33..6e475c9d2 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -547,7 +547,10 @@ proc process_options {argv} { puts " --srcdir $::SRCDIR" puts " --platform [list $platform]" puts " --config [list $config]" - if {$::QUICK} {puts " --quick"} + if {$::QUICK} { + if {$::QUICK==1} {puts " --quick"} + if {$::QUICK==2} {puts " --veryquick"} + } if {$::MSVC} {puts " --msvc"} if {$::BUILDONLY} {puts " --buildonly"} if {$::DRYRUN} {puts " --dryrun"} @@ -645,7 +648,7 @@ proc main {argv} { } if {$target ne "checksymbols"} { switch -- $::QUICK { - 1 {set target test} + 1 {set target quicktest} 2 {set target smoketest} } if {$::BUILDONLY} { diff --git a/test/select7.test b/test/select7.test index 6816b9fcb..9ed535774 100644 --- a/test/select7.test +++ b/test/select7.test @@ -15,6 +15,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix select7 ifcapable compound { @@ -201,4 +202,23 @@ do_test select7-7.7 { } } {text 123} +do_execsql_test 8.0 { + CREATE TABLE t01(x, y); + CREATE TABLE t02(x, y); +} + +do_catchsql_test 8.1 { + SELECT * FROM ( + SELECT * FROM t01 UNION SELECT x FROM t02 + ) WHERE y=1 +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} + +do_catchsql_test 8.2 { + CREATE VIEW v0 as SELECT x, y FROM t01 UNION SELECT x FROM t02; + EXPLAIN QUERY PLAN SELECT * FROM v0 WHERE x='0' OR y; +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} + + finish_test + + diff --git a/test/select8.test b/test/select8.test index 98626641b..39b273949 100644 --- a/test/select8.test +++ b/test/select8.test @@ -32,7 +32,6 @@ set result [execsql { FROM songs GROUP BY LOWER(artist) }] -puts result=$result do_test select8-1.1 { execsql { SELECT DISTINCT artist,sum(timesplayed) AS total diff --git a/test/shared4.test b/test/shared4.test index 83925b06e..88959db42 100644 --- a/test/shared4.test +++ b/test/shared4.test @@ -16,7 +16,6 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl db close -puts hello # This script is only valid if we are running shared-cache mode in a # threadsafe-capable database engine. diff --git a/test/speedtest1.c b/test/speedtest1.c index 8f3f57955..db343d81f 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -43,6 +43,9 @@ static const char zHelp[] = #include <string.h> #include <ctype.h> +#if SQLITE_VERSION_NUMBER<3005000 +# define sqlite3_int64 sqlite_int64 +#endif #ifdef SQLITE_ENABLE_OTA # include "sqlite3ota.h" #endif @@ -143,6 +146,9 @@ static int integerValue(const char *zArg){ /* Return the current wall-clock time, in milliseconds */ sqlite3_int64 speedtest1_timestamp(void){ +#if SQLITE_VERSION_NUMBER<3005000 + return 0; +#else static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); @@ -157,6 +163,7 @@ sqlite3_int64 speedtest1_timestamp(void){ t = (sqlite3_int64)(r*86400000.0); } return t; +#endif } /* Return a pseudo-random unsigned integer */ @@ -306,7 +313,7 @@ static void printSql(const char *zSql){ if( g.bExplain ) printf("EXPLAIN "); printf("%.*s;\n", n, zSql); if( g.bExplain -#if SQLITE_VERSION_NUMBER>=3007010 +#if SQLITE_VERSION_NUMBER>=3007017 && ( sqlite3_strglob("CREATE *", zSql)==0 || sqlite3_strglob("DROP *", zSql)==0 || sqlite3_strglob("ALTER *", zSql)==0 @@ -374,12 +381,15 @@ void speedtest1_run(void){ } } } +#if SQLITE_VERSION_NUMBER>=3006001 if( g.bReprepare ){ sqlite3_stmt *pNew; sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0); sqlite3_finalize(g.pStmt); g.pStmt = pNew; - }else{ + }else +#endif + { sqlite3_reset(g.pStmt); } } @@ -1273,6 +1283,7 @@ int main(int argc, char **argv){ fatal_error(zHelp, argv[0]); } #endif +#if SQLITE_VERSION_NUMBER>=3006001 if( nHeap>0 ){ pHeap = malloc( nHeap ); if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap); @@ -1296,16 +1307,19 @@ int main(int argc, char **argv){ if( nLook>0 ){ sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); } +#endif /* Open the database and the input file */ if( sqlite3_open(zDbName, &g.db) ){ fatal_error("Cannot open database file: %s\n", zDbName); } +#if SQLITE_VERSION_NUMBER>=3006001 if( nLook>0 && szLook>0 ){ pLook = malloc( nLook*szLook ); rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook); if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); } +#endif /* Set database connection options */ sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0); @@ -1387,6 +1401,7 @@ int main(int argc, char **argv){ sqlite3_close(g.db); +#if SQLITE_VERSION_NUMBER>=3006001 /* Global memory usage statistics printed after the database connection ** has closed. Memory usage should be zero at this point. */ if( showStats ){ @@ -1407,6 +1422,7 @@ int main(int argc, char **argv){ sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0); printf("-- Largest Scratch Allocation: %d bytes\n", iHi); } +#endif /* Release memory */ free( pLook ); diff --git a/test/sqldiff1.test b/test/sqldiff1.test index 723b7a5e1..3201fb365 100644 --- a/test/sqldiff1.test +++ b/test/sqldiff1.test @@ -19,6 +19,11 @@ if {$tcl_platform(platform)=="windows"} { } else { set PROG "./sqldiff" } +if {![file exe $PROG]} { + puts "sqldiff cannot run because $PROG is not available" + finish_test + return +} db close forcedelete test.db test2.db sqlite3 db test.db diff --git a/test/table.test b/test/table.test index faa9712bf..2aec6473e 100644 --- a/test/table.test +++ b/test/table.test @@ -808,4 +808,20 @@ do_execsql_test table-17.1 { SELECT p, q, '|' FROM t3 ORDER BY p; } {1 1 | 2 2 |} +# 2015-06-16 +# Ticket [https://www.sqlite.org/src/tktview/873cae2b6e25b1991ce5e9b782f9cd0409b96063] +# Make sure a CREATE TABLE AS statement correctly rolls back partial changes to the +# sqlite_master table when the SELECT on the right-hand side aborts. +# +do_catchsql_test table-18.1 { + DROP TABLE IF EXISTS t1; + BEGIN; + CREATE TABLE t1 AS SELECT zeroblob(2e20); +} {1 {string or blob too big}} +do_execsql_test table-18.2 { + COMMIT; + PRAGMA integrity_check; +} {ok} + + finish_test diff --git a/test/tester.tcl b/test/tester.tcl index 794ea4a40..8022d6a53 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -81,6 +81,12 @@ # permutation # presql # +# Command to test whether or not --verbose=1 was specified on the command +# line (returns 0 for not-verbose, 1 for verbose and 2 for "verbose in the +# output file only"). +# +# verbose +# # Set the precision of FP arithmatic used by the interpreter. And # configure SQLite to take database file locks on the page that begins @@ -388,6 +394,9 @@ if {[info exists cmdlinearg]==0} { # --file-retry-delay=N # --start=[$permutation:]$testfile # --match=$pattern + # --verbose=$val + # --output=$filename + # --help # set cmdlinearg(soft-heap-limit) 0 set cmdlinearg(maxerror) 1000 @@ -399,6 +408,8 @@ if {[info exists cmdlinearg]==0} { set cmdlinearg(file-retry-delay) 0 set cmdlinearg(start) "" set cmdlinearg(match) "" + set cmdlinearg(verbose) "" + set cmdlinearg(output) "" set leftover [list] foreach a $argv { @@ -457,6 +468,22 @@ if {[info exists cmdlinearg]==0} { set ::G(match) $cmdlinearg(match) if {$::G(match) == ""} {unset ::G(match)} } + + {^-+output=.+$} { + foreach {dummy cmdlinearg(output)} [split $a =] break + if {$cmdlinearg(verbose)==""} { + set cmdlinearg(verbose) 2 + } + } + {^-+verbose=.+$} { + foreach {dummy cmdlinearg(verbose)} [split $a =] break + if {$cmdlinearg(verbose)=="file"} { + set cmdlinearg(verbose) 2 + } elseif {[string is boolean -strict $cmdlinearg(verbose)]==0} { + error "option --verbose= must be set to a boolean or to \"file\"" + } + } + default { lappend leftover $a } @@ -484,6 +511,16 @@ if {[info exists cmdlinearg]==0} { if {$cmdlinearg(malloctrace)} { sqlite3_memdebug_backtrace $cmdlinearg(backtrace) } + + if {$cmdlinearg(output)!=""} { + puts "Copying output to file $cmdlinearg(output)" + set ::G(output_fd) [open $cmdlinearg(output) w] + fconfigure $::G(output_fd) -buffering line + } + + if {$cmdlinearg(verbose)==""} { + set cmdlinearg(verbose) 1 + } } # Update the soft-heap-limit each time this script is run. In that @@ -554,7 +591,7 @@ proc fail_test {name} { set nFail [set_test_counter errors] if {$nFail>=$::cmdlinearg(maxerror)} { - puts "*** Giving up..." + output2 "*** Giving up..." finalize_testing } } @@ -562,7 +599,7 @@ proc fail_test {name} { # Remember a warning message to be displayed at the conclusion of all testing # proc warning {msg {append 1}} { - puts "Warning: $msg" + output2 "Warning: $msg" set warnList [set_test_counter warn_list] if {$append} { lappend warnList $msg @@ -577,6 +614,61 @@ proc incr_ntest {} { set_test_counter count [expr [set_test_counter count] + 1] } +# Return true if --verbose=1 was specified on the command line. Otherwise, +# return false. +# +proc verbose {} { + return $::cmdlinearg(verbose) +} + +# Use the following commands instead of [puts] for test output within +# this file. Test scripts can still use regular [puts], which is directed +# to stdout and, if one is open, the --output file. +# +# output1: output that should be printed if --verbose=1 was specified. +# output2: output that should be printed unconditionally. +# output2_if_no_verbose: output that should be printed only if --verbose=0. +# +proc output1 {args} { + set v [verbose] + if {$v==1} { + uplevel output2 $args + } elseif {$v==2} { + uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end] + } +} +proc output2 {args} { + set nArg [llength $args] + uplevel puts $args +} +proc output2_if_no_verbose {args} { + set v [verbose] + if {$v==0} { + uplevel output2 $args + } elseif {$v==2} { + uplevel puts [lrange $args 0 end-1] stdout [lrange $args end end] + } +} + +# Override the [puts] command so that if no channel is explicitly +# specified the string is written to both stdout and to the file +# specified by "--output=", if any. +# +proc puts_override {args} { + set nArg [llength $args] + if {$nArg==1 || ($nArg==2 && [string first [lindex $args 0] -nonewline]==0)} { + uplevel puts_original $args + if {[info exists ::G(output_fd)]} { + uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end] + } + } else { + # A channel was explicitly specified. + uplevel puts_original $args + } +} +rename puts puts_original +proc puts {args} { uplevel puts_override $args } + # Invoke the do_test procedure to run a single test # @@ -604,12 +696,13 @@ proc do_test {name cmd expected} { } incr_ntest - puts -nonewline $name... + output1 -nonewline $name... flush stdout if {![info exists ::G(match)] || [string match $::G(match) $name]} { if {[catch {uplevel #0 "$cmd;\n"} result]} { - puts "\nError: $result" + output2_if_no_verbose -nonewline $name... + output2 "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { @@ -653,14 +746,15 @@ proc do_test {name cmd expected} { # if {![info exists ::testprefix] || $::testprefix eq ""} { # error "no test prefix" # } - puts "\nExpected: \[$expected\]\n Got: \[$result\]" + output2_if_no_verbose -nonewline $name... + output2 "\nExpected: \[$expected\]\n Got: \[$result\]" fail_test $name } else { - puts " Ok" + output1 " Ok" } } } else { - puts " Omitted" + output1 " Omitted" omit_test $name "pattern mismatch" 0 } flush stdout @@ -837,7 +931,7 @@ proc delete_all_data {} { # Return the number of microseconds per statement. # proc speed_trial {name numstmt units sql} { - puts -nonewline [format {%-21.21s } $name...] + output2 -nonewline [format {%-21.21s } $name...] flush stdout set speed [time {sqlite3_exec_nr db $sql}] set tm [lindex $speed 0] @@ -847,13 +941,13 @@ proc speed_trial {name numstmt units sql} { set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]] } set u2 $units/s - puts [format {%12d uS %s %s} $tm $rate $u2] + output2 [format {%12d uS %s %s} $tm $rate $u2] global total_time set total_time [expr {$total_time+$tm}] lappend ::speed_trial_times $name $tm } proc speed_trial_tcl {name numstmt units script} { - puts -nonewline [format {%-21.21s } $name...] + output2 -nonewline [format {%-21.21s } $name...] flush stdout set speed [time {eval $script}] set tm [lindex $speed 0] @@ -863,7 +957,7 @@ proc speed_trial_tcl {name numstmt units script} { set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]] } set u2 $units/s - puts [format {%12d uS %s %s} $tm $rate $u2] + output2 [format {%12d uS %s %s} $tm $rate $u2] global total_time set total_time [expr {$total_time+$tm}] lappend ::speed_trial_times $name $tm @@ -875,19 +969,19 @@ proc speed_trial_init {name} { sqlite3 versdb :memory: set vers [versdb one {SELECT sqlite_source_id()}] versdb close - puts "SQLite $vers" + output2 "SQLite $vers" } proc speed_trial_summary {name} { global total_time - puts [format {%-21.21s %12d uS TOTAL} $name $total_time] + output2 [format {%-21.21s %12d uS TOTAL} $name $total_time] if { 0 } { sqlite3 versdb :memory: set vers [lindex [versdb one {SELECT sqlite_source_id()}] 0] versdb close - puts "CREATE TABLE IF NOT EXISTS time(version, script, test, us);" + output2 "CREATE TABLE IF NOT EXISTS time(version, script, test, us);" foreach {test us} $::speed_trial_times { - puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);" + output2 "INSERT INTO time VALUES('$vers', '$name', '$test', $us);" } } } @@ -931,75 +1025,75 @@ proc finalize_testing {} { } } if {$nKnown>0} { - puts "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\ + output2 "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\ out of $nTest tests" } else { - puts "$nErr errors out of $nTest tests" + output2 "$nErr errors out of $nTest tests" } if {$nErr>$nKnown} { - puts -nonewline "Failures on these tests:" + output2 -nonewline "Failures on these tests:" foreach x [set_test_counter fail_list] { - if {![info exists known_error($x)]} {puts -nonewline " $x"} + if {![info exists known_error($x)]} {output2 -nonewline " $x"} } - puts "" + output2 "" } foreach warning [set_test_counter warn_list] { - puts "Warning: $warning" + output2 "Warning: $warning" } run_thread_tests 1 if {[llength $omitList]>0} { - puts "Omitted test cases:" + output2 "Omitted test cases:" set prec {} foreach {rec} [lsort $omitList] { if {$rec==$prec} continue set prec $rec - puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]] + output2 [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]] } } if {$nErr>0 && ![working_64bit_int]} { - puts "******************************************************************" - puts "N.B.: The version of TCL that you used to build this test harness" - puts "is defective in that it does not support 64-bit integers. Some or" - puts "all of the test failures above might be a result from this defect" - puts "in your TCL build." - puts "******************************************************************" + output2 "******************************************************************" + output2 "N.B.: The version of TCL that you used to build this test harness" + output2 "is defective in that it does not support 64-bit integers. Some or" + output2 "all of the test failures above might be a result from this defect" + output2 "in your TCL build." + output2 "******************************************************************" } if {$::cmdlinearg(binarylog)} { vfslog finalize binarylog } if {$sqlite_open_file_count} { - puts "$sqlite_open_file_count files were left open" + output2 "$sqlite_open_file_count files were left open" incr nErr } if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 || [sqlite3_memory_used]>0} { - puts "Unfreed memory: [sqlite3_memory_used] bytes in\ + output2 "Unfreed memory: [sqlite3_memory_used] bytes in\ [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations" incr nErr ifcapable memdebug||mem5||(mem3&&debug) { - puts "Writing unfreed memory log to \"./memleak.txt\"" + output2 "Writing unfreed memory log to \"./memleak.txt\"" sqlite3_memdebug_dump ./memleak.txt } } else { - puts "All memory allocations freed - no leaks" + output2 "All memory allocations freed - no leaks" ifcapable memdebug||mem5 { sqlite3_memdebug_dump ./memusage.txt } } show_memstats - puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes" - puts "Current memory usage: [sqlite3_memory_highwater] bytes" + output2 "Maximum memory usage: [sqlite3_memory_highwater 1] bytes" + output2 "Current memory usage: [sqlite3_memory_highwater] bytes" if {[info commands sqlite3_memdebug_malloc_count] ne ""} { - puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" + output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" } if {$::cmdlinearg(malloctrace)} { - puts "Writing mallocs.sql..." + output2 "Writing mallocs.sql..." memdebug_log_sql sqlite3_memdebug_log stop sqlite3_memdebug_log clear if {[sqlite3_memory_used]>0} { - puts "Writing leaks.sql..." + output2 "Writing leaks.sql..." sqlite3_memdebug_log sync memdebug_log_sql leaks.sql } @@ -1020,30 +1114,30 @@ proc show_memstats {} { set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] set val [format {now %10d max %10d max-size %10d} \ [lindex $x 1] [lindex $x 2] [lindex $y 2]] - puts "Memory used: $val" + output1 "Memory used: $val" set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] - puts "Allocation count: $val" + output1 "Allocation count: $val" set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0] set val [format {now %10d max %10d max-size %10d} \ [lindex $x 1] [lindex $x 2] [lindex $y 2]] - puts "Page-cache used: $val" + output1 "Page-cache used: $val" set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] - puts "Page-cache overflow: $val" + output1 "Page-cache overflow: $val" set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] - puts "Scratch memory used: $val" + output1 "Scratch memory used: $val" set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0] set val [format {now %10d max %10d max-size %10d} \ [lindex $x 1] [lindex $x 2] [lindex $y 2]] - puts "Scratch overflow: $val" + output1 "Scratch overflow: $val" ifcapable yytrackmaxstackdepth { set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0] set val [format { max %10d} [lindex $x 2]] - puts "Parser stack depth: $val" + output2 "Parser stack depth: $val" } } @@ -1058,7 +1152,7 @@ proc execsql_timed {sql {db db}} { set x [uplevel [list $db eval $sql]] } 1] set tm [lindex $tm 0] - puts -nonewline " ([expr {$tm*0.001}]ms) " + output1 -nonewline " ([expr {$tm*0.001}]ms) " set x } @@ -1074,20 +1168,20 @@ proc catchsql {sql {db db}} { # Do an VDBE code dump on the SQL given # proc explain {sql {db db}} { - puts "" - puts "addr opcode p1 p2 p3 p4 p5 #" - puts "---- ------------ ------ ------ ------ --------------- -- -" + output2 "" + output2 "addr opcode p1 p2 p3 p4 p5 #" + output2 "---- ------------ ------ ------ ------ --------------- -- -" $db eval "explain $sql" {} { - puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \ + output2 [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \ $addr $opcode $p1 $p2 $p3 $p4 $p5 $comment ] } } proc explain_i {sql {db db}} { - puts "" - puts "addr opcode p1 p2 p3 p4 p5 #" - puts "---- ------------ ------ ------ ------ ---------------- -- -" + output2 "" + output2 "addr opcode p1 p2 p3 p4 p5 #" + output2 "---- ------------ ------ ------ ------ ---------------- -- -" # Set up colors for the different opcodes. Scheme is as follows: @@ -1153,18 +1247,18 @@ proc explain_i {sql {db db}} { $db eval "explain $sql" {} { if {[info exists linebreak($addr)]} { - puts "" + output2 "" } set I [string repeat " " $x($addr)] set col "" catch { set col $color($opcode) } - puts [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \ + output2 [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \ $addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment ] } - puts "---- ------------ ------ ------ ------ ---------------- -- -" + output2 "---- ------------ ------ ------ ------ ---------------- -- -" } # Show the VDBE program for an SQL statement but omit the Trace @@ -1595,9 +1689,9 @@ proc do_ioerr_test {testname args} { set nowcksum [cksum] set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}] if {$res==0} { - puts "now=$nowcksum" - puts "the=$::checksum" - puts "fwd=$::goodcksum" + output2 "now=$nowcksum" + output2 "the=$::checksum" + output2 "fwd=$::goodcksum" } set res } 1 @@ -1821,6 +1915,12 @@ proc slave_test_script {script} { interp eval tinterp [list set $var $value] } + # If output is being copied into a file, share the file-descriptor with + # the interpreter. + if {[info exists ::G(output_fd)]} { + interp share {} $::G(output_fd) tinterp + } + # The alias used to access the global test counters. tinterp alias set_test_counter set_test_counter @@ -1889,7 +1989,7 @@ proc slave_test_file {zFile} { # Add some info to the output. # - puts "Time: $tail $ms ms" + output2 "Time: $tail $ms ms" show_memstats } diff --git a/test/vtab1.test b/test/vtab1.test index cd21153f0..84de4cffa 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -56,9 +56,6 @@ ifcapable !vtab||!schema_pragmas { # We cannot create a virtual table if the module has not been registered. # do_test vtab1-1.1.1 { - explain { - CREATE VIRTUAL TABLE t1 USING echo; - } catchsql { CREATE VIRTUAL TABLE t1 USING echo; } diff --git a/test/whereG.test b/test/whereG.test index c2c54db45..110ed5dbd 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -230,4 +230,41 @@ do_eqp_test 5.3.3 { SELECT * FROM t1 WHERE likely(a=?) } {0 0 0 {SCAN TABLE t1}} +# 2015-06-18 +# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70] +# +do_execsql_test 6.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(i int, x, y, z); + INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4); + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(i int, bool char); + INSERT INTO t2 VALUES(1,'T'), (2,'F'); + SELECT count(*) FROM t1 LEFT JOIN t2 ON t1.i=t2.i AND bool='T'; + SELECT count(*) FROM t1 LEFT JOIN t2 ON likely(t1.i=t2.i) AND bool='T'; +} {4 4} + +# 2015-06-20 +# Crash discovered by AFL +# +do_execsql_test 7.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a, b, PRIMARY KEY(a,b)); + INSERT INTO t1 VALUES(9,1),(1,2); + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(x, y, PRIMARY KEY(x,y)); + INSERT INTO t2 VALUES(3,3),(4,4); + SELECT likely(a), x FROM t1, t2 ORDER BY 1, 2; +} {1 3 1 4 9 3 9 4} +do_execsql_test 7.1 { + SELECT unlikely(a), x FROM t1, t2 ORDER BY 1, 2; +} {1 3 1 4 9 3 9 4} +do_execsql_test 7.2 { + SELECT likelihood(a,0.5), x FROM t1, t2 ORDER BY 1, 2; +} {1 3 1 4 9 3 9 4} +do_execsql_test 7.3 { + SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2; +} {1 3 1 4 9 3 9 4} + + finish_test |