OLD | NEW |
| (Empty) |
1 # 2014 October 22 | |
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 # | |
12 | |
13 if {![info exists testdir]} { | |
14 set testdir [file join [file dirname [info script]] .. .. test] | |
15 } | |
16 source $testdir/tester.tcl | |
17 source $testdir/malloc_common.tcl | |
18 set ::testprefix rbufault | |
19 | |
20 proc copy_if_exists {src target} { | |
21 if {[file exists $src]} { | |
22 forcecopy $src $target | |
23 } else { | |
24 forcedelete $target | |
25 } | |
26 } | |
27 | |
28 foreach {tn2 setup sql expect} { | |
29 1 { | |
30 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
31 CREATE INDEX t1cb ON t1(c, b); | |
32 INSERT INTO t1 VALUES(1, 1, 1); | |
33 INSERT INTO t1 VALUES(2, 2, 2); | |
34 INSERT INTO t1 VALUES(3, 3, 3); | |
35 | |
36 CREATE TABLE rbu.data_t1(a, b, c, rbu_control); | |
37 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); | |
38 INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.'); | |
39 INSERT INTO data_t1 VALUES(4, 4, 4, 0); | |
40 } { | |
41 SELECT * FROM t1 | |
42 } {1 1 1 3 three 3 4 4 4} | |
43 | |
44 2 { | |
45 CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; | |
46 CREATE INDEX t2cb ON t2(c, b); | |
47 INSERT INTO t2 VALUES('a', 'a', 'a'); | |
48 INSERT INTO t2 VALUES('b', 'b', 'b'); | |
49 INSERT INTO t2 VALUES('c', 'c', 'c'); | |
50 | |
51 CREATE TABLE rbu.data_t2(a, b, c, rbu_control); | |
52 INSERT INTO data_t2 VALUES('b', NULL, NULL, 1); | |
53 INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.'); | |
54 INSERT INTO data_t2 VALUES('d', 'd', 'd', 0); | |
55 } { | |
56 SELECT * FROM t2 | |
57 } {a a a c see c d d d} | |
58 | |
59 3 { | |
60 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
61 CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; | |
62 CREATE INDEX t1cb ON t1(c, b); | |
63 CREATE INDEX t2cb ON t2(c, b); | |
64 | |
65 CREATE TABLE rbu.data_t1(a, b, c, rbu_control); | |
66 CREATE TABLE rbu.data_t2(a, b, c, rbu_control); | |
67 INSERT INTO data_t1 VALUES(1, 2, 3, 0); | |
68 INSERT INTO data_t2 VALUES(4, 5, 6, 0); | |
69 } { | |
70 SELECT * FROM t1 UNION ALL SELECT * FROM t2 | |
71 } {1 2 3 4 5 6} | |
72 | |
73 4 { | |
74 CREATE TABLE t1(a PRIMARY KEY, b, c); | |
75 CREATE INDEX t1c ON t1(c); | |
76 INSERT INTO t1 VALUES('A', 'B', 'C'); | |
77 INSERT INTO t1 VALUES('D', 'E', 'F'); | |
78 | |
79 CREATE TABLE rbu.data_t1(a, b, c, rbu_control); | |
80 INSERT INTO data_t1 VALUES('D', NULL, NULL, 1); | |
81 INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.'); | |
82 INSERT INTO data_t1 VALUES('G', 'H', 'I', 0); | |
83 } { | |
84 SELECT * FROM t1 ORDER BY a; | |
85 } {A Z C G H I} | |
86 | |
87 5 { | |
88 CREATE TABLE t1(a, b, c); | |
89 CREATE INDEX t1c ON t1(c, b); | |
90 | |
91 CREATE TABLE rbu.data_t1(a, b, c, rbu_rowid, rbu_control); | |
92 INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0); | |
93 INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0); | |
94 } { | |
95 SELECT * FROM t1 ORDER BY a; | |
96 } {a b c d e f} | |
97 | |
98 } { | |
99 catch {db close} | |
100 forcedelete rbu.db test.db | |
101 sqlite3 db test.db | |
102 execsql { | |
103 PRAGMA encoding = utf16; | |
104 ATTACH 'rbu.db' AS rbu; | |
105 } | |
106 execsql $setup | |
107 db close | |
108 | |
109 forcecopy test.db test.db.bak | |
110 forcecopy rbu.db rbu.db.bak | |
111 | |
112 foreach {tn f reslist} { | |
113 1 oom-tra* { | |
114 {0 SQLITE_DONE} | |
115 {1 {SQLITE_NOMEM - out of memory}} | |
116 {1 SQLITE_NOMEM} | |
117 {1 SQLITE_IOERR_NOMEM} | |
118 {1 {SQLITE_NOMEM - unable to open a temporary database file for storing te
mporary tables}} | |
119 } | |
120 | |
121 2 ioerr-* { | |
122 {0 SQLITE_DONE} | |
123 {1 {SQLITE_IOERR - disk I/O error}} | |
124 {1 SQLITE_IOERR} | |
125 {1 SQLITE_IOERR_WRITE} | |
126 {1 SQLITE_IOERR_READ} | |
127 {1 SQLITE_IOERR_FSYNC} | |
128 {1 {SQLITE_ERROR - SQL logic error or missing database}} | |
129 {1 {SQLITE_ERROR - unable to open database: rbu.db}} | |
130 {1 {SQLITE_IOERR - unable to open database: rbu.db}} | |
131 } | |
132 | |
133 3 shmerr-* { | |
134 {0 SQLITE_DONE} | |
135 {1 {SQLITE_IOERR - disk I/O error}} | |
136 {1 SQLITE_IOERR} | |
137 } | |
138 } { | |
139 | |
140 catch {db close} | |
141 sqlite3_shutdown | |
142 set lookaside_config [sqlite3_config_lookaside 0 0] | |
143 sqlite3_initialize | |
144 autoinstall_test_functions | |
145 | |
146 do_faultsim_test 2.$tn2 -faults $::f -prep { | |
147 catch { db close } | |
148 forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal | |
149 forcecopy test.db.bak test.db | |
150 forcecopy rbu.db.bak rbu.db | |
151 } -body { | |
152 sqlite3rbu rbu test.db rbu.db | |
153 while {[rbu step]=="SQLITE_OK"} {} | |
154 rbu close | |
155 } -test { | |
156 faultsim_test_result {*}$::reslist | |
157 if {$testrc==0} { | |
158 sqlite3 db test.db | |
159 faultsim_integrity_check | |
160 set res [db eval $::sql] | |
161 if {$res != [list {*}$::expect]} { | |
162 puts "" | |
163 puts "res: $res" | |
164 puts "exp: $expect" | |
165 error "data not as expected!" | |
166 } | |
167 } | |
168 } | |
169 | |
170 catch {db close} | |
171 sqlite3_shutdown | |
172 sqlite3_config_lookaside {*}$lookaside_config | |
173 sqlite3_initialize | |
174 autoinstall_test_functions | |
175 | |
176 | |
177 for {set iStep 0} {$iStep<=21} {incr iStep} { | |
178 | |
179 forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal | |
180 | |
181 copy_if_exists test.db.bak test.db | |
182 copy_if_exists rbu.db.bak rbu.db | |
183 | |
184 sqlite3rbu rbu test.db rbu.db | |
185 for {set x 0} {$x < $::iStep} {incr x} { rbu step } | |
186 rbu close | |
187 | |
188 # sqlite3 x rbu.db ; puts "XYZ [x eval { SELECT * FROM rbu_state } ]" ; x close | |
189 | |
190 copy_if_exists test.db test.db.bak.2 | |
191 copy_if_exists test.db-wal test.db.bak.2-wal | |
192 copy_if_exists test.db-oal test.db.bak.2-oal | |
193 copy_if_exists rbu.db rbu.db.bak.2 | |
194 | |
195 do_faultsim_test 3.$tn.$iStep -faults $::f -prep { | |
196 catch { db close } | |
197 forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal | |
198 copy_if_exists test.db.bak.2 test.db | |
199 copy_if_exists test.db.bak.2-wal test.db-wal | |
200 copy_if_exists test.db.bak.2-oal test.db-oal | |
201 copy_if_exists rbu.db.bak.2 rbu.db | |
202 } -body { | |
203 sqlite3rbu rbu test.db rbu.db | |
204 rbu step | |
205 rbu close | |
206 } -test { | |
207 | |
208 if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"} | |
209 faultsim_test_result {*}$::reslist | |
210 | |
211 if {$testrc==0} { | |
212 # No error occurred. If the RBU has not already been fully applied, | |
213 # apply the rest of it now. Then ensure that the final state of the | |
214 # target db is as expected. And that "PRAGMA integrity_check" | |
215 # passes. | |
216 sqlite3rbu rbu test.db rbu.db | |
217 while {[rbu step] == "SQLITE_OK"} {} | |
218 rbu close | |
219 | |
220 sqlite3 db test.db | |
221 faultsim_integrity_check | |
222 | |
223 set res [db eval $::sql] | |
224 if {$res != [list {*}$::expect]} { | |
225 puts "" | |
226 puts "res: $res" | |
227 puts "exp: $::expect" | |
228 error "data not as expected!" | |
229 } | |
230 } | |
231 } | |
232 } | |
233 } | |
234 } | |
235 | |
236 finish_test | |
237 | |
OLD | NEW |