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 |