Update test file walprotocol.test to account for the changes in the wal
[sqlite.git] / test / walro2.test
blob9d0a6b4a1958af35d299619c10db8dae5c8d0faf
1 # 2011 May 09
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 #***********************************************************************
12 # This file contains tests for using WAL databases in read-only mode.
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
17 source $testdir/lock_common.tcl
18 source $testdir/wal_common.tcl
19 set ::testprefix walro2
21 # And only if the build is WAL-capable.
23 ifcapable !wal {
24   finish_test
25   return
28 proc copy_to_test2 {bZeroShm} {
29   forcecopy test.db test.db2
30   forcecopy test.db-wal test.db2-wal
31   if {$bZeroShm} {
32     forcedelete test.db2-shm
33     set fd [open test.db2-shm w]
34     seek $fd [expr [file size test.db-shm]-1]
35     puts -nonewline $fd "\0"
36     close $fd
37   } else {
38     forcecopy test.db-shm test.db2-shm
39   }
42 foreach bZeroShm {0 1} {
43 set TN [expr $bZeroShm+1]
44 do_multiclient_test tn {
45   
46   # Close all connections and delete the database.
47   #
48   code1 { db close  }
49   code2 { db2 close }
50   code3 { db3 close }
51   forcedelete test.db
52   
53   # Do not run tests with the connections in the same process.
54   #
55   if {$tn==2} continue
57   foreach c {code1 code2 code3} {
58     $c {
59       sqlite3_shutdown
60       sqlite3_config_uri 1
61     }
62   }
64   do_test $TN.1.1 {
65     code2 { sqlite3 db2 test.db }
66     sql2 { 
67       CREATE TABLE t1(x, y);
68       PRAGMA journal_mode = WAL;
69       INSERT INTO t1 VALUES('a', 'b');
70       INSERT INTO t1 VALUES('c', 'd');
71     }
72     file exists test.db-shm
73   } {1}
75   do_test $TN.1.2.1 {
76     copy_to_test2 $bZeroShm
77     code1 {
78       sqlite3 db file:test.db2?readonly_shm=1
79     }
81     sql1 { SELECT * FROM t1 }
82   } {a b c d}
83   do_test $TN.1.2.2 {
84     sql1 { SELECT * FROM t1 }
85   } {a b c d}
87   do_test $TN.1.3.1 {
88     code3 { sqlite3 db3 test.db2 }
89     sql3 { SELECT * FROM t1 }
90   } {a b c d}
92   do_test $TN.1.3.2 {
93     sql1 { SELECT * FROM t1 }
94   } {a b c d}
96   code1 { db close  }
97   code2 { db2 close }
98   code3 { db3 close }
100   do_test $TN.2.1 {
101     code2 { sqlite3 db2 test.db }
102     sql2 { 
103       INSERT INTO t1 VALUES('e', 'f');
104       INSERT INTO t1 VALUES('g', 'h');
105     }
106     file exists test.db-shm
107   } {1}
109   do_test $TN.2.2 {
110     copy_to_test2 $bZeroShm
111     code1 {
112       sqlite3 db file:test.db2?readonly_shm=1
113     }
114     sql1 { 
115       BEGIN;
116       SELECT * FROM t1;
117     }
118   } {a b c d e f g h}
120   do_test $TN.2.3.1 {
121     code3 { sqlite3 db3 test.db2 }
122     sql3 { SELECT * FROM t1 }
123   } {a b c d e f g h}
124   do_test $TN.2.3.2 {
125     sql3 { INSERT INTO t1 VALUES('i', 'j') }
126     code3 { db3 close }
127     sql1 { COMMIT } 
128   } {}
129   do_test $TN.2.3.3 {
130     sql1 { SELECT * FROM t1 }
131   } {a b c d e f g h i j}
134   #-----------------------------------------------------------------------
135   # 3.1.*: That a readonly_shm connection can read a database file if both
136   #        the *-wal and *-shm files are zero bytes in size.
137   #
138   # 3.2.*: That it flushes the cache if, between transactions on a db with a
139   #        zero byte *-wal file, some other connection modifies the db, then
140   #        does "PRAGMA wal_checkpoint=truncate" to truncate the wal file
141   #        back to zero bytes in size.
142   #
143   # 3.3.*: That, if between transactions some other process wraps the wal
144   #        file, the readonly_shm client reruns recovery.
145   #
146   catch { code1 { db close } }
147   catch { code2 { db2 close } }
148   catch { code3 { db3 close } }
149   do_test $TN.3.1.0 {
150     list [file exists test.db-wal] [file exists test.db-shm]
151   } {0 0}
152   do_test $TN.3.1.1 {
153     close [open test.db-wal w]
154     close [open test.db-shm w]
155     code1 {
156       sqlite3 db file:test.db?readonly_shm=1
157     }
158     sql1 { SELECT * FROM t1 }
159   } {a b c d e f g h}
161   do_test $TN.3.2.0 {
162     list [file size test.db-wal] [file size test.db-shm]
163   } {0 0}
164   do_test $TN.3.2.1 {
165     code2 { sqlite3 db2 test.db }
166     sql2 { INSERT INTO t1 VALUES(1, 2) ; PRAGMA wal_checkpoint=truncate }
167     code2 { db2 close }
168     sql1 { SELECT * FROM t1 }
169   } {a b c d e f g h 1 2}
170   do_test $TN.3.2.2 {
171     list [file size test.db-wal] [file size test.db-shm]
172   } {0 32768}
174   do_test $TN.3.3.0 {
175     code2 { sqlite3 db2 test.db }
176     sql2 { 
177       INSERT INTO t1 VALUES(3, 4);
178       INSERT INTO t1 VALUES(5, 6);
179       INSERT INTO t1 VALUES(7, 8);
180       INSERT INTO t1 VALUES(9, 10);
181     }
182     code2 { db2 close }
183     code1 { db close }
184     list [file size test.db-wal] [file size test.db-shm]
185   } [list [wal_file_size 4 1024] 32768]
186   do_test $TN.3.3.1 {
187     code1 { sqlite3 db file:test.db?readonly_shm=1 }
188     sql1 { SELECT * FROM t1 }
189   } {a b c d e f g h 1 2 3 4 5 6 7 8 9 10}
190   do_test $TN.3.3.2 {
191     code2 { sqlite3 db2 test.db }
192     sql2 { 
193       PRAGMA wal_checkpoint; 
194       DELETE FROM t1;
195       INSERT INTO t1 VALUES('i', 'ii');
196     }
197     code2 { db2 close }
198     list [file size test.db-wal] [file size test.db-shm]
199   } [list [wal_file_size 4 1024] 32768]
200   do_test $TN.3.3.3 {
201     sql1 { SELECT * FROM t1 }
202   } {i ii}
204   #-----------------------------------------------------------------------
205   #
206   #
207   catch { code1 { db close } }
208   catch { code2 { db2 close } }
209   catch { code3 { db3 close } }
211   do_test $TN.4.0 {
212     code1 { forcedelete test.db }
213     code1 { sqlite3 db test.db }
214     sql1 {
215       PRAGMA journal_mode = wal;
216       CREATE TABLE t1(x);
217       INSERT INTO t1 VALUES('hello');
218       INSERT INTO t1 VALUES('world');
219     }
221     copy_to_test2 $bZeroShm
223     code1 { db close }
224   } {}
226   do_test $TN.4.1.1 {
227     code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
228     sql2 { SELECT * FROM t1 }
229   } {hello world}
231   do_test $TN.4.1.2 {
232     code3 { sqlite3 db3 test.db2 }
233     sql3 {
234       INSERT INTO t1 VALUES('!');
235       PRAGMA wal_checkpoint = truncate;
236     }
237     code3 { db3 close }
238   } {}
239   do_test $TN.4.1.3 {
240     sql2 { SELECT * FROM t1 }
241   } {hello world !}
243   catch { code1 { db close } }
244   catch { code2 { db2 close } }
245   catch { code3 { db3 close } }
247   do_test $TN.4.2.1 {
248     code1 { sqlite3 db test.db }
249     sql1 {
250       INSERT INTO t1 VALUES('!');
251       INSERT INTO t1 VALUES('!');
253       PRAGMA cache_size = 10;
254       CREATE TABLE t2(x);
256       BEGIN;
257         WITH s(i) AS (
258           SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500
259           )
260         INSERT INTO t2 SELECT randomblob(500) FROM s;
261         SELECT count(*) FROM t2;
262     } 
263   } {500}
264   do_test $TN.4.2.2 {
265     file size test.db-wal
266   } {461152}
267   do_test $TN.4.2.4 {
268     file_control_persist_wal db 1; db close
270     copy_to_test2 $bZeroShm
271     code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
272     sql2 {
273       SELECT * FROM t1;
274       SELECT count(*) FROM t2;
275     }
276   } {hello world ! ! 0}
278   #-----------------------------------------------------------------------
279   #
280   #
281   catch { code1 { db close } }
282   catch { code2 { db2 close } }
283   catch { code3 { db3 close } }
285   do_test $TN.5.0 {
286     code1 { forcedelete test.db }
287     code1 { sqlite3 db test.db }
288     sql1 {
289       PRAGMA journal_mode = wal;
290       CREATE TABLE t1(x);
291       INSERT INTO t1 VALUES('hello');
292       INSERT INTO t1 VALUES('world');
293       INSERT INTO t1 VALUES('!');
294       INSERT INTO t1 VALUES('world');
295       INSERT INTO t1 VALUES('hello');
296     }
298     copy_to_test2 $bZeroShm
299     
300     code1 { db close }
301   } {}
303   do_test $TN.5.1 {
304     code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
305     sql2 {
306       SELECT * FROM t1;
307     }
308   } {hello world ! world hello}
310   do_test $TN.5.2 {
311     code1 {
312       proc handle_read {op args} {
313         if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
314           set ::res2 [sql2 { SELECT * FROM t1 }]
315         }
316         puts "$msg xRead $args"
317         return "SQLITE_OK"
318       }
319       testvfs tvfs -fullshm 1
321       sqlite3 db file:test.db2?vfs=tvfs
322       db eval { SELECT * FROM sqlite_master }
324       tvfs filter xRead
325       tvfs script handle_read
326     }
327     sql1 {
328       PRAGMA wal_checkpoint = truncate;
329     }
330     code1 { set ::res2 }
331   } {hello world ! world hello}
333   do_test $TN.5.3 {
334     code1 { db close }
335     code1 { tvfs delete }
336   } {}
338   #-----------------------------------------------------------------------
339   #
340   #
341   catch { code1 { db close } }
342   catch { code2 { db2 close } }
343   catch { code3 { db3 close } }
345   do_test $TN.6.1 {
346     code1 { forcedelete test.db }
347     code1 { sqlite3 db test.db }
348     sql1 {
349       PRAGMA journal_mode = wal;
350       CREATE TABLE t1(x);
351       INSERT INTO t1 VALUES('hello');
352       INSERT INTO t1 VALUES('world');
353       INSERT INTO t1 VALUES('!');
354       INSERT INTO t1 VALUES('world');
355       INSERT INTO t1 VALUES('hello');
356     }
358     copy_to_test2 $bZeroShm
359     
360     code1 { db close }
361   } {}
363   do_test $TN.6.2 {
364     code1 {
365       set ::nRem 5
366       proc handle_read {op args} {
367         if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
368           incr ::nRem -1
369           if {$::nRem==0} {
370             code2 { sqlite3 db2 test.db2 }
371             sql2  { PRAGMA wal_checkpoint = truncate }
372           }
373         }
374         return "SQLITE_OK"
375       }
376       testvfs tvfs -fullshm 1
378       tvfs filter xRead
379       tvfs script handle_read
381       sqlite3 db file:test.db2?readonly_shm=1&vfs=tvfs
382       db eval { SELECT * FROM t1 }
383     }
384   } {hello world ! world hello}
386   do_test $TN.6.3 {
387     code1 { db close }
388     code1 { tvfs delete }
389   } {}
391 } ;# foreach bZeroShm
393 finish_test