blob: b9c66bd1f4c1aa06e7127e5c5c1fc3d605023ecc [file] [log] [blame]
# 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