Snapshot of upstream SQLite 3.43.2
[sqlcipher.git] / test / e_walauto.test
blob7665b1bf735f96ba70a0af31d9c43d819b11902b
1 # 2014 December 04
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 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
15 source $testdir/wal_common.tcl
16 set testprefix e_walauto
18 # Do not run this test on OpenBSD, as it depends on read() and mmap both
19 # accessing the same coherent view of the "test.db-shm" file. This doesn't
20 # work on OpenBSD.
22 if {$tcl_platform(os) == "OpenBSD"} {
23   finish_test
24   return
27 # This module uses hard-coded offsets which do not work if the reserved_bytes
28 # value is nonzero.
29 if {[nonzero_reserved_bytes]} {finish_test; return;}
32 proc read_nbackfill {} {
33   seek $::shmfd 96
34   binary scan [read $::shmfd 4] n nBackfill
35   set nBackfill
37 proc read_mxframe {} {
38   seek $::shmfd 16
39   binary scan [read $::shmfd 4] n mxFrame
40   set mxFrame
43 # Assuming that the main db for database handle
45 proc do_autocommit_threshold_test {tn value} {
47   set nBackfillSaved [read_nbackfill]
48   while {1} {
49     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
50     if {[read_mxframe] >= $value} break
51   }
52   
53   set nBackfillNew [read_nbackfill]
54   uplevel [list do_test $tn "expr $nBackfillNew > $nBackfillSaved" 1]
57 # EVIDENCE-OF: R-30135-06439 The wal_autocheckpoint pragma can be used
58 # to invoke this interface from SQL.
60 #   All tests in this file are run twice - once using the
61 #   sqlite3_wal_autocheckpoint() API, and once using "PRAGMA
62 #   wal_autocheckpoint".
64 foreach {tn code} {
65   1 {
66     proc autocheckpoint {db value} {
67       uplevel [list $db eval "PRAGMA wal_autocheckpoint = $value"]
68     }
69   }
71   2 {
72     proc autocheckpoint {db value} {
73       uplevel [list sqlite3_wal_autocheckpoint $db $value]
74       return $value
75     }
76   }
77 } {
79   eval $code
81   reset_db
82   execsql { PRAGMA auto_vacuum = 0 }
83   do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
84   do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
85   set shmfd [open "test.db-shm" rb]
87   # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
88   # having the auto-checkpoint enabled with a threshold of 1000 or
89   # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
90   #
91   do_autocommit_threshold_test 1.$tn.2 1000
92   db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
93   do_autocommit_threshold_test 1.$tn.3 1000
95   # EVIDENCE-OF: R-38128-34102 The sqlite3_wal_autocheckpoint(D,N) is a
96   # wrapper around sqlite3_wal_hook() that causes any database on database
97   # connection D to automatically checkpoint after committing a
98   # transaction if there are N or more frames in the write-ahead log file.
99   #
100   do_test 1.$tn.4 {
101     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
102     autocheckpoint db 100
103   } {100}
104   do_autocommit_threshold_test 1.$tn.5 100
106   do_test 1.$tn.6 {
107     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
108     autocheckpoint db 500
109   } {500}
110   do_autocommit_threshold_test 1.$tn.7 500
112   # EVIDENCE-OF: R-26993-43540 Passing zero or a negative value as the
113   # nFrame parameter disables automatic checkpoints entirely.
114   #
115   do_test 1.$tn.7 {
116     autocheckpoint db 0    ;# Set to zero
117     for {set i 0} {$i < 10000} {incr i} {
118       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
119     }
120     expr {[file size test.db-wal] > (5 * 1024 * 1024)}
121   } 1
122   do_test 1.$tn.8 {
123     sqlite3_wal_checkpoint_v2 db truncate
124     file size test.db-wal
125   } 0
126   do_test 1.$tn.9 {
127     autocheckpoint db -4    ;# Set to a negative value
128     for {set i 0} {$i < 10000} {incr i} {
129       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
130     }
131     expr {[file size test.db-wal] > (5 * 1024 * 1024)}
132   } 1
134   # EVIDENCE-OF: R-10203-42688 The callback registered by this function
135   # replaces any existing callback registered using sqlite3_wal_hook().
136   #
137   set ::wal_hook_callback 0
138   proc wal_hook_callback {args} { incr ::wal_hook_callback ; return 0 }
139   do_test 1.$tn.10.1 {
140     db wal_hook wal_hook_callback
141     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
142     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
143     set ::wal_hook_callback
144   } 2
145   do_test 1.$tn.10.2 {
146     autocheckpoint db 100
147     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
148     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
149     set ::wal_hook_callback
150   } 2
152   # EVIDENCE-OF: R-17497-43474 Likewise, registering a callback using
153   # sqlite3_wal_hook() disables the automatic checkpoint mechanism
154   # configured by this function.
155   do_test 1.$tn.11.1 {
156     sqlite3_wal_checkpoint_v2 db truncate
157     file size test.db-wal
158   } 0
159   do_test 1.$tn.11.2 {
160     autocheckpoint db 100 
161     for {set i 0} {$i < 1000} {incr i} {
162       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
163     }
164     expr {[file size test.db-wal] < (1 * 1024 * 1024)}
165   } 1
166   do_test 1.$tn.11.3 {
167     db wal_hook wal_hook_callback
168     for {set i 0} {$i < 1000} {incr i} {
169       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
170     }
171     expr {[file size test.db-wal] < (1 * 1024 * 1024)}
172   } 0
174   # EVIDENCE-OF: R-33080-59193 Checkpoints initiated by this mechanism 
175   # are PASSIVE.
176   #
177   set ::busy_callback_count 0
178   proc busy_callback {args} {
179     incr ::busy_callback_count
180     return 0
181   }
182   do_test 1.$tn.12.1 {
183     sqlite3_wal_checkpoint_v2 db truncate
184     autocheckpoint db 100 
185     db busy busy_callback
186     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
187     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
188   } {}
189   do_test 1.$tn.12.2 {
190     sqlite3 db2 test.db
191     db2 eval { BEGIN; SELECT * FROM t1 LIMIT 10; }
192     read_nbackfill
193   } {0}
194   do_test 1.$tn.12.3 {
195     for {set i 0} {$i < 1000} {incr i} {
196       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
197     }
198     read_nbackfill
199   } {2}
200   do_test 1.$tn.12.4 {
201     set ::busy_callback_count
202   } {0}
203   db2 close
205   do_test 1.$tn.12.5 {
206     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
207     read_nbackfill
208   } {1559}
210   db close
211   close $shmfd
214 finish_test