OLD | NEW |
| (Empty) |
1 # 2015 December 10 | |
2 # | |
3 # The author disclaims copyright to this source code. In place of | |
4 # a legal notice, here is a blessing: | |
5 # | |
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. | |
9 # | |
10 #*********************************************************************** | |
11 # This file implements regression tests for SQLite library. The focus | |
12 # of this file is the sqlite3_snapshot_xxx() APIs. | |
13 # | |
14 | |
15 set testdir [file dirname $argv0] | |
16 source $testdir/tester.tcl | |
17 ifcapable !snapshot {finish_test; return} | |
18 set testprefix snapshot_fault | |
19 | |
20 #------------------------------------------------------------------------- | |
21 # Check that an sqlite3_snapshot_open() client cannot be tricked into | |
22 # reading a corrupt snapshot even if a second client fails while | |
23 # checkpointing the db. | |
24 # | |
25 do_faultsim_test 1.0 -prep { | |
26 faultsim_delete_and_reopen | |
27 sqlite3 db2 test.db | |
28 db2 eval { | |
29 CREATE TABLE t1(a, b UNIQUE, c UNIQUE); | |
30 INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500)); | |
31 INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500)); | |
32 PRAGMA journal_mode = wal; | |
33 INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500)); | |
34 BEGIN; | |
35 SELECT a FROM t1; | |
36 } | |
37 set ::snapshot [sqlite3_snapshot_get db2 main] | |
38 db2 eval COMMIT | |
39 db2 eval { | |
40 UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1; | |
41 INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500)); | |
42 INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500)); | |
43 INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500)); | |
44 } | |
45 } -body { | |
46 db eval { PRAGMA wal_checkpoint } | |
47 } -test { | |
48 db2 eval BEGIN | |
49 if {[catch { sqlite3_snapshot_open db2 main $::snapshot } msg]} { | |
50 if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} { | |
51 error "error is $msg" | |
52 } | |
53 } else { | |
54 set res [db2 eval { | |
55 SELECT a FROM t1; | |
56 PRAGMA integrity_check; | |
57 }] | |
58 if {$res != "1 2 3 ok"} { error "res is $res" } | |
59 } | |
60 | |
61 sqlite3_snapshot_free $::snapshot | |
62 } | |
63 | |
64 #------------------------------------------------------------------------- | |
65 # This test is similar to the previous one. Except, after the | |
66 # "PRAGMA wal_checkpoint" command fails the db is closed and reopened | |
67 # so as to require wal file recovery. It should not be possible to open | |
68 # a snapshot that is part of the body of a recovered wal file. | |
69 # | |
70 do_faultsim_test 2.0 -prep { | |
71 faultsim_delete_and_reopen | |
72 db eval { | |
73 CREATE TABLE t1(a, b UNIQUE, c UNIQUE); | |
74 INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500)); | |
75 INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500)); | |
76 PRAGMA journal_mode = wal; | |
77 INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500)); | |
78 BEGIN; | |
79 SELECT a FROM t1; | |
80 } | |
81 set ::snapshot [sqlite3_snapshot_get db main] | |
82 db eval COMMIT | |
83 | |
84 db eval { | |
85 UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1; | |
86 INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500)); | |
87 INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500)); | |
88 INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500)); | |
89 } | |
90 } -body { | |
91 db eval { PRAGMA wal_checkpoint } | |
92 } -test { | |
93 | |
94 db_save | |
95 db close | |
96 db_restore_and_reopen | |
97 db eval { SELECT * FROM t1 } | |
98 | |
99 db eval BEGIN | |
100 if {[catch { sqlite3_snapshot_open db main $::snapshot } msg]} { | |
101 if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} { | |
102 error "error is $msg" | |
103 } | |
104 } else { | |
105 # This branch should actually never be taken. But it was useful in | |
106 # determining whether or not this test was actually working (by | |
107 # running a modified version of SQLite that allowed snapshots to be | |
108 # opened following a recovery). | |
109 error "TEST HAS FAILED" | |
110 | |
111 set res [db eval { | |
112 SELECT a FROM t1; | |
113 PRAGMA integrity_check; | |
114 }] | |
115 if {$res != "1 2 3 ok"} { error "res is $res" } | |
116 } | |
117 | |
118 sqlite3_snapshot_free $::snapshot | |
119 } | |
120 | |
121 #------------------------------------------------------------------------- | |
122 # Test the handling of faults that occur within sqlite3_snapshot_open(). | |
123 # | |
124 do_faultsim_test 3.0 -prep { | |
125 faultsim_delete_and_reopen | |
126 db eval { | |
127 CREATE TABLE t1(a, b UNIQUE, c UNIQUE); | |
128 INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500)); | |
129 INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500)); | |
130 PRAGMA journal_mode = wal; | |
131 INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500)); | |
132 BEGIN; | |
133 SELECT a FROM t1; | |
134 } | |
135 set ::snapshot [sqlite3_snapshot_get db main] | |
136 db eval COMMIT | |
137 db eval { | |
138 UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1; | |
139 INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500)); | |
140 INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500)); | |
141 INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500)); | |
142 BEGIN; | |
143 } | |
144 } -body { | |
145 if { [catch { sqlite3_snapshot_open db main $::snapshot } msg] } { | |
146 error $msg | |
147 } | |
148 } -test { | |
149 faultsim_test_result {0 {}} {1 SQLITE_IOERR} \ | |
150 {1 SQLITE_IOERR_NOMEM} {1 SQLITE_IOERR_READ} | |
151 if {$testrc==0} { | |
152 set res [db eval { | |
153 SELECT a FROM t1; | |
154 PRAGMA integrity_check; | |
155 }] | |
156 if {$res != "1 2 3 ok"} { error "res is $res" } | |
157 } | |
158 | |
159 sqlite3_snapshot_free $::snapshot | |
160 } | |
161 | |
162 | |
163 | |
164 finish_test | |
OLD | NEW |