Home | History | Annotate | Download | only in test
      1 # 2001 October 12
      2 #
      3 # The author disclaims copyright to this source code.  In place of
      4 # a legal notice, here is a blessing:
      5 #
      6 #    May you do good and not evil.
      7 #    May you find forgiveness for yourself and forgive others.
      8 #    May you share freely, never taking more than you give.
      9 #
     10 #***********************************************************************
     11 # This file implements regression tests for SQLite library.  The
     12 # focus of this file is testing for correct handling of I/O errors
     13 # such as writes failing because the disk is full.
     14 # 
     15 # The tests in this file use special facilities that are only
     16 # available in the SQLite test fixture.
     17 #
     18 # $Id: incrvacuum_ioerr.test,v 1.6 2008/07/12 14:52:20 drh Exp $
     19 
     20 set testdir [file dirname $argv0]
     21 source $testdir/tester.tcl
     22 
     23 # If this build of the library does not support auto-vacuum, omit this
     24 # whole file.
     25 ifcapable {!autovacuum} {
     26   finish_test
     27   return
     28 }
     29 
     30 do_ioerr_test incrvacuum-ioerr-1 -cksum 1 -sqlprep {
     31   PRAGMA auto_vacuum = 'incremental';
     32   CREATE TABLE abc(a);
     33   INSERT INTO abc VALUES(randstr(1500,1500));
     34 } -sqlbody {
     35   BEGIN;
     36   CREATE TABLE abc2(a);
     37   DELETE FROM abc;
     38   PRAGMA incremental_vacuum;
     39   COMMIT;
     40 } 
     41 
     42 # do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
     43 #   db eval {
     44 #     PRAGMA auto_vacuum = 'full';
     45 #     PRAGMA cache_size = 10;
     46 #     BEGIN;
     47 #     CREATE TABLE abc(a, UNIQUE(a));
     48 #   }
     49 #   for {set ii 0} {$ii < 25} {incr ii} {
     50 #     db eval {INSERT INTO abc VALUES(randstr(1500,1500))}
     51 #   }
     52 #   db eval COMMIT
     53 # } -sqlbody {
     54 #   BEGIN;
     55 #   DELETE FROM abc WHERE (oid%3)==0;
     56 #   INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
     57 #   CREATE INDEX abc_i ON abc(a);
     58 #   DELETE FROM abc WHERE (oid%2)==0;
     59 #   DROP INDEX abc_i;
     60 #   COMMIT;
     61 # }
     62 
     63 do_ioerr_test incrvacuum-ioerr-2 -start 1 -cksum 1 -tclprep {
     64   db eval {
     65     PRAGMA auto_vacuum = 'full';
     66     PRAGMA cache_size = 10;
     67     BEGIN;
     68     CREATE TABLE abc(a, UNIQUE(a));
     69   }
     70   for {set ii 0} {$ii < 25} {incr ii} {
     71     db eval {INSERT INTO abc VALUES(randstr(1500,1500))}
     72   }
     73   db eval COMMIT
     74 } -sqlbody {
     75   BEGIN;
     76   PRAGMA incremental_vacuum;
     77   DELETE FROM abc WHERE (oid%3)==0;
     78   PRAGMA incremental_vacuum;
     79   INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
     80   PRAGMA incremental_vacuum;
     81   CREATE INDEX abc_i ON abc(a);
     82   DELETE FROM abc WHERE (oid%2)==0;
     83   PRAGMA incremental_vacuum;
     84   DROP INDEX abc_i;
     85   PRAGMA incremental_vacuum;
     86   COMMIT;
     87 }
     88 
     89 do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
     90   db eval {
     91     PRAGMA auto_vacuum = 'incremental';
     92     BEGIN;
     93     CREATE TABLE a(i integer, b blob);
     94     INSERT INTO a VALUES(1, randstr(1500,1500));
     95     INSERT INTO a VALUES(2, randstr(1500,1500));
     96   }
     97   db eval COMMIT
     98   db eval {DELETE FROM a WHERE oid}
     99 } -sqlbody {
    100   PRAGMA incremental_vacuum(5);
    101 } -cleanup {
    102   sqlite3 db test.db
    103   integrity_check incrvacuum-ioerr-2.$n.integritycheck
    104   db close
    105 }
    106 
    107 
    108 ifcapable shared_cache {
    109 
    110   catch { db close }
    111   file delete -force test.db
    112   set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
    113   
    114   # Create two connections to a single shared-cache:
    115   #
    116   sqlite3 db1 test.db
    117   sqlite3 db2 test.db
    118   
    119   # Create a database with around 20 free pages.
    120   #
    121   do_test incrvacuum-ioerr-4.0 {
    122     execsql {
    123       PRAGMA page_size = 1024;
    124       PRAGMA locking_mode = exclusive;
    125       PRAGMA auto_vacuum = 'incremental';
    126       BEGIN;
    127       CREATE TABLE a(i integer, b blob);
    128     } db1
    129     for {set ii 0} {$ii < 20} {incr ii} {
    130       execsql { INSERT INTO a VALUES($ii, randstr(800,1500)); } db1
    131     }
    132     execsql COMMIT db1
    133     execsql {DELETE FROM a WHERE oid} db1
    134   } {}
    135   
    136   set ::rc 1
    137   for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} {
    138   
    139     # Figure out how big the database is and how many free pages it
    140     # has before running incremental-vacuum.
    141     #
    142     set nPage [expr {[file size test.db]/1024}]
    143     set nFree [execsql {pragma freelist_count} db1]
    144   
    145     # Now run incremental-vacuum to vacuum 5 pages from the db file.
    146     # The iTest'th I/O call is set to fail.
    147     #
    148     set ::sqlite_io_error_pending $iTest
    149     set ::sqlite_io_error_persist 1
    150     do_test incrvacuum-ioerr-4.$iTest.1 {
    151       set ::rc [catch {execsql {pragma incremental_vacuum(5)} db1} msg]
    152       expr {$::rc==0 || $msg eq "disk I/O error"}
    153     } {1}
    154   
    155     set ::sqlite_io_error_pending 0
    156     set ::sqlite_io_error_persist 0
    157     set ::sqlite_io_error_hit 0
    158     set ::sqlite_io_error_hardhit 0
    159   
    160     set nFree2 [execsql {pragma freelist_count} db1]
    161     set nPage2 [expr {[file size test.db]/1024}]
    162   
    163     do_test incrvacuum-ioerr-4.$iTest.2 {
    164       set shrink [expr {$nPage-$nPage2}]
    165       expr {$shrink==0 || $shrink==5}
    166     } {1}
    167   
    168     do_test incrvacuum-ioerr-4.$iTest.3 {
    169       expr {$nPage - $nPage2}
    170     } [expr {$nFree - $nFree2}]
    171   }
    172   
    173   # Close the two database connections and restore the default
    174   # shared-cache mode setting.
    175   #
    176   db1 close
    177   db2 close
    178   sqlite3_enable_shared_cache $::enable_shared_cache
    179 }
    180 
    181 finish_test
    182