incrvacuum_ioerr.test 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. set testdir [file dirname $argv0]
  20. source $testdir/tester.tcl
  21. # If this build of the library does not support auto-vacuum, omit this
  22. # whole file.
  23. ifcapable {!autovacuum} {
  24. finish_test
  25. return
  26. }
  27. do_ioerr_test incrvacuum-ioerr-1 -cksum 1 -sqlprep {
  28. PRAGMA auto_vacuum = 'incremental';
  29. CREATE TABLE abc(a);
  30. INSERT INTO abc VALUES(randstr(1500,1500));
  31. } -sqlbody {
  32. BEGIN;
  33. CREATE TABLE abc2(a);
  34. DELETE FROM abc;
  35. PRAGMA incremental_vacuum;
  36. COMMIT;
  37. }
  38. # do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
  39. # db eval {
  40. # PRAGMA auto_vacuum = 'full';
  41. # PRAGMA cache_size = 10;
  42. # BEGIN;
  43. # CREATE TABLE abc(a, UNIQUE(a));
  44. # }
  45. # for {set ii 0} {$ii < 25} {incr ii} {
  46. # db eval {INSERT INTO abc VALUES(randstr(1500,1500))}
  47. # }
  48. # db eval COMMIT
  49. # } -sqlbody {
  50. # BEGIN;
  51. # DELETE FROM abc WHERE (oid%3)==0;
  52. # INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
  53. # CREATE INDEX abc_i ON abc(a);
  54. # DELETE FROM abc WHERE (oid%2)==0;
  55. # DROP INDEX abc_i;
  56. # COMMIT;
  57. # }
  58. do_ioerr_test incrvacuum-ioerr-2 -start 1 -cksum 1 -tclprep {
  59. db eval {
  60. PRAGMA auto_vacuum = 'full';
  61. PRAGMA cache_size = 10;
  62. BEGIN;
  63. CREATE TABLE abc(a, UNIQUE(a));
  64. }
  65. for {set ii 0} {$ii < 25} {incr ii} {
  66. db eval {INSERT INTO abc VALUES(randstr(1500,1500))}
  67. }
  68. db eval COMMIT
  69. } -sqlbody {
  70. BEGIN;
  71. PRAGMA incremental_vacuum;
  72. DELETE FROM abc WHERE (oid%3)==0;
  73. PRAGMA incremental_vacuum;
  74. INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
  75. PRAGMA incremental_vacuum;
  76. CREATE INDEX abc_i ON abc(a);
  77. DELETE FROM abc WHERE (oid%2)==0;
  78. PRAGMA incremental_vacuum;
  79. DROP INDEX abc_i;
  80. PRAGMA incremental_vacuum;
  81. COMMIT;
  82. }
  83. do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
  84. db eval {
  85. PRAGMA auto_vacuum = 'incremental';
  86. BEGIN;
  87. CREATE TABLE a(i integer, b blob);
  88. INSERT INTO a VALUES(1, randstr(1500,1500));
  89. INSERT INTO a VALUES(2, randstr(1500,1500));
  90. }
  91. db eval COMMIT
  92. db eval {DELETE FROM a WHERE oid}
  93. } -sqlbody {
  94. PRAGMA incremental_vacuum(5);
  95. } -cleanup {
  96. sqlite3 db test.db
  97. integrity_check incrvacuum-ioerr-2.$n.integritycheck
  98. db close
  99. }
  100. ifcapable shared_cache {
  101. catch { db close }
  102. forcedelete test.db
  103. set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  104. # Create two connections to a single shared-cache:
  105. #
  106. sqlite3 db1 test.db
  107. sqlite3 db2 test.db
  108. # Create a database with around 20 free pages.
  109. #
  110. do_test incrvacuum-ioerr-4.0 {
  111. execsql {
  112. PRAGMA page_size = 1024;
  113. PRAGMA locking_mode = exclusive;
  114. PRAGMA auto_vacuum = 'incremental';
  115. BEGIN;
  116. CREATE TABLE a(i integer, b blob);
  117. } db1
  118. for {set ii 0} {$ii < 20} {incr ii} {
  119. execsql { INSERT INTO a VALUES($ii, randstr(800,1500)); } db1
  120. }
  121. execsql COMMIT db1
  122. execsql {DELETE FROM a WHERE oid} db1
  123. } {}
  124. set ::rc 1
  125. for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} {
  126. # Figure out how big the database is and how many free pages it
  127. # has before running incremental-vacuum.
  128. #
  129. set nFree [execsql {pragma freelist_count} db1]
  130. set nPage [execsql {pragma page_count} db1]
  131. puts "nFree=$nFree nPage=$nPage"
  132. # Now run incremental-vacuum to vacuum 5 pages from the db file.
  133. # The iTest'th I/O call is set to fail.
  134. #
  135. set ::sqlite_io_error_pending $iTest
  136. set ::sqlite_io_error_persist 1
  137. do_test incrvacuum-ioerr-4.$iTest.1 {
  138. set ::rc [catch {execsql {pragma incremental_vacuum(5)} db1} msg]
  139. expr {$::rc==0 || $msg eq "disk I/O error"}
  140. } {1}
  141. set ::sqlite_io_error_pending 0
  142. set ::sqlite_io_error_persist 0
  143. set ::sqlite_io_error_hit 0
  144. set ::sqlite_io_error_hardhit 0
  145. set nFree2 [execsql {pragma freelist_count} db1]
  146. set nPage2 [execsql {pragma page_count} db1]
  147. do_test incrvacuum-ioerr-4.$iTest.2 {
  148. set shrink [expr {$nPage-$nPage2}]
  149. expr {$shrink==0 || $shrink==5 || ($nFree<5 && $shrink==$nFree)}
  150. } {1}
  151. do_test incrvacuum-ioerr-4.$iTest.3 {
  152. expr {$nPage - $nPage2}
  153. } [expr {$nFree - $nFree2}]
  154. }
  155. # Close the two database connections and restore the default
  156. # shared-cache mode setting.
  157. #
  158. db1 close
  159. db2 close
  160. sqlite3_enable_shared_cache $::enable_shared_cache
  161. }
  162. finish_test