Snapshot of upstream SQLite 3.46.1
[sqlcipher.git] / ext / fts5 / test / fts5fault1.test
blob96025133e45789788ffd073200dfaf9678cc25c1
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 #*************************************************************************
11 # This file implements regression tests for SQLite library.  The
12 # focus of this script is testing the FTS5 module.
15 source [file join [file dirname [info script]] fts5_common.tcl]
16 source $testdir/malloc_common.tcl
17 set testprefix fts5fault1
19 # If SQLITE_ENABLE_FTS3 is defined, omit this file.
20 ifcapable !fts5 {
21   finish_test
22   return
25 # Simple tests:
27 #   1: CREATE VIRTUAL TABLE
28 #   2: INSERT statement
29 #   3: DELETE statement
30 #   4: MATCH expressions
34 faultsim_save_and_close
35 do_faultsim_test 1 -faults ioerr-t* -prep {
36   faultsim_restore_and_reopen
37 } -body {
38   execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3') }
39 } -test {
40   faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
43 reset_db
44 do_execsql_test 2.0 {
45   CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
47 faultsim_save_and_close
48 do_faultsim_test 2 -prep {
49   faultsim_restore_and_reopen
50 } -body {
51   execsql { 
52     INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
53   }
54 } -test {
55   faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
58 reset_db
59 do_execsql_test 3.0 {
60   CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
61   INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
63 faultsim_save_and_close
64 do_faultsim_test 3 -prep {
65   faultsim_restore_and_reopen
66 } -body {
67   execsql { DELETE FROM t1 }
68 } -test {
69   faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
72 reset_db
73 do_execsql_test 4.0 {
74   CREATE VIRTUAL TABLE t2 USING fts5(a, b);
75   INSERT INTO t2 VALUES('m f a jj th q gi ar',   'hj n h h sg j i m');
76   INSERT INTO t2 VALUES('nr s t g od j kf h',    'sb h aq rg op rb n nl');
77   INSERT INTO t2 VALUES('do h h pb p p q fr',    'c rj qs or cr a l i');
78   INSERT INTO t2 VALUES('lk gp t i lq mq qm p',  'h mr g f op ld aj h');
79   INSERT INTO t2 VALUES('ct d sq kc qi k f j',   'sn gh c of g s qt q');
80   INSERT INTO t2 VALUES('d ea d d om mp s ab',   'dm hg l df cm ft pa c');
81   INSERT INTO t2 VALUES('tc dk c jn n t sr ge',  'a a kn bc n i af h');
82   INSERT INTO t2 VALUES('ie ii d i b sa qo rf',  'a h m aq i b m fn');
83   INSERT INTO t2 VALUES('gs r fo a er m h li',   'tm c p gl eb ml q r');
84   INSERT INTO t2 VALUES('k fe fd rd a gi ho kk', 'ng m c r d ml rm r');
86 faultsim_save_and_close
88 foreach {tn expr res} {
89   1 { dk  }           7
90   2 { m f }           1
91   3 { f*  }           {1 3 4 5 6 8 9 10}
92   4 { m OR f }        {1 4 5 8 9 10}
93   5 { sn + gh }       {5}
94   6 { "sn gh" }       {5}
95   7 { NEAR(r a, 5) }  {9}
96   8 { m* f* }         {1 4 6 8 9 10}
97   9 { m* + f* }       {1 8}
98   10 { c NOT p }       {5 6 7 10}
99 } {
100   do_faultsim_test 4.$tn -prep {
101     faultsim_restore_and_reopen
102   } -body "
103     execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' }
104   " -test "
105     faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}}
106   "
110 #-------------------------------------------------------------------------
111 # The following tests use a larger database populated with random data.
113 # The database page size is set to 512 bytes and the FTS5 page size left
114 # at the default 1000 bytes. This means that reading a node may require
115 # pulling an overflow page from disk, which is an extra opportunity for
116 # an error to occur.
118 reset_db
119 do_execsql_test 5.0.1 { 
120   PRAGMA main.page_size = 512;
121   CREATE VIRTUAL TABLE x1 USING fts5(a, b);
122   PRAGMA main.page_size;
123 } {512}
125 proc rnddoc {n} {
126   set map [list 0 a  1 b  2 c  3 d  4 e  5 f  6 g  7 h  8 i  9 j]
127   set doc [list]
128   for {set i 0} {$i < $n} {incr i} {
129     lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]]
130   }
131   set doc
133 db func rnddoc rnddoc
135 do_execsql_test 5.0.2 {
136   WITH r(a, b) AS (
137     SELECT rnddoc(6), rnddoc(6) UNION ALL
138     SELECT rnddoc(6), rnddoc(6) FROM r
139   )
140   INSERT INTO x1 SELECT * FROM r LIMIT 10000;
143 set res [db one {
144   SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'}
147 do_faultsim_test 5.1 -faults oom* -body {
148   execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abc' }
149 } -test {
150   faultsim_test_result [list 0 $::res]
152 do_faultsim_test 5.2 -faults oom* -body {
153   execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abcd' }
154 } -test {
155   faultsim_test_result [list 0 0]
158 proc test_astar {a b} {
159   return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }]
161 db func test_astar test_astar
163 set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ]
164 do_faultsim_test 5.3 -faults oom* -body {
165   execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'a*' }
166 } -test {
167   faultsim_test_result [list 0 $::res]
170 do_faultsim_test 5.4 -faults oom* -prep {
171   db close
172   sqlite3 db test.db
173 } -body {
174   execsql { INSERT INTO x1 VALUES('a b c d', 'e f g h') }
175 } -test {
176   faultsim_test_result [list 0 {}]
179 do_faultsim_test 5.5.1 -faults oom* -body {
180   execsql { 
181     SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1
182   }
183 } -test {
184   faultsim_test_result [list 0 1]
186 do_faultsim_test 5.5.2 -faults oom* -body {
187   execsql { 
188     SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10
189   }
190 } -test {
191   faultsim_test_result [list 0 1]
193 do_faultsim_test 5.5.3 -faults oom* -body {
194   execsql { 
195     SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
196       SELECT min(rowid) FROM x1_data WHERE rowid>20
197     )
198   }
199 } -test {
200   faultsim_test_result [list 0 1]
202 do_faultsim_test 5.5.4 -faults oom* -body {
203   execsql { 
204     SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
205       SELECT max(rowid) FROM x1_data 
206     )
207   }
208 } -test {
209   faultsim_test_result [list 0 1]
212 #-------------------------------------------------------------------------
214 reset_db
215 do_execsql_test 6.0 {
216   CREATE VIRTUAL TABLE x1 USING fts5(x);
217   INSERT INTO x1(x1, rank) VALUES('automerge', 0);
219   INSERT INTO x1 VALUES('a b c'); -- 1
220   INSERT INTO x1 VALUES('a b c'); -- 2
221   INSERT INTO x1 VALUES('a b c'); -- 3
222   INSERT INTO x1 VALUES('a b c'); -- 4
223   INSERT INTO x1 VALUES('a b c'); -- 5
224   INSERT INTO x1 VALUES('a b c'); -- 6
225   INSERT INTO x1 VALUES('a b c'); -- 7
226   INSERT INTO x1 VALUES('a b c'); -- 8
227   INSERT INTO x1 VALUES('a b c'); -- 9
228   INSERT INTO x1 VALUES('a b c'); -- 10
229   INSERT INTO x1 VALUES('a b c'); -- 11
230   INSERT INTO x1 VALUES('a b c'); -- 12
231   INSERT INTO x1 VALUES('a b c'); -- 13
232   INSERT INTO x1 VALUES('a b c'); -- 14
233   INSERT INTO x1 VALUES('a b c'); -- 15
235   SELECT count(*) FROM x1_data;
236 } {17}
238 faultsim_save_and_close
240 do_faultsim_test 6.1 -faults oom* -prep {
241   faultsim_restore_and_reopen
242 } -body {
243   execsql { INSERT INTO x1 VALUES('d e f') }
244 } -test {
245   faultsim_test_result [list 0 {}]
246   if {$testrc==0} {
247     set nCnt [db one {SELECT count(*) FROM x1_data}]
248     if {$nCnt!=3} { error "expected 3 entries but there are $nCnt" }
249   }
252 do_faultsim_test 6.2 -faults oom* -prep {
253   faultsim_restore_and_reopen
254 } -body {
255   execsql { INSERT INTO x1(x1, rank) VALUES('pgsz', 32) }
256 } -test {
257   faultsim_test_result [list 0 {}]
260 do_faultsim_test 6.3 -faults oom-* -prep {
261   faultsim_restore_and_reopen
262 } -body {
263   execsql { INSERT INTO x1(x1) VALUES('integrity-check') }
264 } -test {
265   faultsim_test_result [list 0 {}]
268 do_faultsim_test 6.4 -faults oom-* -prep {
269   faultsim_restore_and_reopen
270 } -body {
271   execsql { INSERT INTO x1(x1) VALUES('optimize') }
272 } -test {
273   faultsim_test_result [list 0 {}]
276 #-------------------------------------------------------------------------
278 do_faultsim_test 7.0 -faults oom* -prep {
279   catch { db close }
280 } -body {
281   sqlite3 db test.db
282 } -test {
283   faultsim_test_result [list 0 {}] {1 {}} {1 {initialization of fts5 failed: }}
286 #-------------------------------------------------------------------------
287 # A prefix query against a large document set.
289 proc rnddoc {n} {
290   set map [list 0 a  1 b  2 c  3 d  4 e  5 f  6 g  7 h  8 i  9 j]
291   set doc [list]
292   for {set i 0} {$i < $n} {incr i} {
293     lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]"
294   }
295   set doc
298 reset_db
299 db func rnddoc rnddoc
301 do_test 8.0 {
302   execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) }
303   set ::res [list]
304   for {set i 1} {$i<100} {incr i 1} {
305     execsql { INSERT INTO x1 VALUES( rnddoc(50) ) }
306     lappend ::res $i
307   }
308 } {}
310 do_faultsim_test 8.1 -faults oom* -prep {
311 } -body {
312   execsql { 
313     SELECT rowid FROM x1 WHERE x1 MATCH 'x*'
314   }
315 } -test {
316   faultsim_test_result [list 0 $::res]
319 #-------------------------------------------------------------------------
320 # Segment promotion.
322 do_test 9.0 {
323   reset_db
324   db func rnddoc fts5_rnddoc
325   execsql {
326     CREATE VIRTUAL TABLE s2 USING fts5(x);
327     INSERT INTO s2(s2, rank) VALUES('pgsz', 32);
328     INSERT INTO s2(s2, rank) VALUES('automerge', 0);
329   }
331   for {set i 1} {$i <= 16} {incr i} {
332     execsql { INSERT INTO s2 VALUES(rnddoc(5)) }
333   }
334   fts5_level_segs s2
335 } {0 1}
336 set insert_doc [db one {SELECT rnddoc(160)}]
337 faultsim_save_and_close
339 do_faultsim_test 9.1 -faults oom-* -prep {
340   faultsim_restore_and_reopen
341 } -body {
342   execsql { INSERT INTO s2 VALUES($::insert_doc) }
343 } -test {
344   faultsim_test_result {0 {}}
345   if {$testrc==0} {
346     set ls [fts5_level_segs s2]
347     if {$ls != "2 0"} { error "fts5_level_segs says {$ls}" }
348   }
353 finish_test