xref: /sqlite-3.40.0/test/walfault.test (revision 8f6097c2)
176ed3bc0Sdan# 2010 May 03
276ed3bc0Sdan#
376ed3bc0Sdan# The author disclaims copyright to this source code.  In place of
476ed3bc0Sdan# a legal notice, here is a blessing:
576ed3bc0Sdan#
676ed3bc0Sdan#    May you do good and not evil.
776ed3bc0Sdan#    May you find forgiveness for yourself and forgive others.
876ed3bc0Sdan#    May you share freely, never taking more than you give.
976ed3bc0Sdan#
1076ed3bc0Sdan#***********************************************************************
1176ed3bc0Sdan# This file implements regression tests for SQLite library.  The
1276ed3bc0Sdan# focus of this file is testing the operation of the library in
1376ed3bc0Sdan# "PRAGMA journal_mode=WAL" mode.
1476ed3bc0Sdan#
1576ed3bc0Sdan
1676ed3bc0Sdanset testdir [file dirname $argv0]
1776ed3bc0Sdansource $testdir/tester.tcl
1876ed3bc0Sdansource $testdir/malloc_common.tcl
1976ed3bc0Sdan
2076ed3bc0Sdanifcapable !wal {finish_test ; return }
2176ed3bc0Sdan
2276ed3bc0Sdando_malloc_test walfault-oom-1 -sqlbody {
2376ed3bc0Sdan  PRAGMA journal_mode = WAL;
2476ed3bc0Sdan  CREATE TABLE t1(a, b);
2576ed3bc0Sdan  INSERT INTO t1 VALUES(1, 2);
26ef378025Sdan  PRAGMA wal_checkpoint;
2776ed3bc0Sdan}
2876ed3bc0Sdan
295e9e482fSdando_malloc_test walfault-oom-2 -tclprep {
305e9e482fSdan  execsql {
315e9e482fSdan    PRAGMA journal_mode = WAL;
325e9e482fSdan    BEGIN;
335e9e482fSdan      CREATE TABLE x(y, z, UNIQUE(y, z));
345e9e482fSdan      INSERT INTO x VALUES(randomblob(100), randomblob(100));
355e9e482fSdan    COMMIT;
365e9e482fSdan    PRAGMA wal_checkpoint;
375e9e482fSdan
385e9e482fSdan    INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x;
395e9e482fSdan    INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x;
405e9e482fSdan    INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x;
415e9e482fSdan  }
425e9e482fSdan  file copy -force test.db testX.db
435e9e482fSdan  file copy -force test.db-wal testX.db-wal
445e9e482fSdan  db close
455e9e482fSdan  file rename -force testX.db test.db
465e9e482fSdan  file rename -force testX.db-wal test.db-wal
475e9e482fSdan
485e9e482fSdan  sqlite3 db test.db
495e9e482fSdan  sqlite3_extended_result_codes db 1
505e9e482fSdan  sqlite3_db_config_lookaside db 0 0 0
515e9e482fSdan} -sqlbody {
525e9e482fSdan  SELECT count(*) FROM x;
535e9e482fSdan}
545e9e482fSdan
55c7991bdfSdan# A [testvfs] callback for the VFS created by [do_shmfault_test]. This
56*8f6097c2Sdan# callback injects SQLITE_IOERR faults into methods for which an entry
57*8f6097c2Sdan# in array ::shmfault_ioerr_methods is defined. For example, to enable
58*8f6097c2Sdan# errors in xShmOpen:
59c7991bdfSdan#
60*8f6097c2Sdan#   set ::shmfault_ioerr_methods(xShmOpen) 1
61c7991bdfSdan#
62c7991bdfSdan# Faults are not injected into xShmRelease, xShmClose or xShmLock method
63c7991bdfSdan# calls. The global tcl variables used are:
64c7991bdfSdan#
65c7991bdfSdan#   $::shmfault_ioerr_countdown
66c7991bdfSdan#   $::shmfault_ioerr_persist
67*8f6097c2Sdan#   $::shmfault_ioerr_methods
68c7991bdfSdan#
69c7991bdfSdanproc shmfault_vfs_cb {method args} {
70c7991bdfSdan
71c7991bdfSdan  # If ::shmfault_ioerr_countdown is not set, always return SQLITE_OK.
72c7991bdfSdan  #
73c7991bdfSdan  if {[info exists ::shmfault_ioerr_countdown]==0} { return SQLITE_OK }
74c7991bdfSdan
75*8f6097c2Sdan  if {[info exists ::shmfault_ioerr_methods($method)]} {
76c7991bdfSdan    incr ::shmfault_ioerr_countdown -1
77c7991bdfSdan    if { ($::shmfault_ioerr_countdown==0)
78c7991bdfSdan      || ($::shmfault_ioerr_countdown<=0 && $::shmfault_ioerr_persist)
79c7991bdfSdan    } {
80c7991bdfSdan      return SQLITE_IOERR
81c7991bdfSdan    }
82c7991bdfSdan  }
83c7991bdfSdan  return SQLITE_OK
84c7991bdfSdan}
85c7991bdfSdan
86*8f6097c2Sdan# Options are:
87*8f6097c2Sdan#
88*8f6097c2Sdan#   -tclprep TCL
89*8f6097c2Sdan#   -sqlprep SQL
90*8f6097c2Sdan#   -sqlbody SQL
91*8f6097c2Sdan#
92c7991bdfSdanproc do_shmfault_test {name args} {
93*8f6097c2Sdan
94*8f6097c2Sdan  set A(-tclprep) "sqlite3 db test.db -vfs shmfault"
95*8f6097c2Sdan  set A(-sqlprep) ""
96*8f6097c2Sdan  set A(-sqlbody) ""
97*8f6097c2Sdan  set A(-methods) [list xShmGet xShmOpen xShmSize]
98c7991bdfSdan  array set A $args
99c7991bdfSdan
100c7991bdfSdan  # Create a VFS to use:
101c7991bdfSdan  testvfs shmfault shmfault_vfs_cb
102c7991bdfSdan
103*8f6097c2Sdan  unset -nocomplain ::shmfault_ioerr_methods
104*8f6097c2Sdan  foreach m $A(-methods) { set ::shmfault_ioerr_methods($m) 1 }
105*8f6097c2Sdan
106c7991bdfSdan  foreach mode {transient persistent} {
107c7991bdfSdan    set ::shmfault_ioerr_persist [expr {$mode == "persistent"}]
108*8f6097c2Sdan
109c7991bdfSdan    for {set nDelay 1} {$nDelay < 10000} {incr nDelay} {
110c7991bdfSdan
111c7991bdfSdan      file delete -force test.db test.db-wal test.db-journal
112c7991bdfSdan
113*8f6097c2Sdan      eval $A(-tclprep)
114*8f6097c2Sdan      db eval $A(-sqlprep)
115*8f6097c2Sdan
116*8f6097c2Sdan      set ::shmfault_ioerr_countdown $nDelay
117*8f6097c2Sdan      set rc [catch { db eval $A(-sqlbody) } msg]
118c7991bdfSdan      set hit_error [expr {$::shmfault_ioerr_countdown<=0}]
119c7991bdfSdan      unset ::shmfault_ioerr_countdown
120*8f6097c2Sdan
121c7991bdfSdan      catch { db close }
122c7991bdfSdan
123c7991bdfSdan      do_test $name-$mode.$nDelay.1 [list set {} $hit_error] $rc
124c7991bdfSdan
125c7991bdfSdan      if {$hit_error==0} break
126c7991bdfSdan    }
127c7991bdfSdan  }
128c7991bdfSdan
129c7991bdfSdan  shmfault delete
130c7991bdfSdan}
131c7991bdfSdan
132*8f6097c2Sdan
133c7991bdfSdando_shmfault_test walfault-shm-1 -sqlbody {
134c7991bdfSdan  PRAGMA journal_mode = WAL;
135c7991bdfSdan  CREATE TABLE t1(a PRIMARY KEY, b);
136c7991bdfSdan  INSERT INTO t1 VALUES('a', 'b');
137c7991bdfSdan  PRAGMA wal_checkpoint;
138c7991bdfSdan}
13976ed3bc0Sdan
140*8f6097c2Sdando_shmfault_test walfault-shm-2 -methods xShmSize -sqlprep {
141*8f6097c2Sdan  PRAGMA page_size = 512;
142*8f6097c2Sdan  PRAGMA journal_mode = WAL;
143*8f6097c2Sdan  PRAGMA wal_autocheckpoint = 0;
144*8f6097c2Sdan} -sqlbody {
145*8f6097c2Sdan  CREATE TABLE t1(x);
146*8f6097c2Sdan  BEGIN;
147*8f6097c2Sdan    INSERT INTO t1 VALUES(randomblob(400));           /* 1 */
148*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 2 */
149*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 4 */
150*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 8 */
151*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 16 */
152*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 32 */
153*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 64 */
154*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 128 */
155*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 256 */
156*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 512 */
157*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 1024 */
158*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 2048 */
159*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 4096 */
160*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 8192 */
161*8f6097c2Sdan    INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 16384 */
162*8f6097c2Sdan  COMMIT;
163*8f6097c2Sdan}
164*8f6097c2Sdan
165*8f6097c2Sdando_shmfault_test walfault-shm-3 -methods xShmSize -tclprep {
166*8f6097c2Sdan  sqlite3 db test.db -vfs shmfault
167*8f6097c2Sdan  unset -nocomplain ::shmfault_ioerr_countdown
168*8f6097c2Sdan  db eval {
169*8f6097c2Sdan    PRAGMA page_size = 512;
170*8f6097c2Sdan    PRAGMA journal_mode = WAL;
171*8f6097c2Sdan    PRAGMA wal_autocheckpoint = 0;
172*8f6097c2Sdan    CREATE TABLE t1(x);
173*8f6097c2Sdan    BEGIN;
174*8f6097c2Sdan      INSERT INTO t1 VALUES(randomblob(400));           /* 1 */
175*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 2 */
176*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 4 */
177*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 8 */
178*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 16 */
179*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 32 */
180*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 64 */
181*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 128 */
182*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 256 */
183*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 512 */
184*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 1024 */
185*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 2048 */
186*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 4096 */
187*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 8192 */
188*8f6097c2Sdan      INSERT INTO t1 SELECT randomblob(400) FROM t1;    /* 16384 */
189*8f6097c2Sdan    COMMIT;
190*8f6097c2Sdan  }
191*8f6097c2Sdan
192*8f6097c2Sdan  set ::shmfault_ioerr_countdown 1
193*8f6097c2Sdan  set ::shmfault_ioerr_methods(xShmGet) 1
194*8f6097c2Sdan  db close
195*8f6097c2Sdan  unset ::shmfault_ioerr_methods(xShmGet)
196*8f6097c2Sdan  if {[file exists test.db-wal]==0} {error "Failed to create WAL file!"}
197*8f6097c2Sdan
198*8f6097c2Sdan  sqlite3 db test.db -vfs shmfault
199*8f6097c2Sdanbreakpoint
200*8f6097c2Sdan} -sqlbody {
201*8f6097c2Sdan  SELECT count(*) FROM t1;
202*8f6097c2Sdan}
203*8f6097c2Sdan
20476ed3bc0Sdanfinish_test
205c7991bdfSdan
206