gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/incrvacuum_ioerr.test (about) 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 forcedelete 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 nFree [execsql {pragma freelist_count} db1] 143 set nPage [execsql {pragma page_count} db1] 144 puts "nFree=$nFree nPage=$nPage" 145 146 # Now run incremental-vacuum to vacuum 5 pages from the db file. 147 # The iTest'th I/O call is set to fail. 148 # 149 set ::sqlite_io_error_pending $iTest 150 set ::sqlite_io_error_persist 1 151 do_test incrvacuum-ioerr-4.$iTest.1 { 152 set ::rc [catch {execsql {pragma incremental_vacuum(5)} db1} msg] 153 expr {$::rc==0 || $msg eq "disk I/O error"} 154 } {1} 155 156 set ::sqlite_io_error_pending 0 157 set ::sqlite_io_error_persist 0 158 set ::sqlite_io_error_hit 0 159 set ::sqlite_io_error_hardhit 0 160 161 set nFree2 [execsql {pragma freelist_count} db1] 162 set nPage2 [execsql {pragma page_count} db1] 163 164 do_test incrvacuum-ioerr-4.$iTest.2 { 165 set shrink [expr {$nPage-$nPage2}] 166 expr {$shrink==0 || $shrink==5 || ($nFree<5 && $shrink==$nFree)} 167 } {1} 168 169 do_test incrvacuum-ioerr-4.$iTest.3 { 170 expr {$nPage - $nPage2} 171 } [expr {$nFree - $nFree2}] 172 } 173 174 # Close the two database connections and restore the default 175 # shared-cache mode setting. 176 # 177 db1 close 178 db2 close 179 sqlite3_enable_shared_cache $::enable_shared_cache 180 } 181 182 finish_test