xref: /sqlite-3.40.0/ext/fts5/test/fts5fault1.test (revision a690ff36)
1# 2014 June 17
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
12# focus of this script is testing the FTS5 module.
13#
14
15source [file join [file dirname [info script]] fts5_common.tcl]
16source $testdir/malloc_common.tcl
17set testprefix fts5fault1
18
19# If SQLITE_ENABLE_FTS3 is defined, omit this file.
20ifcapable !fts5 {
21  finish_test
22  return
23}
24
25# Simple tests:
26#
27#   1: CREATE VIRTUAL TABLE
28#   2: INSERT statement
29#   3: DELETE statement
30#   4: MATCH expressions
31#
32#
33
34faultsim_save_and_close
35do_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}}
41}
42
43reset_db
44do_execsql_test 2.0 {
45  CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
46}
47faultsim_save_and_close
48do_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}}
56}
57
58reset_db
59do_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');
62}
63faultsim_save_and_close
64do_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}}
70}
71
72reset_db
73do_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');
85}
86faultsim_save_and_close
87
88foreach {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  "
107}
108
109
110#-------------------------------------------------------------------------
111# The following tests use a larger database populated with random data.
112#
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.
117#
118reset_db
119do_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}
124
125proc 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
132}
133db func rnddoc rnddoc
134
135do_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;
141}
142
143set res [db one {
144  SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'}
145]
146
147do_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]
151}
152do_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]
156}
157
158proc test_astar {a b} {
159  return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }]
160}
161db func test_astar test_astar
162
163set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ]
164do_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]
168}
169
170do_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 {}]
177}
178
179do_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]
185}
186do_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]
192}
193do_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]
201}
202do_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]
210}
211
212#-------------------------------------------------------------------------
213#
214reset_db
215do_execsql_test 6.0 {
216  CREATE VIRTUAL TABLE x1 USING fts5(x);
217  INSERT INTO x1(x1, rank) VALUES('automerge', 0);
218
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
234
235  SELECT count(*) FROM x1_data;
236} {17}
237
238faultsim_save_and_close
239
240do_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  }
250}
251
252do_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 {}]
258}
259
260do_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 {}]
266}
267
268do_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 {}]
274}
275
276#-------------------------------------------------------------------------
277#
278do_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: }}
284}
285
286#-------------------------------------------------------------------------
287# A prefix query against a large document set.
288#
289proc 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
296}
297
298reset_db
299db func rnddoc rnddoc
300
301do_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} {}
309
310do_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]
317}
318
319#-------------------------------------------------------------------------
320# Segment promotion.
321#
322do_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  }
330
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}
336set insert_doc [db one {SELECT rnddoc(160)}]
337faultsim_save_and_close
338
339do_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  }
349}
350
351
352
353finish_test
354