OLD | NEW |
| (Empty) |
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 | |
15 source [file join [file dirname [info script]] fts5_common.tcl] | |
16 source $testdir/malloc_common.tcl | |
17 set testprefix fts5fault1 | |
18 | |
19 # If SQLITE_ENABLE_FTS3 is defined, omit this file. | |
20 ifcapable !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 | |
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}} | |
41 } | |
42 | |
43 reset_db | |
44 do_execsql_test 2.0 { | |
45 CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3'); | |
46 } | |
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}} | |
56 } | |
57 | |
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'); | |
62 } | |
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}} | |
70 } | |
71 | |
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 jr 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 } | |
86 faultsim_save_and_close | |
87 | |
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 } { | |
99 do_faultsim_test 4.$tn -prep { | |
100 faultsim_restore_and_reopen | |
101 } -body " | |
102 execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' } | |
103 " -test " | |
104 faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}} | |
105 " | |
106 } | |
107 | |
108 | |
109 #------------------------------------------------------------------------- | |
110 # The following tests use a larger database populated with random data. | |
111 # | |
112 # The database page size is set to 512 bytes and the FTS5 page size left | |
113 # at the default 1000 bytes. This means that reading a node may require | |
114 # pulling an overflow page from disk, which is an extra opportunity for | |
115 # an error to occur. | |
116 # | |
117 reset_db | |
118 do_execsql_test 5.0.1 { | |
119 PRAGMA main.page_size = 512; | |
120 CREATE VIRTUAL TABLE x1 USING fts5(a, b); | |
121 PRAGMA main.page_size; | |
122 } {512} | |
123 | |
124 proc rnddoc {n} { | |
125 set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] | |
126 set doc [list] | |
127 for {set i 0} {$i < $n} {incr i} { | |
128 lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]] | |
129 } | |
130 set doc | |
131 } | |
132 db func rnddoc rnddoc | |
133 | |
134 do_execsql_test 5.0.2 { | |
135 WITH r(a, b) AS ( | |
136 SELECT rnddoc(6), rnddoc(6) UNION ALL | |
137 SELECT rnddoc(6), rnddoc(6) FROM r | |
138 ) | |
139 INSERT INTO x1 SELECT * FROM r LIMIT 10000; | |
140 } | |
141 | |
142 set res [db one { | |
143 SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'} | |
144 ] | |
145 | |
146 do_faultsim_test 5.1 -faults oom* -body { | |
147 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abc' } | |
148 } -test { | |
149 faultsim_test_result [list 0 $::res] | |
150 } | |
151 do_faultsim_test 5.2 -faults oom* -body { | |
152 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abcd' } | |
153 } -test { | |
154 faultsim_test_result [list 0 0] | |
155 } | |
156 | |
157 proc test_astar {a b} { | |
158 return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }] | |
159 } | |
160 db func test_astar test_astar | |
161 | |
162 set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ] | |
163 do_faultsim_test 5.3 -faults oom* -body { | |
164 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'a*' } | |
165 } -test { | |
166 faultsim_test_result [list 0 $::res] | |
167 } | |
168 | |
169 do_faultsim_test 5.4 -faults oom* -prep { | |
170 db close | |
171 sqlite3 db test.db | |
172 } -body { | |
173 execsql { INSERT INTO x1 VALUES('a b c d', 'e f g h') } | |
174 } -test { | |
175 faultsim_test_result [list 0 {}] | |
176 } | |
177 | |
178 do_faultsim_test 5.5.1 -faults oom* -body { | |
179 execsql { | |
180 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1 | |
181 } | |
182 } -test { | |
183 faultsim_test_result [list 0 1] | |
184 } | |
185 do_faultsim_test 5.5.2 -faults oom* -body { | |
186 execsql { | |
187 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10 | |
188 } | |
189 } -test { | |
190 faultsim_test_result [list 0 1] | |
191 } | |
192 do_faultsim_test 5.5.3 -faults oom* -body { | |
193 execsql { | |
194 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( | |
195 SELECT min(rowid) FROM x1_data WHERE rowid>20 | |
196 ) | |
197 } | |
198 } -test { | |
199 faultsim_test_result [list 0 1] | |
200 } | |
201 do_faultsim_test 5.5.4 -faults oom* -body { | |
202 execsql { | |
203 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( | |
204 SELECT max(rowid) FROM x1_data | |
205 ) | |
206 } | |
207 } -test { | |
208 faultsim_test_result [list 0 1] | |
209 } | |
210 | |
211 #------------------------------------------------------------------------- | |
212 # | |
213 reset_db | |
214 do_execsql_test 6.0 { | |
215 CREATE VIRTUAL TABLE x1 USING fts5(x); | |
216 INSERT INTO x1(x1, rank) VALUES('automerge', 0); | |
217 | |
218 INSERT INTO x1 VALUES('a b c'); -- 1 | |
219 INSERT INTO x1 VALUES('a b c'); -- 2 | |
220 INSERT INTO x1 VALUES('a b c'); -- 3 | |
221 INSERT INTO x1 VALUES('a b c'); -- 4 | |
222 INSERT INTO x1 VALUES('a b c'); -- 5 | |
223 INSERT INTO x1 VALUES('a b c'); -- 6 | |
224 INSERT INTO x1 VALUES('a b c'); -- 7 | |
225 INSERT INTO x1 VALUES('a b c'); -- 8 | |
226 INSERT INTO x1 VALUES('a b c'); -- 9 | |
227 INSERT INTO x1 VALUES('a b c'); -- 10 | |
228 INSERT INTO x1 VALUES('a b c'); -- 11 | |
229 INSERT INTO x1 VALUES('a b c'); -- 12 | |
230 INSERT INTO x1 VALUES('a b c'); -- 13 | |
231 INSERT INTO x1 VALUES('a b c'); -- 14 | |
232 INSERT INTO x1 VALUES('a b c'); -- 15 | |
233 | |
234 SELECT count(*) FROM x1_data; | |
235 } {17} | |
236 | |
237 faultsim_save_and_close | |
238 | |
239 do_faultsim_test 6.1 -faults oom* -prep { | |
240 faultsim_restore_and_reopen | |
241 } -body { | |
242 execsql { INSERT INTO x1 VALUES('d e f') } | |
243 } -test { | |
244 faultsim_test_result [list 0 {}] | |
245 if {$testrc==0} { | |
246 set nCnt [db one {SELECT count(*) FROM x1_data}] | |
247 if {$nCnt!=3} { error "expected 3 entries but there are $nCnt" } | |
248 } | |
249 } | |
250 | |
251 do_faultsim_test 6.2 -faults oom* -prep { | |
252 faultsim_restore_and_reopen | |
253 } -body { | |
254 execsql { INSERT INTO x1(x1, rank) VALUES('pgsz', 32) } | |
255 } -test { | |
256 faultsim_test_result [list 0 {}] | |
257 } | |
258 | |
259 do_faultsim_test 6.3 -faults oom-* -prep { | |
260 faultsim_restore_and_reopen | |
261 } -body { | |
262 execsql { INSERT INTO x1(x1) VALUES('integrity-check') } | |
263 } -test { | |
264 faultsim_test_result [list 0 {}] | |
265 } | |
266 | |
267 do_faultsim_test 6.4 -faults oom-* -prep { | |
268 faultsim_restore_and_reopen | |
269 } -body { | |
270 execsql { INSERT INTO x1(x1) VALUES('optimize') } | |
271 } -test { | |
272 faultsim_test_result [list 0 {}] | |
273 } | |
274 | |
275 #------------------------------------------------------------------------- | |
276 # | |
277 do_faultsim_test 7.0 -faults oom* -prep { | |
278 catch { db close } | |
279 } -body { | |
280 sqlite3 db test.db | |
281 } -test { | |
282 faultsim_test_result [list 0 {}] {1 {}} {1 {initialization of fts5 failed: }} | |
283 } | |
284 | |
285 #------------------------------------------------------------------------- | |
286 # A prefix query against a large document set. | |
287 # | |
288 proc rnddoc {n} { | |
289 set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] | |
290 set doc [list] | |
291 for {set i 0} {$i < $n} {incr i} { | |
292 lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]" | |
293 } | |
294 set doc | |
295 } | |
296 | |
297 reset_db | |
298 db func rnddoc rnddoc | |
299 | |
300 do_test 8.0 { | |
301 execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) } | |
302 set ::res [list] | |
303 for {set i 1} {$i<100} {incr i 1} { | |
304 execsql { INSERT INTO x1 VALUES( rnddoc(50) ) } | |
305 lappend ::res $i | |
306 } | |
307 } {} | |
308 | |
309 do_faultsim_test 8.1 -faults oom* -prep { | |
310 } -body { | |
311 execsql { | |
312 SELECT rowid FROM x1 WHERE x1 MATCH 'x*' | |
313 } | |
314 } -test { | |
315 faultsim_test_result [list 0 $::res] | |
316 } | |
317 | |
318 #------------------------------------------------------------------------- | |
319 # Segment promotion. | |
320 # | |
321 do_test 9.0 { | |
322 reset_db | |
323 db func rnddoc fts5_rnddoc | |
324 execsql { | |
325 CREATE VIRTUAL TABLE s2 USING fts5(x); | |
326 INSERT INTO s2(s2, rank) VALUES('pgsz', 32); | |
327 INSERT INTO s2(s2, rank) VALUES('automerge', 0); | |
328 } | |
329 | |
330 for {set i 1} {$i <= 16} {incr i} { | |
331 execsql { INSERT INTO s2 VALUES(rnddoc(5)) } | |
332 } | |
333 fts5_level_segs s2 | |
334 } {0 1} | |
335 set insert_doc [db one {SELECT rnddoc(160)}] | |
336 faultsim_save_and_close | |
337 | |
338 do_faultsim_test 9.1 -faults oom-* -prep { | |
339 faultsim_restore_and_reopen | |
340 } -body { | |
341 execsql { INSERT INTO s2 VALUES($::insert_doc) } | |
342 } -test { | |
343 faultsim_test_result {0 {}} | |
344 if {$testrc==0} { | |
345 set ls [fts5_level_segs s2] | |
346 if {$ls != "2 0"} { error "fts5_level_segs says {$ls}" } | |
347 } | |
348 } | |
349 | |
350 | |
351 | |
352 finish_test | |
353 | |
OLD | NEW |