fts5fault1.test 9.2 KB

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