Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: third_party/sqlite/sqlite-src-3100200/ext/fts5/test/fts5corrupt3.test

Issue 1610543003: [sql] Import reference version of SQLite 3.10.2. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # 2015 Apr 24
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 # This file tests that FTS5 handles corrupt databases (i.e. internal
13 # inconsistencies in the backing tables) correctly. In this case
14 # "correctly" means without crashing.
15 #
16
17 source [file join [file dirname [info script]] fts5_common.tcl]
18 set testprefix fts5corrupt3
19
20 # If SQLITE_ENABLE_FTS5 is defined, omit this file.
21 ifcapable !fts5 {
22 finish_test
23 return
24 }
25 sqlite3_fts5_may_be_corrupt 1
26
27 proc create_t1 {} {
28 expr srand(0)
29 db func rnddoc fts5_rnddoc
30 db eval {
31 CREATE VIRTUAL TABLE t1 USING fts5(x);
32 INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
33 WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100)
34 INSERT INTO t1 SELECT rnddoc(10) FROM ii;
35 }
36 }
37
38 if 1 {
39
40 # Create a simple FTS5 table containing 100 documents. Each document
41 # contains 10 terms, each of which start with the character "x".
42 #
43 do_test 1.0 { create_t1 } {}
44
45 do_test 1.1 {
46 # Pick out the rowid of the right-most b-tree leaf in the new segment.
47 set rowid [db one {
48 SELECT max(rowid) FROM t1_data WHERE ((rowid>>31) & 0x0F)==1
49 }]
50 set L [db one {SELECT length(block) FROM t1_data WHERE rowid = $rowid}]
51 set {} {}
52 } {}
53
54 for {set i 0} {$i < $L} {incr i} {
55 do_test 1.2.$i {
56 catchsql {
57 BEGIN;
58 UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid;
59 INSERT INTO t1(t1) VALUES('integrity-check');
60 }
61 } {1 {database disk image is malformed}}
62 catchsql ROLLBACK
63 }
64
65 #-------------------------------------------------------------------------
66 # Test that trailing bytes appended to the averages record are ignored.
67 #
68 do_execsql_test 2.1 {
69 CREATE VIRTUAL TABLE t2 USING fts5(x);
70 INSERT INTO t2 VALUES(rnddoc(10));
71 INSERT INTO t2 VALUES(rnddoc(10));
72 SELECT length(block) FROM t2_data WHERE id=1;
73 } {2}
74 do_execsql_test 2.2 {
75 UPDATE t2_data SET block = block || 'abcd' WHERE id=1;
76 SELECT length(block) FROM t2_data WHERE id=1;
77 } {6}
78 do_execsql_test 2.2 {
79 INSERT INTO t2 VALUES(rnddoc(10));
80 SELECT length(block) FROM t2_data WHERE id=1;
81 } {2}
82
83
84 #-------------------------------------------------------------------------
85 # Test that missing leaf pages are recognized as corruption.
86 #
87 reset_db
88 do_test 3.0 { create_t1 } {}
89
90 do_execsql_test 3.1 {
91 SELECT count(*) FROM t1_data;
92 } {105}
93
94 proc do_3_test {tn} {
95 set i 0
96 foreach ::rowid [db eval "SELECT rowid FROM t1_data WHERE rowid>100"] {
97 incr i
98 do_test $tn.$i {
99 db eval BEGIN
100 db eval {DELETE FROM t1_data WHERE rowid = $::rowid}
101 list [
102 catch { db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'} } msg
103 ] $msg
104 } {1 {database disk image is malformed}}
105 catch { db eval ROLLBACK }
106 }
107 }
108
109 do_3_test 3.2
110
111 do_execsql_test 3.3 {
112 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
113 INSERT INTO t1 SELECT x FROM t1;
114 INSERT INTO t1(t1) VALUES('optimize');
115 } {}
116
117 do_3_test 3.4
118
119 do_test 3.5 {
120 execsql {
121 DELETE FROM t1;
122 INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
123 }
124 for {set i 0} {$i < 1000} {incr i} {
125 set rnd [expr int(rand() * 1000)]
126 set doc [string repeat "x$rnd " [expr int(rand() * 3) + 1]]
127 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
128 }
129 } {}
130
131 do_3_test 3.6
132
133 do_test 3.7 {
134 execsql {
135 INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
136 INSERT INTO t1 SELECT x FROM t1;
137 INSERT INTO t1(t1) VALUES('optimize');
138 }
139 } {}
140
141 do_3_test 3.8
142
143 do_test 3.9 {
144 execsql {
145 DELETE FROM t1;
146 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
147 }
148 for {set i 0} {$i < 100} {incr i} {
149 set rnd [expr int(rand() * 100)]
150 set doc "x[string repeat $rnd 20]"
151 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
152 }
153 } {}
154
155 do_3_test 3.10
156
157 #-------------------------------------------------------------------------
158 # Test that segments that end unexpectedly are identified as corruption.
159 #
160 reset_db
161 do_test 4.0 {
162 execsql {
163 CREATE VIRTUAL TABLE t1 USING fts5(x);
164 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
165 }
166 for {set i 0} {$i < 100} {incr i} {
167 set rnd [expr int(rand() * 100)]
168 set doc "x[string repeat $rnd 20]"
169 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
170 }
171 execsql { INSERT INTO t1(t1) VALUES('optimize') }
172 } {}
173
174 set nErr 0
175 for {set i 1} {1} {incr i} {
176 set struct [db one {SELECT block FROM t1_data WHERE id=10}]
177 binary scan $struct c* var
178 set end [lindex $var end]
179 if {$end<=$i} break
180 lset var end [expr $end - $i]
181 set struct [binary format c* $var]
182 db eval {
183 BEGIN;
184 UPDATE t1_data SET block = $struct WHERE id=10;
185 }
186 do_test 4.1.$i {
187 incr nErr [catch { db eval { SELECT rowid FROM t1 WHERE t1 MATCH 'x*' } }]
188 set {} {}
189 } {}
190 catch { db eval ROLLBACK }
191 }
192 do_test 4.1.x { expr $nErr>45 } 1
193
194 #-------------------------------------------------------------------------
195 #
196
197 # The first argument passed to this command must be a binary blob
198 # containing an FTS5 leaf page. This command returns a copy of this
199 # blob, with the pgidx of the leaf page replaced by a single varint
200 # containing value $iVal.
201 #
202 proc rewrite_pgidx {blob iVal} {
203 binary scan $blob SS off1 szLeaf
204 if {$iVal<0 || $iVal>=128} {
205 error "$iVal out of range!"
206 } else {
207 set pgidx [binary format c $iVal]
208 }
209
210 binary format a${szLeaf}a* $blob $pgidx
211 }
212
213 reset_db
214 do_execsql_test 5.1 {
215 CREATE VIRTUAL TABLE x1 USING fts5(x);
216 INSERT INTO x1(x1, rank) VALUES('pgsz', 40);
217 BEGIN;
218 INSERT INTO x1 VALUES('xaaa xabb xccc xcdd xeee xeff xggg xghh xiii xijj');
219 INSERT INTO x1 SELECT x FROM x1;
220 INSERT INTO x1 SELECT x FROM x1;
221 INSERT INTO x1 SELECT x FROM x1;
222 INSERT INTO x1 SELECT x FROM x1;
223 INSERT INTO x1(x1) VALUES('optimize');
224 COMMIT;
225 }
226
227 #db eval { SELECT fts5_decode(id, block) b from x1_data } { puts $b }
228 #
229 db func rewrite_pgidx rewrite_pgidx
230 set i 0
231 foreach rowid [db eval {SELECT rowid FROM x1_data WHERE rowid>100}] {
232 foreach val {2 100} {
233 do_test 5.2.$val.[incr i] {
234 catchsql {
235 BEGIN;
236 UPDATE x1_data SET block=rewrite_pgidx(block, $val) WHERE id=$rowid;
237 SELECT rowid FROM x1 WHERE x1 MATCH 'xa*';
238 SELECT rowid FROM x1 WHERE x1 MATCH 'xb*';
239 SELECT rowid FROM x1 WHERE x1 MATCH 'xc*';
240 SELECT rowid FROM x1 WHERE x1 MATCH 'xd*';
241 SELECT rowid FROM x1 WHERE x1 MATCH 'xe*';
242 SELECT rowid FROM x1 WHERE x1 MATCH 'xf*';
243 SELECT rowid FROM x1 WHERE x1 MATCH 'xg*';
244 SELECT rowid FROM x1 WHERE x1 MATCH 'xh*';
245 SELECT rowid FROM x1 WHERE x1 MATCH 'xi*';
246 }
247 set {} {}
248 } {}
249 catch { db eval ROLLBACK }
250 }
251 }
252
253 #------------------------------------------------------------------------
254 #
255 reset_db
256 do_execsql_test 6.1.0 {
257 CREATE VIRTUAL TABLE t1 USING fts5(a);
258 INSERT INTO t1 VALUES('bbbbb ccccc');
259 SELECT quote(block) FROM t1_data WHERE rowid>100;
260 } {X'000000180630626262626201020201056363636363010203040A'}
261 do_execsql_test 6.1.1 {
262 UPDATE t1_data SET block =
263 X'000000180630626262626201020201056161616161010203040A'
264 WHERE rowid>100;
265 }
266 do_catchsql_test 6.1.2 {
267 INSERT INTO t1(t1) VALUES('integrity-check');
268 } {1 {database disk image is malformed}}
269
270 #-------
271 reset_db
272 do_execsql_test 6.2.0 {
273 CREATE VIRTUAL TABLE t1 USING fts5(a);
274 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
275 INSERT INTO t1 VALUES('aa bb cc dd ee');
276 SELECT pgno, quote(term) FROM t1_idx;
277 } {2 X'' 4 X'3064'}
278 do_execsql_test 6.2.1 {
279 UPDATE t1_idx SET term = X'3065' WHERE pgno=4;
280 }
281 do_catchsql_test 6.2.2 {
282 INSERT INTO t1(t1) VALUES('integrity-check');
283 } {1 {database disk image is malformed}}
284
285 #-------
286 reset_db
287 do_execsql_test 6.3.0 {
288 CREATE VIRTUAL TABLE t1 USING fts5(a);
289 INSERT INTO t1 VALUES('abc abcdef abcdefghi');
290 SELECT quote(block) FROM t1_data WHERE id>100;
291 } {X'0000001C043061626301020204036465660102030703676869010204040808'}
292 do_execsql_test 6.3.1 {
293 BEGIN;
294 UPDATE t1_data SET block =
295 X'0000001C043061626301020204036465660102035003676869010204040808'
296 ------------------------------------------^^---------------------
297 WHERE id>100;
298 }
299 do_catchsql_test 6.3.2 {
300 INSERT INTO t1(t1) VALUES('integrity-check');
301 } {1 {database disk image is malformed}}
302 do_execsql_test 6.3.3 {
303 ROLLBACK;
304 BEGIN;
305 UPDATE t1_data SET block =
306 X'0000001C043061626301020204036465660102030750676869010204040808'
307 --------------------------------------------^^-------------------
308 WHERE id>100;
309 }
310 do_catchsql_test 6.3.3 {
311 INSERT INTO t1(t1) VALUES('integrity-check');
312 } {1 {database disk image is malformed}}
313 do_execsql_test 6.3.4 {
314 ROLLBACK;
315 BEGIN;
316 UPDATE t1_data SET block =
317 X'0000001C043061626301020204036465660102030707676869010204040850'
318 --------------------------------------------------------------^^-
319 WHERE id>100;
320 }
321 do_catchsql_test 6.3.5 {
322 INSERT INTO t1(t1) VALUES('integrity-check');
323 } {1 {database disk image is malformed}}
324 do_execsql_test 6.3.6 {
325 ROLLBACK;
326 BEGIN;
327 UPDATE t1_data SET block =
328 X'0000001C503061626301020204036465660102030707676869010204040808'
329 ----------^^-----------------------------------------------------
330 WHERE id>100;
331 }
332 do_catchsql_test 6.3.5 {
333 INSERT INTO t1(t1) VALUES('integrity-check');
334 } {1 {database disk image is malformed}}
335
336
337 }
338
339 #------------------------------------------------------------------------
340 #
341 reset_db
342 reset_db
343 proc rnddoc {n} {
344 set map [list a b c d]
345 set doc [list]
346 for {set i 0} {$i < $n} {incr i} {
347 lappend doc "x[lindex $map [expr int(rand()*4)]]"
348 }
349 set doc
350 }
351
352 db func rnddoc rnddoc
353 do_test 7.0 {
354 execsql {
355 CREATE VIRTUAL TABLE t5 USING fts5(x);
356 INSERT INTO t5 VALUES( rnddoc(10000) );
357 INSERT INTO t5 VALUES( rnddoc(10000) );
358 INSERT INTO t5 VALUES( rnddoc(10000) );
359 INSERT INTO t5 VALUES( rnddoc(10000) );
360 INSERT INTO t5(t5) VALUES('optimize');
361 }
362 } {}
363
364 do_test 7.1 {
365 foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] {
366 db eval BEGIN
367 db eval {DELETE FROM t5_data WHERE rowid = $i}
368 set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ]
369 if {$r != "1 {database disk image is malformed}"} { error $r }
370 db eval ROLLBACK
371 }
372 } {}
373
374 sqlite3_fts5_may_be_corrupt 0
375 finish_test
376
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698