skip uneccesary sqlcipher_free calls
[sqlcipher.git] / ext / fts5 / test / fts5fault4.test
blob1d0d5c9b7c4effc0205cd550de57d78dadb94847
1 # 2014 June 17
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 is focused on OOM errors.
15 source [file join [file dirname [info script]] fts5_common.tcl]
16 source $testdir/malloc_common.tcl
17 set testprefix fts5fault4
19 # If SQLITE_ENABLE_FTS5 is not defined, omit this file.
20 ifcapable !fts5 {
21   finish_test
22   return
25 set ::TMPDBERROR [list 1 \
26   {unable to open a temporary database file for storing temporary tables}
29 #-------------------------------------------------------------------------
30 # An OOM while dropping an fts5 table.
32 db func rnddoc fts5_rnddoc 
33 do_test 1.0 {
34   execsql { CREATE VIRTUAL TABLE xx USING fts5(x) }
35 } {}
36 faultsim_save_and_close
38 do_faultsim_test 1 -faults oom-* -prep {
39   faultsim_restore_and_reopen
40   execsql { SELECT * FROM xx }
41 } -body {
42   execsql { DROP TABLE xx }
43 } -test {
44   faultsim_test_result [list 0 {}]
47 #-------------------------------------------------------------------------
48 # An OOM while "reseeking" an FTS cursor.
50 do_execsql_test 3.0 {
51   CREATE VIRTUAL TABLE jj USING fts5(j);
52   INSERT INTO jj(rowid, j) VALUES(101, 'm t w t f s s');
53   INSERT INTO jj(rowid, j) VALUES(202, 't w t f s');
54   INSERT INTO jj(rowid, j) VALUES(303, 'w t f');
55   INSERT INTO jj(rowid, j) VALUES(404, 't');
57 faultsim_save_and_close
59 do_faultsim_test 3 -faults oom-* -prep {
60   faultsim_restore_and_reopen
61   execsql { SELECT * FROM jj }
62 } -body {
63   set res [list]
64   db eval { SELECT rowid FROM jj WHERE jj MATCH 't' } {
65     lappend res $rowid
66     if {$rowid==303} {
67       execsql { DELETE FROM jj WHERE rowid=404 }
68     }
69   }
70   set res
71 } -test {
72   faultsim_test_result [list 0 {101 202 303}]
75 #-------------------------------------------------------------------------
76 # An OOM within a special "*reads" query.
78 reset_db
79 db func rnddoc fts5_rnddoc
80 do_execsql_test 4.0 {
81   CREATE VIRTUAL TABLE x1 USING fts5(x);
82   INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
84   WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 )
85   INSERT INTO x1 SELECT rnddoc(5) FROM ii;
88 set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
90 do_faultsim_test 4 -faults oom-* -body {
91   db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
92 } -test {
93   faultsim_test_result {0 {0 {} 3}}
96 #-------------------------------------------------------------------------
97 # An OOM within a query that uses a custom rank function.
99 reset_db
100 do_execsql_test 5.0 {
101   PRAGMA encoding='utf16';
102   CREATE VIRTUAL TABLE x2 USING fts5(x);
103   INSERT INTO x2(rowid, x) VALUES(10, 'a b c'); -- 3
104   INSERT INTO x2(rowid, x) VALUES(20, 'a b c'); -- 6
105   INSERT INTO x2(rowid, x) VALUES(30, 'a b c'); -- 2
106   INSERT INTO x2(rowid, x) VALUES(40, 'a b c'); -- 5
107   INSERT INTO x2(rowid, x) VALUES(50, 'a b c'); -- 1
110 proc rowidmod {cmd mod} { 
111   set row [$cmd xRowid]
112   expr {$row % $mod}
114 sqlite3_fts5_create_function db rowidmod rowidmod
116 do_faultsim_test 5.1 -faults oom-* -body {
117   db eval {
118     SELECT rowid || '-' || rank FROM x2 WHERE x2 MATCH 'b' AND 
119     rank MATCH "rowidmod('7')" ORDER BY rank
120   }
121 } -test {
122   faultsim_test_result {0 {50-1 30-2 10-3 40-5 20-6}}
125 proc rowidprefix {cmd prefix} { 
126   set row [$cmd xRowid]
127   set {} "${row}-${prefix}"
129 sqlite3_fts5_create_function db rowidprefix rowidprefix
131 set str [string repeat abcdefghijklmnopqrstuvwxyz 10]
132 do_faultsim_test 5.2 -faults oom-* -body {
133   db eval "
134     SELECT rank, x FROM x2 WHERE x2 MATCH 'b' AND 
135     rank MATCH 'rowidprefix(''$::str'')'
136     LIMIT 1
137   "
138 } -test {
139   faultsim_test_result "0 {10-$::str {a b c}}"
143 #-------------------------------------------------------------------------
144 # OOM errors within auxiliary functions.
146 reset_db
147 do_execsql_test 6.0 {
148   CREATE VIRTUAL TABLE x3 USING fts5(xxx);
149   INSERT INTO x3 VALUES('a b c d c b a');
150   INSERT INTO x3 VALUES('a a a a a a a');
151   INSERT INTO x3 VALUES('a a a a a a a');
154 do_faultsim_test 6.1 -faults oom-t* -body {
155   db eval { SELECT highlight(x3, 0, '*', '*') FROM x3 WHERE x3 MATCH 'c' }
156 } -test {
157   faultsim_test_result {0 {{a b *c* d *c* b a}}}
160 proc firstinst {cmd} { 
161   foreach {p c o} [$cmd xInst 0] {}
162   expr $c*100 + $o
164 sqlite3_fts5_create_function db firstinst firstinst
166 do_faultsim_test 6.2 -faults oom-t* -body {
167   db eval { SELECT firstinst(x3) FROM x3 WHERE x3 MATCH 'c' }
168 } -test {
169   faultsim_test_result {0 2} {1 SQLITE_NOMEM}
172 proc previc {cmd} {
173   set res [$cmd xGetAuxdataInt 0]
174   $cmd xSetAuxdataInt [$cmd xInstCount]
175   return $res
177 sqlite3_fts5_create_function db previc  previc
179 do_faultsim_test 6.2 -faults oom-t* -body {
180   db eval { SELECT previc(x3) FROM x3 WHERE x3 MATCH 'a' }
181 } -test {
182   faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM}
185 #-------------------------------------------------------------------------
186 # OOM error when querying for a phrase with many tokens.
188 reset_db
189 do_execsql_test 7.0 {
190   CREATE VIRTUAL TABLE tt USING fts5(x, y);
191   INSERT INTO tt VALUES('f b g b c b', 'f a d c c b');  -- 1
192   INSERT INTO tt VALUES('d a e f e d', 'f b b d e e');  -- 2
193   INSERT INTO tt VALUES('f b g a d c', 'e f c f a d');  -- 3
194   INSERT INTO tt VALUES('f f c d g f', 'f a e b g b');  -- 4
195   INSERT INTO tt VALUES('a g b d a g', 'e g a e a c');  -- 5
196   INSERT INTO tt VALUES('c d b d e f', 'f g e g e e');  -- 6
197   INSERT INTO tt VALUES('e g f f b c', 'f c e f g f');  -- 7
198   INSERT INTO tt VALUES('e g c f c e', 'f e e a f g');  -- 8
199   INSERT INTO tt VALUES('e a e b e e', 'd c c f f f');  -- 9
200   INSERT INTO tt VALUES('f a g g c c', 'e g d g c e');  -- 10
201   INSERT INTO tt VALUES('c d b a e f', 'f g e h e e');  -- 11
203   CREATE VIRTUAL TABLE tt2 USING fts5(o);
204   INSERT INTO tt2(rowid, o) SELECT rowid, x||' '||y FROM tt;
205   INSERT INTO tt2(rowid, o) VALUES(12, 'a b c d e f g h i j k l');
208 do_faultsim_test 7.2 -faults oom-* -body {
209   db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' }
210 } -test {
211   faultsim_test_result {0 6} {1 SQLITE_NOMEM}
214 do_faultsim_test 7.3 -faults oom-* -body {
215   db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' }
216 } -test {
217   faultsim_test_result {0 11} {1 SQLITE_NOMEM}
220 do_faultsim_test 7.4 -faults oom-t* -body {
221   db eval { SELECT rowid FROM tt2 WHERE tt2 MATCH '"g c f c e f e e a f"' }
222 } -test {
223   faultsim_test_result {0 8} {1 SQLITE_NOMEM}
226 do_faultsim_test 7.5 -faults oom-* -body {
227   db eval {SELECT rowid FROM tt2 WHERE tt2 MATCH 'NEAR(a b c d e f g h i j k)'}
228 } -test {
229   faultsim_test_result {0 12} {1 SQLITE_NOMEM}
232 do_faultsim_test 7.6 -faults oom-* -body {
233   db eval {SELECT rowid FROM tt WHERE tt MATCH 'y: "c c"'}
234 } -test {
235   faultsim_test_result {0 {1 9}} {1 SQLITE_NOMEM}
238 #-------------------------------------------------------------------------
240 reset_db
241 do_execsql_test 8.0 {
242   CREATE VIRTUAL TABLE tt USING fts5(x);
243   INSERT INTO tt(tt, rank) VALUES('pgsz', 32);
244   BEGIN;
245     INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x');
246     WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99)
247       INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii;
248     INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x');
249   COMMIT;
252 do_faultsim_test 8.1 -faults oom-t* -body {
253   db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' }
254 } -test {
255   faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM}
258 do_faultsim_test 8.2 -faults oom-t* -body {
259   db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' }
260 } -test {
261   faultsim_test_result {0 100} {1 SQLITE_NOMEM}
265 #-------------------------------------------------------------------------
266 # Fault in NOT query.
268 reset_db
269 do_execsql_test 9.0 {
270   CREATE VIRTUAL TABLE tt USING fts5(x);
271   INSERT INTO tt(tt, rank) VALUES('pgsz', 32);
272   BEGIN;
273     WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200)
274       INSERT INTO tt(rowid, x) 
275       SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END 
276       FROM ii;
277   COMMIT;
280 do_faultsim_test 9.1 -faults oom-* -body {
281   db eval { SELECT rowid FROM tt WHERE tt MATCH 'a NOT x' }
282 } -test {
283   faultsim_test_result {0 {50 100 150 200}} {1 SQLITE_NOMEM}
286 #-------------------------------------------------------------------------
287 # OOM in fts5_expr() SQL function.
289 do_faultsim_test 10.1 -faults oom-t* -body {
290   db one { SELECT fts5_expr('a AND b NEAR(a b)') }
291 } -test {
292   faultsim_test_result {0 {"a" AND "b" AND NEAR("a" "b", 10)}} 
295 do_faultsim_test 10.2 -faults oom-t* -body {
296   db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') }
297 } -test {
298   set res {AND [ns -col 0 -- {a b c}] [ns -- {b}] [ns -near 10 -- {a} {b}]}
299   faultsim_test_result [list 0 $res]
302 do_faultsim_test 10.3 -faults oom-t* -body {
303   db one { SELECT fts5_expr('x:a', 'x') }
304 } -test {
305   faultsim_test_result {0 {x : "a"}}
308 #-------------------------------------------------------------------------
309 # OOM while configuring 'rank' option.
311 reset_db
312 do_execsql_test 11.0 {
313   CREATE VIRTUAL TABLE ft USING fts5(x);
315 do_faultsim_test 11.1 -faults oom-t* -body {
316   db eval { INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)') }
317 } -test {
318   faultsim_test_result {0 {}} {1 {disk I/O error}}
321 #-------------------------------------------------------------------------
322 # OOM while creating an fts5vocab table.
324 reset_db
325 do_execsql_test 12.0 {
326   CREATE VIRTUAL TABLE ft USING fts5(x);
328 faultsim_save_and_close
329 do_faultsim_test 12.1 -faults oom-t* -prep {
330   faultsim_restore_and_reopen
331   db eval { SELECT * FROM sqlite_master }
332 } -body {
333   db eval { CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row') }
334 } -test {
335   faultsim_test_result {0 {}} 
338 #-------------------------------------------------------------------------
339 # OOM while querying an fts5vocab table.
341 reset_db
342 do_execsql_test 13.0 {
343   CREATE VIRTUAL TABLE ft USING fts5(x);
344   INSERT INTO ft VALUES('a b');
345   CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row');
347 faultsim_save_and_close
348 do_faultsim_test 13.1 -faults oom-t* -prep {
349   faultsim_restore_and_reopen
350   db eval { SELECT * FROM vv }
351 } -body {
352   db eval { SELECT * FROM vv }
353 } -test {
354   faultsim_test_result {0 {a 1 1 b 1 1}} 
357 #-------------------------------------------------------------------------
358 # OOM in multi-column token query.
360 reset_db
361 do_execsql_test 13.0 {
362   CREATE VIRTUAL TABLE ft USING fts5(x, y, z);
363   INSERT INTO ft(ft, rank) VALUES('pgsz', 32);
364   INSERT INTO ft VALUES(
365       'x x x x x x x x x x x x x x x x',
366       'y y y y y y y y y y y y y y y y',
367       'z z z z z z z z x x x x x x x x'
368   );
369   INSERT INTO ft SELECT * FROM ft;
370   INSERT INTO ft SELECT * FROM ft;
371   INSERT INTO ft SELECT * FROM ft;
372   INSERT INTO ft SELECT * FROM ft;
374 faultsim_save_and_close
375 do_faultsim_test 13.1 -faults oom-t* -prep {
376   faultsim_restore_and_reopen
377   db eval { SELECT * FROM ft }
378 } -body {
379   db eval { SELECT rowid FROM ft WHERE ft MATCH '{x z}: x' }
380 } -test {
381   faultsim_test_result {0 {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}}
384 #-------------------------------------------------------------------------
385 # OOM in an "ALTER TABLE RENAME TO"
387 reset_db
388 do_execsql_test 14.0 {
389   CREATE VIRTUAL TABLE "tbl one" USING fts5(x, y, z);
391 faultsim_save_and_close
392 do_faultsim_test 14.1 -faults oom-t* -prep {
393   faultsim_restore_and_reopen
394   db eval { SELECT * FROM "tbl one" }
395 } -body {
396   db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" }
397 } -test {
398   faultsim_test_result {0 {}} $::TMPDBERROR
401 finish_test