]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add fault-injection and other tests (and fixes) to improve coverage of vdbesort.c.
authordan <dan@noemail.net>
Mon, 8 Aug 2011 16:44:25 +0000 (16:44 +0000)
committerdan <dan@noemail.net>
Mon, 8 Aug 2011 16:44:25 +0000 (16:44 +0000)
FossilOrigin-Name: 0e6defa6aa540b413ea3f4bb6dcd86364d547067

manifest
manifest.uuid
src/vdbesort.c
test/index4.test
test/indexfault.test [new file with mode: 0644]
test/permutations.test

index dfd48315442780d9c05ae0f61838a3cf4b521c76..7c553cd034eb7d792ce6a5c2c2f5bd2313344c93 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\swith\sbuilding\slarge\sindexes\sintroduced\sby\sthe\sprevious\scommit.
-D 2011-08-06T15:09:33.468
+C Add\sfault-injection\sand\sother\stests\s(and\sfixes)\sto\simprove\scoverage\sof\svdbesort.c.
+D 2011-08-08T16:44:25.654
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -245,7 +245,7 @@ F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
 F src/vdbeaux.c 8fb978eb73a97b34d352dd3ef3bff35b1b3fa7e9
 F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
-F src/vdbesort.c 345235345a414bf387f1254fe3695bb566bf66d7
+F src/vdbesort.c e9a7d969bd5a85fc7b9f42865a71b834d26442be
 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
 F src/wal.c 0c70ad7b1cac6005fa5e2cbefd23ee05e391c290
@@ -511,8 +511,9 @@ F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
 F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
 F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
 F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
-F test/index4.test 8d737e87536cba23d4567096b6432116e2ba896f
+F test/index4.test c82a59c9ae2ac01804bdb100162dca057318f40f
 F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
+F test/indexfault.test 758a11b2e0c00609c227fa10136e9edcd1200c7f
 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
 F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
 F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
@@ -618,7 +619,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test aae89941ca0968b53633c97b5dd0d6f9f9899d27
+F test/permutations.test bfe51414b7c355a6dfb8803176808dc2e00e3783
 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -954,7 +955,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 8051c1767c4386b0f14a66742d9fac41e001eb07
-R 93dcea351d8a57ea1935b884e502f99e
+P 038ec9ea92f7661358580d999adc400da14d47f0
+R bca0e64155bd4edc59b1ae2d567af815
 U dan
-Z c870855eb410ccb3672032b9f318773d
+Z 7ff7f4144c189044a56c845ca9d84e7e
index a094757db6352460c5a75cdb25bd78a101970efd..365d6d940713722d19bcd41cc5b233ab014e7945 100644 (file)
@@ -1 +1 @@
-038ec9ea92f7661358580d999adc400da14d47f0
\ No newline at end of file
+0e6defa6aa540b413ea3f4bb6dcd86364d547067
\ No newline at end of file
index 640c7acac71f7df248b7693f558e566ea4e89a9f..369b4d9f55126a89b136ef952cf167f9667c445c 100644 (file)
@@ -396,8 +396,10 @@ static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
       /* Make sure the aMalloc[] buffer is large enough for the record */
       if( rc==SQLITE_OK && nKey>nMalloc ){
         aMalloc = sqlite3DbReallocOrFree(db, aMalloc, nKey);
-        if( !aMalloc ){
-          rc = SQLITE_NOMEM;
+        if( !aMalloc ){ 
+          rc = SQLITE_NOMEM; 
+        }else{
+          nMalloc = nKey;
         }
       }
 
@@ -410,9 +412,10 @@ static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
         }
       }
 
+      if( rc!=SQLITE_OK ) break;
     }
 
-    assert( pSorter->nBtree==(
+    assert( rc!=SQLITE_OK || pSorter->nBtree==(
           iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
     ));
     pSorter->iWriteOff = iWriteOff;
@@ -648,6 +651,13 @@ int sqlite3VdbeSorterRowkey(sqlite3 *db, VdbeCursor *pCsr, Mem *pOut){
   VdbeSorterIter *pIter;
 
   pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+
+  /* Coverage testing note: As things are currently, this call will always
+  ** succeed. This is because the memory cell passed by the VDBE layer 
+  ** happens to be the same one as was used to assemble the keys before they
+  ** were passed to the sorter - meaning it is always large enough for the
+  ** largest key. But this could change very easily, so we leave the call
+  ** to sqlite3VdbeMemGrow() in. */
   if( sqlite3VdbeMemGrow(pOut, pIter->nKey, 0) ){
     return SQLITE_NOMEM;
   }
index 9bacf84eb8aaf05beee9a3b3f17ff08ff66be8eb..6400e34e4ef82da6436de59f7199d1fd4b4d49b1 100644 (file)
@@ -67,4 +67,46 @@ ifcapable memorymanage {
 }
 
 
+do_execsql_test 1.6 {
+  BEGIN;
+    DROP TABLE t1;
+    CREATE TABLE t1(x);
+    INSERT INTO t1 VALUES('a');
+    INSERT INTO t1 VALUES('b');
+    INSERT INTO t1 VALUES('c');
+    INSERT INTO t1 VALUES('d');
+    INSERT INTO t1 VALUES('e');
+    INSERT INTO t1 VALUES('f');
+    INSERT INTO t1 VALUES('g');
+    INSERT INTO t1 VALUES(NULL);
+    INSERT INTO t1 SELECT randomblob(1202) FROM t1;     --    16
+    INSERT INTO t1 SELECT randomblob(2202) FROM t1;     --    32
+    INSERT INTO t1 SELECT randomblob(3202) FROM t1;     --    64
+    INSERT INTO t1 SELECT randomblob(4202) FROM t1;     --   128
+    INSERT INTO t1 SELECT randomblob(5202) FROM t1;     --   256
+  COMMIT;
+  CREATE INDEX i1 ON t1(x); 
+  PRAGMA integrity_check
+} {ok}
+
+do_execsql_test 1.7 {
+  BEGIN;
+    DROP TABLE t1;
+    CREATE TABLE t1(x);
+    INSERT INTO t1 VALUES('a');
+  COMMIT;
+  CREATE INDEX i1 ON t1(x); 
+  PRAGMA integrity_check
+} {ok}
+
+do_execsql_test 1.8 {
+  BEGIN;
+    DROP TABLE t1;
+    CREATE TABLE t1(x);
+  COMMIT;
+  CREATE INDEX i1 ON t1(x); 
+  PRAGMA integrity_check
+} {ok}
+
+
 finish_test
diff --git a/test/indexfault.test b/test/indexfault.test
new file mode 100644 (file)
index 0000000..e1d0177
--- /dev/null
@@ -0,0 +1,248 @@
+# 2011 August 08
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    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.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+source $testdir/malloc_common.tcl
+
+set testprefix indexfault
+
+#-------------------------------------------------------------------------
+# These tests - indexfault-1.* - Build an index on a smallish table with
+# all different kinds of fault-injection. The CREATE INDEX is run once
+# with default options and once with a 50KB soft-heap-limit.
+#
+do_execsql_test 1.0 {
+  BEGIN;
+    CREATE TABLE t1(x);
+    INSERT INTO t1 VALUES(randomblob(202));
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     2
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     4
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     8
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    16
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    32
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    64
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --   128
+    INSERT INTO t1 SELECT randomblob(202) FROM t1;     --   256
+  COMMIT;
+}
+faultsim_save_and_close
+
+do_faultsim_test 1.1 -prep {
+  faultsim_restore_and_reopen
+} -body {
+  execsql { CREATE INDEX i1 ON t1(x) }
+  faultsim_test_result {0 {}} 
+  faultsim_integrity_check
+}
+ifcapable memorymanage {
+  set soft_limit [sqlite3_soft_heap_limit 50000]
+  do_faultsim_test 2.1 -prep {
+    faultsim_restore_and_reopen
+  } -body {
+    execsql { CREATE INDEX i1 ON t1(x) }
+    faultsim_test_result {0 {}} 
+  }
+  sqlite3_soft_heap_limit $soft_limit
+}
+
+#-------------------------------------------------------------------------
+# These are similar to the indexfault-1.* tests, except they create an
+# index with more than one column.
+#
+sqlite3 db test.db
+do_execsql_test 2.0 {
+  BEGIN;
+    DROP TABLE IF EXISTS t1;
+    CREATE TABLE t1(t,u,v,w,x,y,z);
+    INSERT INTO t1 VALUES(
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30)
+    );
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 2
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 4
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 8
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 16
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 32
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 64
+    INSERT INTO t1 SELECT 
+      randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+      randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 128
+  COMMIT;
+}
+faultsim_save_and_close
+
+do_faultsim_test 2.1 -prep {
+  faultsim_restore_and_reopen
+} -body {
+  execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
+  faultsim_test_result {0 {}} 
+  faultsim_integrity_check
+}
+ifcapable memorymanage {
+  set soft_limit [sqlite3_soft_heap_limit 50000]
+  do_faultsim_test 2.2 -prep {
+    faultsim_restore_and_reopen
+  } -body {
+    execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
+    faultsim_test_result {0 {}} 
+  }
+  sqlite3_soft_heap_limit $soft_limit
+}
+
+#-------------------------------------------------------------------------
+# The following tests - indexfault-2.* - all attempt to build a index
+# on table t1 in the main database with injected IO errors. Individual
+# test cases work as follows:
+#
+#   3.1: IO errors injected into xOpen() calls.
+#   3.2: As 7.1, but with a low (50KB) soft-heap-limit.
+#
+#   3.3: IO errors injected into the first 200 write() calls made on the
+#        second temporary file.
+#   3.4: As 7.3, but with a low (50KB) soft-heap-limit.
+#
+#
+
+# Set up the custom fault-injector. This is further configured by using
+# different values for $::custom_filter and different implementations
+# of Tcl proc [xCustom] for each test case.
+#
+set FAULTSIM(custom)            [list      \
+  -injectinstall   custom_injectinstall    \
+  -injectstart     custom_injectstart      \
+  -injectstop      custom_injectstop       \
+  -injecterrlist   {{1 {disk I/O error}}}  \
+  -injectuninstall custom_injectuninstall  \
+]
+proc custom_injectinstall {} {
+  testvfs shmfault -default true
+  shmfault filter $::custom_filter
+  shmfault script xCustom
+}
+proc custom_injectuninstall {} {
+  catch {db  close}
+  catch {db2 close}
+  shmfault delete
+}
+set ::custom_ifail -1
+set ::custom_nfail -1
+proc custom_injectstart {iFail} {
+  set ::custom_ifail $iFail
+  set ::custom_nfail 0
+}
+proc custom_injectstop {} {
+  set ::custom_ifail -1
+  return $::custom_nfail
+}
+
+# Set up a table to build indexes on. Save the setup using the 
+# [faultsim_save_and_close] mechanism.
+# 
+sqlite3 db test.db
+do_execsql_test 3.0 {
+  BEGIN;
+    DROP TABLE IF EXISTS t1;
+    CREATE TABLE t1(x);
+    INSERT INTO t1 VALUES(randomblob(11000));
+    INSERT INTO t1 SELECT randomblob(11001) FROM t1;     --     2
+    INSERT INTO t1 SELECT randomblob(11002) FROM t1;     --     4
+    INSERT INTO t1 SELECT randomblob(11003) FROM t1;     --     8
+    INSERT INTO t1 SELECT randomblob(11004) FROM t1;     --    16
+    INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    32
+    INSERT INTO t1 SELECT randomblob(11006) FROM t1;     --    64
+    INSERT INTO t1 SELECT randomblob(11007) FROM t1;     --   128
+    INSERT INTO t1 SELECT randomblob(11008) FROM t1;     --   256
+    INSERT INTO t1 SELECT randomblob(11009) FROM t1;     --   512
+  COMMIT;
+}
+faultsim_save_and_close
+
+set ::custom_filter xOpen
+proc xCustom {args} {
+  incr ::custom_ifail -1
+  if {$::custom_ifail==0} {
+    incr ::custom_nfail
+    return "SQLITE_IOERR"
+  }
+  return "SQLITE_OK"
+}
+do_faultsim_test 3.1 -faults custom -prep {
+  faultsim_restore_and_reopen
+} -body {
+  execsql { CREATE INDEX i1 ON t1(x) }
+  faultsim_test_result {0 {}} 
+}
+ifcapable memorymanage {
+  set soft_limit [sqlite3_soft_heap_limit 50000]
+  do_faultsim_test 3.2 -faults custom -prep {
+    faultsim_restore_and_reopen
+  } -body {
+    execsql { CREATE INDEX i1 ON t1(x) }
+    faultsim_test_result {0 {}} 
+  }
+  sqlite3_soft_heap_limit $soft_limit
+}
+
+set ::custom_filter {xOpen xWrite}
+proc xCustom {method args} {
+  if {$method == "xOpen"} {
+    if {[lindex $args 0] == ""} {
+      incr ::nTmpOpen 1
+      if {$::nTmpOpen == 3} { return "failme" }
+    }
+    return "SQLITE_OK"
+  }
+  if {$::custom_ifail<200 && [lindex $args 1] == "failme"} {
+    incr ::custom_ifail -1
+    if {$::custom_ifail==0} {
+      incr ::custom_nfail
+      return "SQLITE_IOERR"
+    }
+  }
+  return "SQLITE_OK"
+}
+
+do_faultsim_test 3.3 -faults custom -prep {
+  faultsim_restore_and_reopen
+  set ::nTmpOpen 0
+} -body {
+  execsql { CREATE INDEX i1 ON t1(x) }
+  faultsim_test_result {0 {}} 
+}
+
+ifcapable memorymanage {
+  set soft_limit [sqlite3_soft_heap_limit 50000]
+  do_faultsim_test 3.4 -faults custom -prep {
+    faultsim_restore_and_reopen
+    set ::nTmpOpen 0
+  } -body {
+    execsql { CREATE INDEX i1 ON t1(x) }
+    faultsim_test_result {0 {}} 
+  }
+  sqlite3_soft_heap_limit $soft_limit
+}
+
+finish_test
index 57f69462a58c88b691b185cb9734f63452d43e4b..8459aa2819462d8a4c23a8b4e805b13c7e746529 100644 (file)
@@ -111,7 +111,7 @@ set allquicktests [test_set $alltests -exclude {
   thread003.test thread004.test thread005.test trans2.test vacuum3.test 
   incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
   vtab_err.test walslow.test walcrash.test 
-  walthread.test rtree3.test
+  walthread.test rtree3.test indexfault.test
 }]
 if {[info exists ::env(QUICKTEST_INCLUDE)]} {
   set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]