xref: /sqlite-3.40.0/test/walfault.test (revision c7991bdf)
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
55*c7991bdfSdan# A [testvfs] callback for the VFS created by [do_shmfault_test]. This
56*c7991bdfSdan# callback injects SQLITE_IOERR faults into the following methods:
57*c7991bdfSdan#
58*c7991bdfSdan#   xShmOpen
59*c7991bdfSdan#   xShmSize
60*c7991bdfSdan#   xShmGet
61*c7991bdfSdan#
62*c7991bdfSdan# Faults are not injected into xShmRelease, xShmClose or xShmLock method
63*c7991bdfSdan# calls. The global tcl variables used are:
64*c7991bdfSdan#
65*c7991bdfSdan#   $::shmfault_ioerr_countdown
66*c7991bdfSdan#   $::shmfault_ioerr_persist
67*c7991bdfSdan#
68*c7991bdfSdanproc shmfault_vfs_cb {method args} {
69*c7991bdfSdan
70*c7991bdfSdan  # If ::shmfault_ioerr_countdown is not set, always return SQLITE_OK.
71*c7991bdfSdan  #
72*c7991bdfSdan  if {[info exists ::shmfault_ioerr_countdown]==0} { return SQLITE_OK }
73*c7991bdfSdan
74*c7991bdfSdan  if {$method == "xShmOpen"
75*c7991bdfSdan   || $method == "xShmSize"
76*c7991bdfSdan   || $method == "xShmGet"
77*c7991bdfSdan  } {
78*c7991bdfSdan    incr ::shmfault_ioerr_countdown -1
79*c7991bdfSdan    if { ($::shmfault_ioerr_countdown==0)
80*c7991bdfSdan      || ($::shmfault_ioerr_countdown<=0 && $::shmfault_ioerr_persist)
81*c7991bdfSdan    } {
82*c7991bdfSdan      return SQLITE_IOERR
83*c7991bdfSdan    }
84*c7991bdfSdan  }
85*c7991bdfSdan  return SQLITE_OK
86*c7991bdfSdan}
87*c7991bdfSdan
88*c7991bdfSdanproc do_shmfault_test {name args} {
89*c7991bdfSdan  array set A $args
90*c7991bdfSdan
91*c7991bdfSdan  # Create a VFS to use:
92*c7991bdfSdan  testvfs shmfault shmfault_vfs_cb
93*c7991bdfSdan
94*c7991bdfSdan  foreach mode {transient persistent} {
95*c7991bdfSdan    set ::shmfault_ioerr_persist [expr {$mode == "persistent"}]
96*c7991bdfSdan    for {set nDelay 1} {$nDelay < 10000} {incr nDelay} {
97*c7991bdfSdan      set ::shmfault_ioerr_countdown $nDelay
98*c7991bdfSdan
99*c7991bdfSdan      file delete -force test.db test.db-wal test.db-journal
100*c7991bdfSdan
101*c7991bdfSdan      set rc [catch {
102*c7991bdfSdan        sqlite3 db test.db -vfs shmfault
103*c7991bdfSdan        db eval $A(-sqlbody)
104*c7991bdfSdan      } msg]
105*c7991bdfSdan      set hit_error [expr {$::shmfault_ioerr_countdown<=0}]
106*c7991bdfSdan      unset ::shmfault_ioerr_countdown
107*c7991bdfSdan      catch { db close }
108*c7991bdfSdan
109*c7991bdfSdan      do_test $name-$mode.$nDelay.1 [list set {} $hit_error] $rc
110*c7991bdfSdan
111*c7991bdfSdan      if {$hit_error==0} break
112*c7991bdfSdan    }
113*c7991bdfSdan  }
114*c7991bdfSdan
115*c7991bdfSdan  shmfault delete
116*c7991bdfSdan}
117*c7991bdfSdan
118*c7991bdfSdando_shmfault_test walfault-shm-1 -sqlbody {
119*c7991bdfSdan  PRAGMA journal_mode = WAL;
120*c7991bdfSdan  CREATE TABLE t1(a PRIMARY KEY, b);
121*c7991bdfSdan  INSERT INTO t1 VALUES('a', 'b');
122*c7991bdfSdan  PRAGMA wal_checkpoint;
123*c7991bdfSdan}
12476ed3bc0Sdan
12576ed3bc0Sdanfinish_test
126*c7991bdfSdan
127