AryaWu/sqlite
0
1# 2001 October 122#3# The author disclaims copyright to this source code. In place of4# 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. The12# focus of this file is testing for correct handling of I/O errors13# such as writes failing because the disk is full.14# 15# The tests in this file use special facilities that are only16# available in the SQLite test fixture.17#18# $Id: incrvacuum_ioerr.test,v 1.6 2008/07/12 14:52:20 drh Exp $19 20set testdir [file dirname $argv0]21source $testdir/tester.tcl22 23# If this build of the library does not support auto-vacuum, omit this24# whole file.25ifcapable {!autovacuum} {26 finish_test27 return28}29 30do_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 COMMIT53# } -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 63do_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 COMMIT74} -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 89do_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 COMMIT98 db eval {DELETE FROM a WHERE oid}99} -sqlbody {100 PRAGMA incremental_vacuum(5);101} -cleanup {102 sqlite3 db test.db103 integrity_check incrvacuum-ioerr-2.$n.integritycheck104 db close105}106 107 108ifcapable shared_cache {109 110 catch { db close }111 forcedelete test.db112 set ::enable_shared_cache [sqlite3_enable_shared_cache 1]113 114 # Create two connections to a single shared-cache:115 #116 sqlite3 db1 test.db117 sqlite3 db2 test.db118 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 } db1129 for {set ii 0} {$ii < 20} {incr ii} {130 execsql { INSERT INTO a VALUES($ii, randstr(800,1500)); } db1131 }132 execsql COMMIT db1133 execsql {DELETE FROM a WHERE oid} db1134 } {}135 136 set ::rc 1137 for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} {138 139 # Figure out how big the database is and how many free pages it140 # 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 $iTest150 set ::sqlite_io_error_persist 1151 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 0157 set ::sqlite_io_error_persist 0158 set ::sqlite_io_error_hit 0159 set ::sqlite_io_error_hardhit 0160 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 default175 # shared-cache mode setting.176 #177 db1 close178 db2 close179 sqlite3_enable_shared_cache $::enable_shared_cache180}181 182finish_test183 