summaryrefslogtreecommitdiffstats
path: root/test/interrupt2.test
blob: b9c66bd1f4c1aa06e7127e5c5c1fc3d605023ecc (plain)
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