| # 2014 June 17 |
| # |
| # The author disclaims copyright to this source code. In place of |
| # a legal notice, here is a blessing: |
| # |
| # May you do good and not evil. |
| # May you find forgiveness for yourself and forgive others. |
| # May you share freely, never taking more than you give. |
| # |
| #************************************************************************* |
| # This file implements regression tests for SQLite library. The |
| # focus of this script is testing the FTS5 module. |
| # |
| |
| source [file join [file dirname [info script]] fts5_common.tcl] |
| source $testdir/malloc_common.tcl |
| set testprefix fts5fault1 |
| |
| # If SQLITE_ENABLE_FTS3 is defined, omit this file. |
| ifcapable !fts5 { |
| finish_test |
| return |
| } |
| |
| # Simple tests: |
| # |
| # 1: CREATE VIRTUAL TABLE |
| # 2: INSERT statement |
| # 3: DELETE statement |
| # 4: MATCH expressions |
| # |
| # |
| |
| faultsim_save_and_close |
| do_faultsim_test 1 -faults ioerr-t* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3') } |
| } -test { |
| faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} |
| } |
| |
| reset_db |
| do_execsql_test 2.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3'); |
| } |
| faultsim_save_and_close |
| do_faultsim_test 2 -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { |
| INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); |
| } |
| } -test { |
| faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} |
| } |
| |
| reset_db |
| do_execsql_test 3.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3'); |
| INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); |
| } |
| faultsim_save_and_close |
| do_faultsim_test 3 -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { DELETE FROM t1 } |
| } -test { |
| faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} |
| } |
| |
| reset_db |
| do_execsql_test 4.0 { |
| CREATE VIRTUAL TABLE t2 USING fts5(a, b); |
| INSERT INTO t2 VALUES('m f a jj th q gi ar', 'hj n h h sg j i m'); |
| INSERT INTO t2 VALUES('nr s t g od j kf h', 'sb h aq rg op rb n nl'); |
| INSERT INTO t2 VALUES('do h h pb p p q fr', 'c rj qs or cr a l i'); |
| INSERT INTO t2 VALUES('lk gp t i lq mq qm p', 'h mr g f op ld aj h'); |
| INSERT INTO t2 VALUES('ct d sq kc qi k f j', 'sn gh c of g s qt q'); |
| INSERT INTO t2 VALUES('d ea d d om mp s ab', 'dm hg l df cm ft pa c'); |
| INSERT INTO t2 VALUES('tc dk c jn n t sr ge', 'a a kn bc n i af h'); |
| INSERT INTO t2 VALUES('ie ii d i b sa qo rf', 'a h m aq i b m fn'); |
| INSERT INTO t2 VALUES('gs r fo a er m h li', 'tm c p gl eb ml q r'); |
| INSERT INTO t2 VALUES('k fe fd rd a gi ho kk', 'ng m c r d ml rm r'); |
| } |
| faultsim_save_and_close |
| |
| foreach {tn expr res} { |
| 1 { dk } 7 |
| 2 { m f } 1 |
| 3 { f* } {1 3 4 5 6 8 9 10} |
| 4 { m OR f } {1 4 5 8 9 10} |
| 5 { sn + gh } {5} |
| 6 { "sn gh" } {5} |
| 7 { NEAR(r a, 5) } {9} |
| 8 { m* f* } {1 4 6 8 9 10} |
| 9 { m* + f* } {1 8} |
| 10 { c NOT p } {5 6 7 10} |
| } { |
| do_faultsim_test 4.$tn -prep { |
| faultsim_restore_and_reopen |
| } -body " |
| execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' } |
| " -test " |
| faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}} |
| " |
| } |
| |
| |
| #------------------------------------------------------------------------- |
| # The following tests use a larger database populated with random data. |
| # |
| # The database page size is set to 512 bytes and the FTS5 page size left |
| # at the default 1000 bytes. This means that reading a node may require |
| # pulling an overflow page from disk, which is an extra opportunity for |
| # an error to occur. |
| # |
| reset_db |
| do_execsql_test 5.0.1 { |
| PRAGMA main.page_size = 512; |
| CREATE VIRTUAL TABLE x1 USING fts5(a, b); |
| PRAGMA main.page_size; |
| } {512} |
| |
| proc rnddoc {n} { |
| set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] |
| set doc [list] |
| for {set i 0} {$i < $n} {incr i} { |
| lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]] |
| } |
| set doc |
| } |
| db func rnddoc rnddoc |
| |
| do_execsql_test 5.0.2 { |
| WITH r(a, b) AS ( |
| SELECT rnddoc(6), rnddoc(6) UNION ALL |
| SELECT rnddoc(6), rnddoc(6) FROM r |
| ) |
| INSERT INTO x1 SELECT * FROM r LIMIT 10000; |
| } |
| |
| set res [db one { |
| SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'} |
| ] |
| |
| do_faultsim_test 5.1 -faults oom* -body { |
| execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abc' } |
| } -test { |
| faultsim_test_result [list 0 $::res] |
| } |
| do_faultsim_test 5.2 -faults oom* -body { |
| execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abcd' } |
| } -test { |
| faultsim_test_result [list 0 0] |
| } |
| |
| proc test_astar {a b} { |
| return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }] |
| } |
| db func test_astar test_astar |
| |
| set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ] |
| do_faultsim_test 5.3 -faults oom* -body { |
| execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'a*' } |
| } -test { |
| faultsim_test_result [list 0 $::res] |
| } |
| |
| do_faultsim_test 5.4 -faults oom* -prep { |
| db close |
| sqlite3 db test.db |
| } -body { |
| execsql { INSERT INTO x1 VALUES('a b c d', 'e f g h') } |
| } -test { |
| faultsim_test_result [list 0 {}] |
| } |
| |
| do_faultsim_test 5.5.1 -faults oom* -body { |
| execsql { |
| SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1 |
| } |
| } -test { |
| faultsim_test_result [list 0 1] |
| } |
| do_faultsim_test 5.5.2 -faults oom* -body { |
| execsql { |
| SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10 |
| } |
| } -test { |
| faultsim_test_result [list 0 1] |
| } |
| do_faultsim_test 5.5.3 -faults oom* -body { |
| execsql { |
| SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( |
| SELECT min(rowid) FROM x1_data WHERE rowid>20 |
| ) |
| } |
| } -test { |
| faultsim_test_result [list 0 1] |
| } |
| do_faultsim_test 5.5.4 -faults oom* -body { |
| execsql { |
| SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( |
| SELECT max(rowid) FROM x1_data |
| ) |
| } |
| } -test { |
| faultsim_test_result [list 0 1] |
| } |
| |
| #------------------------------------------------------------------------- |
| # |
| reset_db |
| do_execsql_test 6.0 { |
| CREATE VIRTUAL TABLE x1 USING fts5(x); |
| INSERT INTO x1(x1, rank) VALUES('automerge', 0); |
| |
| INSERT INTO x1 VALUES('a b c'); -- 1 |
| INSERT INTO x1 VALUES('a b c'); -- 2 |
| INSERT INTO x1 VALUES('a b c'); -- 3 |
| INSERT INTO x1 VALUES('a b c'); -- 4 |
| INSERT INTO x1 VALUES('a b c'); -- 5 |
| INSERT INTO x1 VALUES('a b c'); -- 6 |
| INSERT INTO x1 VALUES('a b c'); -- 7 |
| INSERT INTO x1 VALUES('a b c'); -- 8 |
| INSERT INTO x1 VALUES('a b c'); -- 9 |
| INSERT INTO x1 VALUES('a b c'); -- 10 |
| INSERT INTO x1 VALUES('a b c'); -- 11 |
| INSERT INTO x1 VALUES('a b c'); -- 12 |
| INSERT INTO x1 VALUES('a b c'); -- 13 |
| INSERT INTO x1 VALUES('a b c'); -- 14 |
| INSERT INTO x1 VALUES('a b c'); -- 15 |
| |
| SELECT count(*) FROM x1_data; |
| } {17} |
| |
| faultsim_save_and_close |
| |
| do_faultsim_test 6.1 -faults oom* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { INSERT INTO x1 VALUES('d e f') } |
| } -test { |
| faultsim_test_result [list 0 {}] |
| if {$testrc==0} { |
| set nCnt [db one {SELECT count(*) FROM x1_data}] |
| if {$nCnt!=3} { error "expected 3 entries but there are $nCnt" } |
| } |
| } |
| |
| do_faultsim_test 6.2 -faults oom* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { INSERT INTO x1(x1, rank) VALUES('pgsz', 32) } |
| } -test { |
| faultsim_test_result [list 0 {}] |
| } |
| |
| do_faultsim_test 6.3 -faults oom-* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { INSERT INTO x1(x1) VALUES('integrity-check') } |
| } -test { |
| faultsim_test_result [list 0 {}] |
| } |
| |
| do_faultsim_test 6.4 -faults oom-* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { INSERT INTO x1(x1) VALUES('optimize') } |
| } -test { |
| faultsim_test_result [list 0 {}] |
| } |
| |
| #------------------------------------------------------------------------- |
| # |
| do_faultsim_test 7.0 -faults oom* -prep { |
| catch { db close } |
| } -body { |
| sqlite3 db test.db |
| } -test { |
| faultsim_test_result [list 0 {}] {1 {}} {1 {initialization of fts5 failed: }} |
| } |
| |
| #------------------------------------------------------------------------- |
| # A prefix query against a large document set. |
| # |
| proc rnddoc {n} { |
| set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] |
| set doc [list] |
| for {set i 0} {$i < $n} {incr i} { |
| lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]" |
| } |
| set doc |
| } |
| |
| reset_db |
| db func rnddoc rnddoc |
| |
| do_test 8.0 { |
| execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) } |
| set ::res [list] |
| for {set i 1} {$i<100} {incr i 1} { |
| execsql { INSERT INTO x1 VALUES( rnddoc(50) ) } |
| lappend ::res $i |
| } |
| } {} |
| |
| do_faultsim_test 8.1 -faults oom* -prep { |
| } -body { |
| execsql { |
| SELECT rowid FROM x1 WHERE x1 MATCH 'x*' |
| } |
| } -test { |
| faultsim_test_result [list 0 $::res] |
| } |
| |
| #------------------------------------------------------------------------- |
| # Segment promotion. |
| # |
| do_test 9.0 { |
| reset_db |
| db func rnddoc fts5_rnddoc |
| execsql { |
| CREATE VIRTUAL TABLE s2 USING fts5(x); |
| INSERT INTO s2(s2, rank) VALUES('pgsz', 32); |
| INSERT INTO s2(s2, rank) VALUES('automerge', 0); |
| } |
| |
| for {set i 1} {$i <= 16} {incr i} { |
| execsql { INSERT INTO s2 VALUES(rnddoc(5)) } |
| } |
| fts5_level_segs s2 |
| } {0 1} |
| set insert_doc [db one {SELECT rnddoc(160)}] |
| faultsim_save_and_close |
| |
| do_faultsim_test 9.1 -faults oom-* -prep { |
| faultsim_restore_and_reopen |
| } -body { |
| execsql { INSERT INTO s2 VALUES($::insert_doc) } |
| } -test { |
| faultsim_test_result {0 {}} |
| if {$testrc==0} { |
| set ls [fts5_level_segs s2] |
| if {$ls != "2 0"} { error "fts5_level_segs says {$ls}" } |
| } |
| } |
| |
| |
| |
| finish_test |