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