1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
# 2016 Aug 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is using the sqlite_interrupt() API to
# interrupt WAL checkpoint operations.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl
set testprefix interrupt2
if {[permutation]=="journaltest" || [permutation]=="inmemory_journal"} {
finish_test
return
}
db close
testvfs tvfs -default 1
tvfs filter xWrite
tvfs script write_cb
set ::trigger_interrupt 0
proc write_cb {method args} {
set filename [lindex $args 0]
if {[file tail $filename]=="test.db" && $::trigger_interrupt} {
if {$::trigger_interrupt} {
incr ::trigger_interrupt -1
if {$::trigger_interrupt==0} { sqlite3_interrupt db }
}
}
return 0
}
sqlite3 db test.db
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
CREATE INDEX t1a ON t1(a);
CREATE INDEX t1b ON t1(b);
PRAGMA journal_mode = wal;
WITH ii(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM ii WHERE i<1000 )
INSERT INTO t1 SELECT i, i FROM ii;
} {wal}
foreach idelay {
5
10
15
20
} {
set ::trigger_interrupt $idelay
do_catchsql_test 1.$idelay.1 { PRAGMA wal_checkpoint; } {1 interrupted}
do_execsql_test 1.$idelay.2 { SELECT count(*) FROM t1 } 1000
set ::trigger_interrupt $idelay
do_test 1.$idelay.3 {
list [catch { sqlite3_wal_checkpoint_v2 db truncate } msg] $msg
} {1 {SQLITE_INTERRUPT - interrupted}}
do_execsql_test 1.$idelay.4 { SELECT count(*) FROM t1 } 1000
}
#-------------------------------------------------------------------------
# Check that if there are other SQL statements running, a checkpoint does
# not clear the isInterrupted flag.
#
do_execsql_test 2.0 {
CREATE TEMP TABLE z1(a, b);
INSERT INTO z1 SELECT * FROM t1;
}
do_test 2.1 {
set i 10
set res [list [catch {
set i 10
db eval {SELECT * FROM z1} {
incr i -1
if {$i==0} {
set ::trigger_interrupt 10
set cres [catch { sqlite3_wal_checkpoint_v2 db truncate } msg]
lappend cres $msg
}
}
} msg] $msg]
list $cres $res
} {{1 {SQLITE_INTERRUPT - interrupted}} {1 interrupted}}
do_execsql_test 2.0 {
SELECT count(*) FROM t1
UNION ALL
SELECT count(*) FROM z1
} {1000 1000}
#-------------------------------------------------------------------------
# Check the effect of an interrupt during sqlite3_close().
#
db_save_and_close
db_restore_and_reopen
do_test 3.1.1 {
set ::trigger_interrupt 10
db eval { SELECT * FROM sqlite_master }
db close
set {} {}
} {}
do_test 3.1.2 {
list [file exists test.db] [file exists test.db-wal]
} {1 1}
db_restore_and_reopen
do_test 3.2.1 {
db eval { SELECT * FROM sqlite_master }
db close
set {} {}
} {}
do_test 3.2.2 {
list [file exists test.db] [file exists test.db-wal]
} {1 0}
#-------------------------------------------------------------------------
# Check the effect of an interrupt during an automatic checkpoint
#
db_restore_and_reopen
do_test 4.0 {
execsql { PRAGMA wal_autocheckpoint = 10 }
set ::trigger_interrupt 10
execsql { CREATE TABLE t2(x, y) }
} {}
# The auto-checkpoint in test 4.0 should have been interrupted. So this
# db write should cause the wal file to grow.
do_test 4.1 {
set nFrame1 [wal_frame_count test.db-wal 1024]
execsql { CREATE TABLE t3(x, y) }
set nFrame2 [wal_frame_count test.db-wal 1024]
expr $nFrame2 > $nFrame1
} {1}
# The auto-checkpoint in test 4.0 should not have been interrupted. So
# this db write should not cause the wal file to grow.
do_test 4.2 {
set nFrame1 [wal_frame_count test.db-wal 1024]
execsql { CREATE TABLE t4(x, y) }
set nFrame2 [wal_frame_count test.db-wal 1024]
expr $nFrame2 == $nFrame1
} {1}
finish_test
|