pagerfault.test 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548
  1. # 2010 June 15
  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. #
  12. set testdir [file dirname $argv0]
  13. source $testdir/tester.tcl
  14. source $testdir/lock_common.tcl
  15. source $testdir/malloc_common.tcl
  16. if {[permutation] == "inmemory_journal"} {
  17. finish_test
  18. return
  19. }
  20. if {$::tcl_platform(platform)=="windows"} {
  21. finish_test
  22. return
  23. }
  24. set a_string_counter 1
  25. proc a_string {n} {
  26. global a_string_counter
  27. incr a_string_counter
  28. string range [string repeat "${a_string_counter}." $n] 1 $n
  29. }
  30. db func a_string a_string
  31. #-------------------------------------------------------------------------
  32. # Test fault-injection while rolling back a hot-journal file.
  33. #
  34. do_test pagerfault-1-pre1 {
  35. execsql {
  36. PRAGMA journal_mode = DELETE;
  37. PRAGMA cache_size = 10;
  38. CREATE TABLE t1(a UNIQUE, b UNIQUE);
  39. INSERT INTO t1 VALUES(a_string(200), a_string(300));
  40. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  41. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  42. BEGIN;
  43. INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
  44. INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
  45. INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
  46. INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
  47. }
  48. faultsim_save_and_close
  49. } {}
  50. do_faultsim_test pagerfault-1 -prep {
  51. faultsim_restore_and_reopen
  52. } -body {
  53. execsql { SELECT count(*) FROM t1 }
  54. } -test {
  55. faultsim_test_result {0 4}
  56. faultsim_integrity_check
  57. if {[db one { SELECT count(*) FROM t1 }] != 4} {
  58. error "Database content appears incorrect"
  59. }
  60. }
  61. #-------------------------------------------------------------------------
  62. # Test fault-injection while rolling back a hot-journal file with a
  63. # page-size different from the current value stored on page 1 of the
  64. # database file.
  65. #
  66. do_test pagerfault-2-pre1 {
  67. testvfs tv -default 1
  68. tv filter xSync
  69. tv script xSyncCb
  70. proc xSyncCb {filename args} {
  71. if {[string match *journal filename]==0} faultsim_save
  72. }
  73. faultsim_delete_and_reopen
  74. execsql {
  75. PRAGMA page_size = 4096;
  76. BEGIN;
  77. CREATE TABLE abc(a, b, c);
  78. INSERT INTO abc VALUES('o', 't', 't');
  79. INSERT INTO abc VALUES('f', 'f', 's');
  80. INSERT INTO abc SELECT * FROM abc; -- 4
  81. INSERT INTO abc SELECT * FROM abc; -- 8
  82. INSERT INTO abc SELECT * FROM abc; -- 16
  83. INSERT INTO abc SELECT * FROM abc; -- 32
  84. INSERT INTO abc SELECT * FROM abc; -- 64
  85. INSERT INTO abc SELECT * FROM abc; -- 128
  86. INSERT INTO abc SELECT * FROM abc; -- 256
  87. COMMIT;
  88. PRAGMA page_size = 1024;
  89. VACUUM;
  90. }
  91. db close
  92. tv delete
  93. } {}
  94. do_faultsim_test pagerfault-2 -prep {
  95. faultsim_restore_and_reopen
  96. } -body {
  97. execsql { SELECT * FROM abc }
  98. } -test {
  99. set answer [split [string repeat "ottffs" 128] ""]
  100. faultsim_test_result [list 0 $answer]
  101. faultsim_integrity_check
  102. set res [db eval { SELECT * FROM abc }]
  103. if {$res != $answer} { error "Database content appears incorrect ($res)" }
  104. }
  105. #-------------------------------------------------------------------------
  106. # Test fault-injection while rolling back hot-journals that were created
  107. # as part of a multi-file transaction.
  108. #
  109. do_test pagerfault-3-pre1 {
  110. testvfs tstvfs -default 1
  111. tstvfs filter xDelete
  112. tstvfs script xDeleteCallback
  113. proc xDeleteCallback {method file args} {
  114. set file [file tail $file]
  115. if { [string match *mj* $file] } { faultsim_save }
  116. }
  117. faultsim_delete_and_reopen
  118. db func a_string a_string
  119. execsql {
  120. ATTACH 'test.db2' AS aux;
  121. PRAGMA journal_mode = DELETE;
  122. PRAGMA main.cache_size = 10;
  123. PRAGMA aux.cache_size = 10;
  124. CREATE TABLE t1(a UNIQUE, b UNIQUE);
  125. CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
  126. INSERT INTO t1 VALUES(a_string(200), a_string(300));
  127. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  128. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  129. INSERT INTO t2 SELECT * FROM t1;
  130. BEGIN;
  131. INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
  132. INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
  133. INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
  134. INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
  135. REPLACE INTO t2 SELECT * FROM t1;
  136. COMMIT;
  137. }
  138. db close
  139. tstvfs delete
  140. } {}
  141. do_faultsim_test pagerfault-3 -prep {
  142. faultsim_restore_and_reopen
  143. } -body {
  144. execsql {
  145. ATTACH 'test.db2' AS aux;
  146. SELECT count(*) FROM t2;
  147. SELECT count(*) FROM t1;
  148. }
  149. } -test {
  150. faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}}
  151. faultsim_integrity_check
  152. catchsql { ATTACH 'test.db2' AS aux }
  153. if {[db one { SELECT count(*) FROM t1 }] != 4
  154. || [db one { SELECT count(*) FROM t2 }] != 4
  155. } {
  156. error "Database content appears incorrect"
  157. }
  158. }
  159. #-------------------------------------------------------------------------
  160. # Test fault-injection as part of a vanilla, no-transaction, INSERT
  161. # statement.
  162. #
  163. do_faultsim_test pagerfault-4 -prep {
  164. faultsim_delete_and_reopen
  165. } -body {
  166. execsql {
  167. CREATE TABLE x(y);
  168. INSERT INTO x VALUES('z');
  169. SELECT * FROM x;
  170. }
  171. } -test {
  172. faultsim_test_result {0 z}
  173. faultsim_integrity_check
  174. }
  175. #-------------------------------------------------------------------------
  176. # Test fault-injection as part of a commit when using journal_mode=PERSIST.
  177. # Three different cases:
  178. #
  179. # pagerfault-5.1: With no journal_size_limit configured.
  180. # pagerfault-5.2: With a journal_size_limit configured.
  181. # pagerfault-5.4: Multi-file transaction. One connection has a
  182. # journal_size_limit of 0, the other has no limit.
  183. #
  184. do_test pagerfault-5-pre1 {
  185. faultsim_delete_and_reopen
  186. db func a_string a_string
  187. execsql {
  188. CREATE TABLE t1(a UNIQUE, b UNIQUE);
  189. INSERT INTO t1 VALUES(a_string(200), a_string(300));
  190. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  191. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  192. }
  193. faultsim_save_and_close
  194. } {}
  195. do_faultsim_test pagerfault-5.1 -prep {
  196. faultsim_restore_and_reopen
  197. db func a_string a_string
  198. execsql { PRAGMA journal_mode = PERSIST }
  199. } -body {
  200. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  201. } -test {
  202. faultsim_test_result {0 {}}
  203. faultsim_integrity_check
  204. }
  205. do_faultsim_test pagerfault-5.2 -prep {
  206. faultsim_restore_and_reopen
  207. db func a_string a_string
  208. execsql {
  209. PRAGMA journal_mode = PERSIST;
  210. PRAGMA journal_size_limit = 2048;
  211. }
  212. } -body {
  213. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  214. } -test {
  215. faultsim_test_result {0 {}}
  216. faultsim_integrity_check
  217. }
  218. do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
  219. faultsim_restore_and_reopen
  220. db func a_string a_string
  221. forcedelete test2.db test2.db-journal test2.db-wal
  222. execsql {
  223. PRAGMA journal_mode = PERSIST;
  224. ATTACH 'test2.db' AS aux;
  225. PRAGMA aux.journal_mode = PERSIST;
  226. PRAGMA aux.journal_size_limit = 0;
  227. }
  228. } -body {
  229. execsql {
  230. BEGIN;
  231. INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
  232. CREATE TABLE aux.t2 AS SELECT * FROM t1;
  233. COMMIT;
  234. }
  235. } -test {
  236. faultsim_test_result {0 {}}
  237. catchsql { COMMIT }
  238. catchsql { ROLLBACK }
  239. faultsim_integrity_check
  240. set res ""
  241. set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
  242. if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
  243. }
  244. #-------------------------------------------------------------------------
  245. # Test fault-injection as part of a commit when using
  246. # journal_mode=TRUNCATE.
  247. #
  248. do_test pagerfault-6-pre1 {
  249. faultsim_delete_and_reopen
  250. db func a_string a_string
  251. execsql {
  252. CREATE TABLE t1(a UNIQUE, b UNIQUE);
  253. INSERT INTO t1 VALUES(a_string(200), a_string(300));
  254. }
  255. faultsim_save_and_close
  256. } {}
  257. do_faultsim_test pagerfault-6.1 -prep {
  258. faultsim_restore_and_reopen
  259. db func a_string a_string
  260. execsql { PRAGMA journal_mode = TRUNCATE }
  261. } -body {
  262. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  263. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  264. } -test {
  265. faultsim_test_result {0 {}}
  266. faultsim_integrity_check
  267. }
  268. # The unix vfs xAccess() method considers a file zero bytes in size to
  269. # "not exist". This proc overrides that behaviour so that a zero length
  270. # file is considered to exist.
  271. #
  272. proc xAccess {method filename op args} {
  273. if {$op != "SQLITE_ACCESS_EXISTS"} { return "" }
  274. return [file exists $filename]
  275. }
  276. do_faultsim_test pagerfault-6.2 -faults cantopen-* -prep {
  277. shmfault filter xAccess
  278. shmfault script xAccess
  279. faultsim_restore_and_reopen
  280. db func a_string a_string
  281. execsql { PRAGMA journal_mode = TRUNCATE }
  282. } -body {
  283. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  284. execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  285. } -test {
  286. faultsim_test_result {0 {}}
  287. faultsim_integrity_check
  288. }
  289. # The following was an attempt to get a bitvec malloc to fail. Didn't work.
  290. #
  291. # do_test pagerfault-6-pre1 {
  292. # faultsim_delete_and_reopen
  293. # execsql {
  294. # CREATE TABLE t1(x, y, UNIQUE(x, y));
  295. # INSERT INTO t1 VALUES(1, randomblob(1501));
  296. # INSERT INTO t1 VALUES(2, randomblob(1502));
  297. # INSERT INTO t1 VALUES(3, randomblob(1503));
  298. # INSERT INTO t1 VALUES(4, randomblob(1504));
  299. # INSERT INTO t1
  300. # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
  301. # INSERT INTO t1
  302. # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
  303. # INSERT INTO t1
  304. # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
  305. # INSERT INTO t1
  306. # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
  307. # }
  308. # faultsim_save_and_close
  309. # } {}
  310. # do_faultsim_test pagerfault-6 -prep {
  311. # faultsim_restore_and_reopen
  312. # } -body {
  313. # execsql {
  314. # BEGIN;
  315. # UPDATE t1 SET x=x+4 WHERE x=1;
  316. # SAVEPOINT one;
  317. # UPDATE t1 SET x=x+4 WHERE x=2;
  318. # SAVEPOINT three;
  319. # UPDATE t1 SET x=x+4 WHERE x=3;
  320. # SAVEPOINT four;
  321. # UPDATE t1 SET x=x+4 WHERE x=4;
  322. # RELEASE three;
  323. # COMMIT;
  324. # SELECT DISTINCT x FROM t1;
  325. # }
  326. # } -test {
  327. # faultsim_test_result {0 {5 6 7 8}}
  328. # faultsim_integrity_check
  329. # }
  330. #
  331. # This is designed to provoke a special case in the pager code:
  332. #
  333. # If an error (specifically, a FULL or IOERR error) occurs while writing a
  334. # dirty page to the file-system in order to free up memory, the pager enters
  335. # the "error state". An IO error causes SQLite to roll back the current
  336. # transaction (exiting the error state). A FULL error, however, may only
  337. # rollback the current statement.
  338. #
  339. # This block tests that nothing goes wrong if a FULL error occurs while
  340. # writing a dirty page out to free memory from within a statement that has
  341. # opened a statement transaction.
  342. #
  343. do_test pagerfault-7-pre1 {
  344. faultsim_delete_and_reopen
  345. execsql {
  346. CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
  347. BEGIN;
  348. INSERT INTO t2 VALUES(NULL, randomblob(1500));
  349. INSERT INTO t2 VALUES(NULL, randomblob(1500));
  350. INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 4
  351. INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 8
  352. INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 16
  353. INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 32
  354. INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 64
  355. COMMIT;
  356. CREATE TABLE t1(a PRIMARY KEY, b);
  357. INSERT INTO t1 SELECT * FROM t2;
  358. DROP TABLE t2;
  359. }
  360. faultsim_save_and_close
  361. } {}
  362. do_faultsim_test pagerfault-7 -prep {
  363. faultsim_restore_and_reopen
  364. execsql {
  365. PRAGMA cache_size = 10;
  366. BEGIN;
  367. UPDATE t1 SET b = randomblob(1500);
  368. }
  369. } -body {
  370. execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }
  371. execsql COMMIT
  372. } -test {
  373. faultsim_test_result {0 {}}
  374. faultsim_integrity_check
  375. }
  376. do_test pagerfault-8-pre1 {
  377. faultsim_delete_and_reopen
  378. execsql {
  379. PRAGMA auto_vacuum = 1;
  380. CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  381. BEGIN;
  382. INSERT INTO t1 VALUES(NULL, randomblob(1500));
  383. INSERT INTO t1 VALUES(NULL, randomblob(1500));
  384. INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 4
  385. INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 8
  386. INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 16
  387. INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 32
  388. INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 64
  389. COMMIT;
  390. }
  391. faultsim_save_and_close
  392. set filesize [file size test.db]
  393. set {} {}
  394. } {}
  395. do_test pagerfault-8-pre2 {
  396. faultsim_restore_and_reopen
  397. execsql { DELETE FROM t1 WHERE a>32 }
  398. expr {[file size test.db] < $filesize}
  399. } {1}
  400. do_faultsim_test pagerfault-8 -prep {
  401. faultsim_restore_and_reopen
  402. execsql {
  403. BEGIN;
  404. DELETE FROM t1 WHERE a>32;
  405. }
  406. } -body {
  407. execsql COMMIT
  408. } -test {
  409. faultsim_test_result {0 {}}
  410. faultsim_integrity_check
  411. }
  412. #-------------------------------------------------------------------------
  413. # This test case is specially designed so that during a savepoint
  414. # rollback, a new cache entry must be allocated (see comments surrounding
  415. # the call to sqlite3PagerAcquire() from within pager_playback_one_page()
  416. # for details). Test the effects of injecting an OOM at this point.
  417. #
  418. do_test pagerfault-9-pre1 {
  419. faultsim_delete_and_reopen
  420. execsql {
  421. PRAGMA auto_vacuum = incremental;
  422. CREATE TABLE t1(x);
  423. CREATE TABLE t2(y);
  424. CREATE TABLE t3(z);
  425. INSERT INTO t1 VALUES(randomblob(900));
  426. INSERT INTO t1 VALUES(randomblob(900));
  427. DELETE FROM t1;
  428. }
  429. faultsim_save_and_close
  430. } {}
  431. do_faultsim_test pagerfault-9.1 -prep {
  432. faultsim_restore_and_reopen
  433. execsql {
  434. BEGIN;
  435. INSERT INTO t1 VALUES(randomblob(900));
  436. INSERT INTO t1 VALUES(randomblob(900));
  437. DROP TABLE t3;
  438. DROP TABLE t2;
  439. SAVEPOINT abc;
  440. PRAGMA incremental_vacuum;
  441. }
  442. } -body {
  443. execsql {
  444. ROLLBACK TO abc;
  445. COMMIT;
  446. PRAGMA freelist_count
  447. }
  448. } -test {
  449. faultsim_test_result {0 2}
  450. faultsim_integrity_check
  451. set sl [db one { SELECT COALESCE(sum(length(x)), 'null') FROM t1 }]
  452. if {$sl!="null" && $sl!=1800} {
  453. error "Content looks no good... ($sl)"
  454. }
  455. }
  456. #-------------------------------------------------------------------------
  457. # Test fault injection with a temporary database file.
  458. #
  459. foreach v {a b} {
  460. do_faultsim_test pagerfault-10$v -prep {
  461. sqlite3 db ""
  462. db func a_string a_string;
  463. execsql {
  464. PRAGMA cache_size = 10;
  465. BEGIN;
  466. CREATE TABLE xx(a, b, UNIQUE(a, b));
  467. INSERT INTO xx VALUES(a_string(200), a_string(200));
  468. INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
  469. INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
  470. INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
  471. INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
  472. COMMIT;
  473. }
  474. } -body {
  475. execsql { UPDATE xx SET a = a_string(300) }
  476. } -test {
  477. faultsim_test_result {0 {}}
  478. if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } }
  479. faultsim_integrity_check
  480. faultsim_integrity_check
  481. }
  482. }
  483. #-------------------------------------------------------------------------
  484. # Test fault injection with transaction savepoints (savepoints created
  485. # when a SAVEPOINT command is executed outside of any other savepoint
  486. # or transaction context).
  487. #
  488. do_test pagerfault-9-pre1 {
  489. faultsim_delete_and_reopen
  490. db func a_string a_string;
  491. execsql {
  492. PRAGMA auto_vacuum = on;
  493. CREATE TABLE t1(x UNIQUE);
  494. CREATE TABLE t2(y UNIQUE);
  495. CREATE TABLE t3(z UNIQUE);
  496. BEGIN;
  497. INSERT INTO t1 VALUES(a_string(202));
  498. INSERT INTO t2 VALUES(a_string(203));
  499. INSERT INTO t3 VALUES(a_string(204));
  500. INSERT INTO t1 SELECT a_string(202) FROM t1;
  501. INSERT INTO t1 SELECT a_string(203) FROM t1;
  502. INSERT INTO t1 SELECT a_string(204) FROM t1;
  503. INSERT INTO t1 SELECT a_string(205) FROM t1;
  504. INSERT INTO t2 SELECT a_string(length(x)) FROM t1;
  505. INSERT INTO t3 SELECT a_string(length(x)) FROM t1;
  506. COMMIT;
  507. }
  508. faultsim_save_and_close
  509. } {}
  510. do_faultsim_test pagerfault-11 -prep {
  511. faultsim_restore_and_reopen
  512. execsql { PRAGMA cache_size = 10 }
  513. } -body {
  514. execsql {
  515. SAVEPOINT trans;
  516. UPDATE t2 SET y = y||'2';
  517. INSERT INTO t3 SELECT * FROM t2;
  518. DELETE FROM t1;
  519. ROLLBACK TO trans;
  520. UPDATE t1 SET x = x||'3';
  521. INSERT INTO t2 SELECT * FROM t1;
  522. DELETE FROM t3;
  523. RELEASE trans;
  524. }
  525. } -test {
  526. faultsim_test_result {0 {}}
  527. faultsim_integrity_check
  528. }
  529. #-------------------------------------------------------------------------
  530. # Test fault injection when writing to a database file that resides on
  531. # a file-system with a sector-size larger than the database page-size.
  532. #
  533. do_test pagerfault-12-pre1 {
  534. testvfs ss_layer -default 1
  535. ss_layer sectorsize 4096
  536. faultsim_delete_and_reopen
  537. db func a_string a_string;
  538. execsql {
  539. PRAGMA page_size = 1024;
  540. PRAGMA journal_mode = PERSIST;
  541. PRAGMA cache_size = 10;
  542. BEGIN;
  543. CREATE TABLE t1(x, y UNIQUE);
  544. INSERT INTO t1 VALUES(a_string(333), a_string(444));
  545. INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
  546. INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
  547. INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
  548. INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
  549. INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13;
  550. COMMIT;
  551. }
  552. faultsim_save_and_close
  553. } {}
  554. do_faultsim_test pagerfault-12a -prep {
  555. faultsim_restore_and_reopen
  556. execsql { PRAGMA cache_size = 10 }
  557. db func a_string a_string;
  558. } -body {
  559. execsql {
  560. UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y));
  561. }
  562. } -test {
  563. faultsim_test_result {0 {}}
  564. faultsim_integrity_check
  565. }
  566. do_test pagerfault-12-pre2 {
  567. faultsim_restore_and_reopen
  568. execsql {
  569. CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 10;
  570. }
  571. faultsim_save_and_close
  572. } {}
  573. do_faultsim_test pagerfault-12b -prep {
  574. faultsim_restore_and_reopen
  575. db func a_string a_string;
  576. execsql { SELECT * FROM t1 }
  577. } -body {
  578. set sql(1) { UPDATE t2 SET x = a_string(280) }
  579. set sql(2) { UPDATE t1 SET x = a_string(280) WHERE rowid = 5 }
  580. db eval { SELECT rowid FROM t1 LIMIT 2 } { db eval $sql($rowid) }
  581. } -test {
  582. faultsim_test_result {0 {}}
  583. faultsim_integrity_check
  584. }
  585. catch { db close }
  586. ss_layer delete
  587. #-------------------------------------------------------------------------
  588. # Test fault injection when SQLite opens a database where the size of the
  589. # database file is zero bytes but the accompanying journal file is larger
  590. # than that. In this scenario SQLite should delete the journal file
  591. # without rolling it back, even if it is in all other respects a valid
  592. # hot-journal file.
  593. #
  594. do_test pagerfault-13-pre1 {
  595. faultsim_delete_and_reopen
  596. db func a_string a_string;
  597. execsql {
  598. PRAGMA journal_mode = PERSIST;
  599. BEGIN;
  600. CREATE TABLE t1(x, y UNIQUE);
  601. INSERT INTO t1 VALUES(a_string(333), a_string(444));
  602. COMMIT;
  603. }
  604. db close
  605. forcedelete test.db
  606. faultsim_save
  607. } {}
  608. do_faultsim_test pagerfault-13 -prep {
  609. faultsim_restore_and_reopen
  610. } -body {
  611. execsql { CREATE TABLE xx(a, b) }
  612. } -test {
  613. faultsim_test_result {0 {}}
  614. }
  615. #---------------------------------------------------------------------------
  616. # Test fault injection into a small backup operation.
  617. #
  618. do_test pagerfault-14-pre1 {
  619. faultsim_delete_and_reopen
  620. db func a_string a_string;
  621. execsql {
  622. PRAGMA journal_mode = PERSIST;
  623. ATTACH 'test.db2' AS two;
  624. BEGIN;
  625. CREATE TABLE t1(x, y UNIQUE);
  626. CREATE TABLE two.t2(x, y UNIQUE);
  627. INSERT INTO t1 VALUES(a_string(333), a_string(444));
  628. INSERT INTO t2 VALUES(a_string(333), a_string(444));
  629. COMMIT;
  630. }
  631. faultsim_save_and_close
  632. } {}
  633. do_faultsim_test pagerfault-14a -prep {
  634. faultsim_restore_and_reopen
  635. } -body {
  636. if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
  637. } -test {
  638. faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
  639. }
  640. # If TEMP_STORE is 2 or greater, then the database [db2] will be created
  641. # as an in-memory database. This test will not work in that case, as it
  642. # is not possible to change the page-size of an in-memory database. Even
  643. # using the backup API.
  644. #
  645. if {$TEMP_STORE<2} {
  646. do_faultsim_test pagerfault-14b -prep {
  647. catch { db2 close }
  648. faultsim_restore_and_reopen
  649. sqlite3 db2 ""
  650. db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
  651. } -body {
  652. sqlite3_backup B db2 main db main
  653. B step 200
  654. set rc [B finish]
  655. if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
  656. if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
  657. set {} {}
  658. } -test {
  659. faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
  660. }
  661. }
  662. do_faultsim_test pagerfault-14c -prep {
  663. catch { db2 close }
  664. faultsim_restore_and_reopen
  665. sqlite3 db2 test.db2
  666. db2 eval {
  667. PRAGMA synchronous = off;
  668. PRAGMA page_size = 4096;
  669. CREATE TABLE xx(a);
  670. }
  671. } -body {
  672. sqlite3_backup B db2 main db main
  673. B step 200
  674. set rc [B finish]
  675. if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
  676. if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
  677. set {} {}
  678. } -test {
  679. faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
  680. }
  681. do_test pagerfault-15-pre1 {
  682. faultsim_delete_and_reopen
  683. db func a_string a_string;
  684. execsql {
  685. BEGIN;
  686. CREATE TABLE t1(x, y UNIQUE);
  687. INSERT INTO t1 VALUES(a_string(11), a_string(22));
  688. INSERT INTO t1 VALUES(a_string(11), a_string(22));
  689. COMMIT;
  690. }
  691. faultsim_save_and_close
  692. } {}
  693. do_faultsim_test pagerfault-15 -prep {
  694. faultsim_restore_and_reopen
  695. db func a_string a_string;
  696. } -body {
  697. db eval { SELECT * FROM t1 LIMIT 1 } {
  698. execsql {
  699. BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
  700. BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
  701. }
  702. }
  703. } -test {
  704. faultsim_test_result {0 {}}
  705. faultsim_integrity_check
  706. }
  707. do_test pagerfault-16-pre1 {
  708. faultsim_delete_and_reopen
  709. execsql { CREATE TABLE t1(x, y UNIQUE) }
  710. faultsim_save_and_close
  711. } {}
  712. do_faultsim_test pagerfault-16 -prep {
  713. faultsim_restore_and_reopen
  714. } -body {
  715. execsql {
  716. PRAGMA locking_mode = exclusive;
  717. PRAGMA journal_mode = wal;
  718. INSERT INTO t1 VALUES(1, 2);
  719. INSERT INTO t1 VALUES(3, 4);
  720. PRAGMA journal_mode = delete;
  721. INSERT INTO t1 VALUES(4, 5);
  722. PRAGMA journal_mode = wal;
  723. INSERT INTO t1 VALUES(6, 7);
  724. PRAGMA journal_mode = persist;
  725. INSERT INTO t1 VALUES(8, 9);
  726. }
  727. } -test {
  728. faultsim_test_result {0 {exclusive wal delete wal persist}}
  729. faultsim_integrity_check
  730. }
  731. #-------------------------------------------------------------------------
  732. # Test fault injection while changing into and out of WAL mode.
  733. #
  734. do_test pagerfault-17-pre1 {
  735. faultsim_delete_and_reopen
  736. execsql {
  737. CREATE TABLE t1(a PRIMARY KEY, b);
  738. INSERT INTO t1 VALUES(1862, 'Botha');
  739. INSERT INTO t1 VALUES(1870, 'Smuts');
  740. INSERT INTO t1 VALUES(1866, 'Hertzog');
  741. }
  742. faultsim_save_and_close
  743. } {}
  744. do_faultsim_test pagerfault-17a -prep {
  745. faultsim_restore_and_reopen
  746. } -body {
  747. execsql {
  748. PRAGMA journal_mode = wal;
  749. PRAGMA journal_mode = delete;
  750. }
  751. } -test {
  752. faultsim_test_result {0 {wal delete}}
  753. faultsim_integrity_check
  754. }
  755. do_faultsim_test pagerfault-17b -prep {
  756. faultsim_restore_and_reopen
  757. execsql { PRAGMA synchronous = OFF }
  758. } -body {
  759. execsql {
  760. PRAGMA journal_mode = wal;
  761. INSERT INTO t1 VALUES(22, 'Clarke');
  762. PRAGMA journal_mode = delete;
  763. }
  764. } -test {
  765. faultsim_test_result {0 {wal delete}}
  766. faultsim_integrity_check
  767. }
  768. do_faultsim_test pagerfault-17c -prep {
  769. faultsim_restore_and_reopen
  770. execsql {
  771. PRAGMA locking_mode = exclusive;
  772. PRAGMA journal_mode = wal;
  773. }
  774. } -body {
  775. execsql { PRAGMA journal_mode = delete }
  776. } -test {
  777. faultsim_test_result {0 delete}
  778. faultsim_integrity_check
  779. }
  780. do_faultsim_test pagerfault-17d -prep {
  781. catch { db2 close }
  782. faultsim_restore_and_reopen
  783. sqlite3 db2 test.db
  784. execsql { PRAGMA journal_mode = delete }
  785. execsql { PRAGMA journal_mode = wal }
  786. execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2
  787. } -body {
  788. execsql { PRAGMA journal_mode = delete }
  789. } -test {
  790. faultsim_test_result {1 {database is locked}}
  791. faultsim_integrity_check
  792. }
  793. do_faultsim_test pagerfault-17e -prep {
  794. catch { db2 close }
  795. faultsim_restore_and_reopen
  796. sqlite3 db2 test.db
  797. execsql { PRAGMA journal_mode = delete }
  798. execsql { PRAGMA journal_mode = wal }
  799. set ::chan [launch_testfixture]
  800. testfixture $::chan {
  801. sqlite3 db test.db
  802. db eval { INSERT INTO t1 VALUES(101, 'Latham') }
  803. }
  804. catch { testfixture $::chan sqlite_abort }
  805. catch { close $::chan }
  806. } -body {
  807. execsql { PRAGMA journal_mode = delete }
  808. } -test {
  809. faultsim_test_result {0 delete}
  810. faultsim_integrity_check
  811. }
  812. #-------------------------------------------------------------------------
  813. # Test fault-injection when changing from journal_mode=persist to
  814. # journal_mode=delete (this involves deleting the journal file).
  815. #
  816. do_test pagerfault-18-pre1 {
  817. faultsim_delete_and_reopen
  818. execsql {
  819. CREATE TABLE qq(x);
  820. INSERT INTO qq VALUES('Herbert');
  821. INSERT INTO qq VALUES('Macalister');
  822. INSERT INTO qq VALUES('Mackenzie');
  823. INSERT INTO qq VALUES('Lilley');
  824. INSERT INTO qq VALUES('Palmer');
  825. }
  826. faultsim_save_and_close
  827. } {}
  828. do_faultsim_test pagerfault-18 -prep {
  829. faultsim_restore_and_reopen
  830. execsql {
  831. PRAGMA journal_mode = PERSIST;
  832. INSERT INTO qq VALUES('Beatty');
  833. }
  834. } -body {
  835. execsql { PRAGMA journal_mode = delete }
  836. } -test {
  837. faultsim_test_result {0 delete}
  838. faultsim_integrity_check
  839. }
  840. do_faultsim_test pagerfault-19a -prep {
  841. sqlite3 db :memory:
  842. db func a_string a_string
  843. execsql {
  844. PRAGMA auto_vacuum = FULL;
  845. BEGIN;
  846. CREATE TABLE t1(a, b);
  847. INSERT INTO t1 VALUES(a_string(5000), a_string(6000));
  848. COMMIT;
  849. }
  850. } -body {
  851. execsql {
  852. CREATE TABLE t2(a, b);
  853. INSERT INTO t2 SELECT * FROM t1;
  854. DELETE FROM t1;
  855. }
  856. } -test {
  857. faultsim_test_result {0 {}}
  858. }
  859. do_test pagerfault-19-pre1 {
  860. faultsim_delete_and_reopen
  861. execsql {
  862. PRAGMA auto_vacuum = FULL;
  863. CREATE TABLE t1(x); INSERT INTO t1 VALUES(1);
  864. CREATE TABLE t2(x); INSERT INTO t2 VALUES(2);
  865. CREATE TABLE t3(x); INSERT INTO t3 VALUES(3);
  866. CREATE TABLE t4(x); INSERT INTO t4 VALUES(4);
  867. CREATE TABLE t5(x); INSERT INTO t5 VALUES(5);
  868. CREATE TABLE t6(x); INSERT INTO t6 VALUES(6);
  869. }
  870. faultsim_save_and_close
  871. } {}
  872. do_faultsim_test pagerfault-19b -prep {
  873. faultsim_restore_and_reopen
  874. } -body {
  875. execsql {
  876. BEGIN;
  877. UPDATE t4 SET x = x+1;
  878. UPDATE t6 SET x = x+1;
  879. SAVEPOINT one;
  880. UPDATE t3 SET x = x+1;
  881. SAVEPOINT two;
  882. DROP TABLE t2;
  883. ROLLBACK TO one;
  884. COMMIT;
  885. SELECT * FROM t3;
  886. SELECT * FROM t4;
  887. SELECT * FROM t6;
  888. }
  889. } -test {
  890. faultsim_test_result {0 {3 5 7}}
  891. }
  892. #-------------------------------------------------------------------------
  893. # This tests fault-injection in a special case in the auto-vacuum code.
  894. #
  895. do_test pagerfault-20-pre1 {
  896. faultsim_delete_and_reopen
  897. execsql {
  898. PRAGMA cache_size = 10;
  899. PRAGMA auto_vacuum = FULL;
  900. CREATE TABLE t0(a, b);
  901. }
  902. faultsim_save_and_close
  903. } {}
  904. do_faultsim_test pagerfault-20 -prep {
  905. faultsim_restore_and_reopen
  906. } -body {
  907. execsql {
  908. BEGIN;
  909. CREATE TABLE t1(a, b);
  910. CREATE TABLE t2(a, b);
  911. DROP TABLE t1;
  912. COMMIT;
  913. }
  914. } -test {
  915. faultsim_test_result {0 {}}
  916. }
  917. do_test pagerfault-21-pre1 {
  918. faultsim_delete_and_reopen
  919. execsql {
  920. PRAGMA cache_size = 10;
  921. CREATE TABLE t0(a PRIMARY KEY, b);
  922. INSERT INTO t0 VALUES(1, 2);
  923. }
  924. faultsim_save_and_close
  925. } {}
  926. do_faultsim_test pagerfault-21 -prep {
  927. faultsim_restore_and_reopen
  928. } -body {
  929. db eval { SELECT * FROM t0 LIMIT 1 } {
  930. db eval { INSERT INTO t0 SELECT a+1, b FROM t0 }
  931. db eval { INSERT INTO t0 SELECT a+2, b FROM t0 }
  932. }
  933. } -test {
  934. faultsim_test_result {0 {}}
  935. }
  936. #-------------------------------------------------------------------------
  937. # Test fault-injection and rollback when the nReserve header value
  938. # is non-zero.
  939. #
  940. do_test pagerfault-21-pre1 {
  941. faultsim_delete_and_reopen
  942. execsql {
  943. PRAGMA page_size = 1024;
  944. PRAGMA journal_mode = WAL;
  945. PRAGMA journal_mode = DELETE;
  946. }
  947. db close
  948. hexio_write test.db 20 10
  949. hexio_write test.db 105 03F0
  950. sqlite3 db test.db
  951. db func a_string a_string
  952. execsql {
  953. CREATE TABLE t0(a PRIMARY KEY, b UNIQUE);
  954. INSERT INTO t0 VALUES(a_string(222), a_string(333));
  955. INSERT INTO t0 VALUES(a_string(223), a_string(334));
  956. INSERT INTO t0 VALUES(a_string(224), a_string(335));
  957. INSERT INTO t0 VALUES(a_string(225), a_string(336));
  958. }
  959. faultsim_save_and_close
  960. } {}
  961. do_faultsim_test pagerfault-21 -prep {
  962. faultsim_restore_and_reopen
  963. } -body {
  964. execsql { INSERT INTO t0 SELECT a||'x', b||'x' FROM t0 }
  965. } -test {
  966. faultsim_test_result {0 {}}
  967. faultsim_integrity_check
  968. }
  969. ifcapable crashtest {
  970. faultsim_delete_and_reopen
  971. execsql {
  972. PRAGMA page_size = 1024;
  973. PRAGMA journal_mode = WAL;
  974. PRAGMA journal_mode = DELETE;
  975. }
  976. db close
  977. hexio_write test.db 20 10
  978. hexio_write test.db 105 03F0
  979. sqlite3 db test.db
  980. db func a_string a_string
  981. execsql {
  982. CREATE TABLE t0(a PRIMARY KEY, b UNIQUE);
  983. INSERT INTO t0 VALUES(a_string(222), a_string(333));
  984. INSERT INTO t0 VALUES(a_string(223), a_string(334));
  985. }
  986. faultsim_save_and_close
  987. for {set iTest 1} {$iTest<50} {incr iTest} {
  988. do_test pagerfault-21.crash.$iTest.1 {
  989. crashsql -delay 1 -file test.db -seed $iTest {
  990. BEGIN;
  991. CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
  992. INSERT INTO t1 SELECT a, b FROM t0;
  993. COMMIT;
  994. }
  995. } {1 {child process exited abnormally}}
  996. do_test pagerfault-22.$iTest.2 {
  997. sqlite3 db test.db
  998. execsql { PRAGMA integrity_check }
  999. } {ok}
  1000. db close
  1001. }
  1002. }
  1003. #-------------------------------------------------------------------------
  1004. # When a 3.7.0 client opens a write-transaction on a database file that
  1005. # has been appended to or truncated by a pre-370 client, it updates
  1006. # the db-size in the file header immediately. This test case provokes
  1007. # errors during that operation.
  1008. #
  1009. do_test pagerfault-22-pre1 {
  1010. faultsim_delete_and_reopen
  1011. db func a_string a_string
  1012. execsql {
  1013. PRAGMA page_size = 1024;
  1014. PRAGMA auto_vacuum = 0;
  1015. CREATE TABLE t1(a);
  1016. CREATE INDEX i1 ON t1(a);
  1017. INSERT INTO t1 VALUES(a_string(3000));
  1018. CREATE TABLE t2(a);
  1019. INSERT INTO t2 VALUES(1);
  1020. }
  1021. db close
  1022. sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
  1023. faultsim_save_and_close
  1024. } {}
  1025. do_faultsim_test pagerfault-22 -prep {
  1026. faultsim_restore_and_reopen
  1027. } -body {
  1028. execsql { INSERT INTO t2 VALUES(2) }
  1029. execsql { SELECT * FROM t2 }
  1030. } -test {
  1031. faultsim_test_result {0 {1 2}}
  1032. faultsim_integrity_check
  1033. }
  1034. #-------------------------------------------------------------------------
  1035. # Provoke an OOM error during a commit of multi-file transaction. One of
  1036. # the databases written during the transaction is an in-memory database.
  1037. # This test causes rollback of the in-memory database after CommitPhaseOne()
  1038. # has successfully returned. i.e. the series of calls for the aborted commit
  1039. # is:
  1040. #
  1041. # PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK
  1042. # PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR
  1043. # PagerRollback(<in-memory-db>)
  1044. # PagerRollback(<file-db>)
  1045. #
  1046. do_faultsim_test pagerfault-23 -prep {
  1047. sqlite3 db :memory:
  1048. foreach f [glob -nocomplain test.db*] { forcedelete $f }
  1049. db eval {
  1050. ATTACH 'test.db2' AS aux;
  1051. CREATE TABLE t1(a, b);
  1052. CREATE TABLE aux.t2(a, b);
  1053. }
  1054. } -body {
  1055. execsql {
  1056. BEGIN;
  1057. INSERT INTO t1 VALUES(1,2);
  1058. INSERT INTO t2 VALUES(3,4);
  1059. COMMIT;
  1060. }
  1061. } -test {
  1062. faultsim_test_result {0 {}}
  1063. faultsim_integrity_check
  1064. }
  1065. do_faultsim_test pagerfault-24 -prep {
  1066. faultsim_delete_and_reopen
  1067. db eval { PRAGMA temp_store = file }
  1068. execsql { CREATE TABLE x(a, b) }
  1069. } -body {
  1070. execsql { CREATE TEMP TABLE t1(a, b) }
  1071. } -test {
  1072. faultsim_test_result {0 {}} \
  1073. {1 {unable to open a temporary database file for storing temporary tables}}
  1074. set ic [db eval { PRAGMA temp.integrity_check }]
  1075. if {$ic != "ok"} { error "Integrity check: $ic" }
  1076. }
  1077. proc lockrows {n} {
  1078. if {$n==0} { return "" }
  1079. db eval { SELECT * FROM t1 WHERE oid = $n } {
  1080. return [lockrows [expr {$n-1}]]
  1081. }
  1082. }
  1083. do_test pagerfault-25-pre1 {
  1084. faultsim_delete_and_reopen
  1085. db func a_string a_string
  1086. execsql {
  1087. PRAGMA page_size = 1024;
  1088. PRAGMA auto_vacuum = 0;
  1089. CREATE TABLE t1(a);
  1090. INSERT INTO t1 VALUES(a_string(500));
  1091. INSERT INTO t1 SELECT a_string(500) FROM t1;
  1092. INSERT INTO t1 SELECT a_string(500) FROM t1;
  1093. INSERT INTO t1 SELECT a_string(500) FROM t1;
  1094. INSERT INTO t1 SELECT a_string(500) FROM t1;
  1095. INSERT INTO t1 SELECT a_string(500) FROM t1;
  1096. }
  1097. faultsim_save_and_close
  1098. } {}
  1099. do_faultsim_test pagerfault-25 -prep {
  1100. faultsim_restore_and_reopen
  1101. db func a_string a_string
  1102. set ::channel [db incrblob -readonly t1 a 1]
  1103. execsql {
  1104. PRAGMA cache_size = 10;
  1105. BEGIN;
  1106. INSERT INTO t1 VALUES(a_string(3000));
  1107. INSERT INTO t1 VALUES(a_string(3000));
  1108. }
  1109. } -body {
  1110. lockrows 30
  1111. } -test {
  1112. catch { lockrows 30 }
  1113. catch { db eval COMMIT }
  1114. close $::channel
  1115. faultsim_test_result {0 {}}
  1116. }
  1117. do_faultsim_test pagerfault-26 -prep {
  1118. faultsim_delete_and_reopen
  1119. execsql {
  1120. PRAGMA page_size = 1024;
  1121. PRAGMA journal_mode = truncate;
  1122. PRAGMA auto_vacuum = full;
  1123. PRAGMA locking_mode=exclusive;
  1124. CREATE TABLE t1(a, b);
  1125. INSERT INTO t1 VALUES(1, 2);
  1126. PRAGMA page_size = 4096;
  1127. }
  1128. } -body {
  1129. execsql {
  1130. VACUUM;
  1131. }
  1132. } -test {
  1133. faultsim_test_result {0 {}}
  1134. set contents [db eval {SELECT * FROM t1}]
  1135. if {$contents != "1 2"} { error "Bad database contents ($contents)" }
  1136. set sz [file size test.db]
  1137. if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} {
  1138. error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes"
  1139. }
  1140. if {$testrc==0 && $sz!=4096*3} {
  1141. error "Expected file size to be 12288 bytes - actual size $sz bytes"
  1142. }
  1143. }
  1144. do_test pagerfault-27-pre {
  1145. faultsim_delete_and_reopen
  1146. db func a_string a_string
  1147. execsql {
  1148. PRAGMA page_size = 1024;
  1149. CREATE TABLE t1(a, b);
  1150. CREATE TABLE t2(a UNIQUE, b UNIQUE);
  1151. INSERT INTO t2 VALUES( a_string(800), a_string(800) );
  1152. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1153. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1154. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1155. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1156. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1157. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1158. INSERT INTO t1 VALUES (a_string(20000), a_string(20000));
  1159. }
  1160. faultsim_save_and_close
  1161. } {}
  1162. do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep {
  1163. faultsim_restore_and_reopen
  1164. db func a_string a_string
  1165. execsql {
  1166. PRAGMA cache_size = 10;
  1167. BEGIN EXCLUSIVE;
  1168. }
  1169. set ::channel [db incrblob t1 a 1]
  1170. } -body {
  1171. puts $::channel [string repeat abc 6000]
  1172. flush $::channel
  1173. } -test {
  1174. catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) }
  1175. catch { close $::channel }
  1176. catchsql { ROLLBACK }
  1177. faultsim_integrity_check
  1178. }
  1179. #-------------------------------------------------------------------------
  1180. #
  1181. do_test pagerfault-28-pre {
  1182. faultsim_delete_and_reopen
  1183. db func a_string a_string
  1184. execsql {
  1185. PRAGMA page_size = 512;
  1186. PRAGMA journal_mode = wal;
  1187. PRAGMA wal_autocheckpoint = 0;
  1188. PRAGMA cache_size = 100000;
  1189. BEGIN;
  1190. CREATE TABLE t2(a UNIQUE, b UNIQUE);
  1191. INSERT INTO t2 VALUES( a_string(800), a_string(800) );
  1192. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1193. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1194. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1195. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1196. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1197. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1198. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1199. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1200. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1201. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1202. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1203. COMMIT;
  1204. CREATE TABLE t1(a PRIMARY KEY, b);
  1205. }
  1206. expr {[file size test.db-shm] >= 96*1024}
  1207. } {1}
  1208. faultsim_save_and_close
  1209. do_faultsim_test pagerfault-28a -faults oom* -prep {
  1210. faultsim_restore_and_reopen
  1211. execsql { PRAGMA mmap_size=0 }
  1212. sqlite3 db2 test.db
  1213. db2 eval { SELECT count(*) FROM t2 }
  1214. db func a_string a_string
  1215. execsql {
  1216. BEGIN;
  1217. INSERT INTO t1 VALUES(a_string(2000), a_string(2000));
  1218. INSERT INTO t1 VALUES(a_string(2000), a_string(2000));
  1219. }
  1220. set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY]
  1221. sqlite3_step $::STMT
  1222. } -body {
  1223. execsql { ROLLBACK }
  1224. } -test {
  1225. db2 close
  1226. sqlite3_finalize $::STMT
  1227. catchsql { ROLLBACK }
  1228. faultsim_integrity_check
  1229. }
  1230. faultsim_restore_and_reopen
  1231. sqlite3 db2 test.db
  1232. db2 eval {SELECT count(*) FROM t2}
  1233. db close
  1234. do_faultsim_test pagerfault-28b -faults oom* -prep {
  1235. sqlite3 db test.db
  1236. } -body {
  1237. execsql { SELECT count(*) FROM t2 }
  1238. } -test {
  1239. faultsim_test_result {0 2048}
  1240. db close
  1241. }
  1242. db2 close
  1243. #-------------------------------------------------------------------------
  1244. # Try this:
  1245. #
  1246. # 1) Put the pager in ERROR state (error during rollback)
  1247. #
  1248. # 2) Next time the connection is used inject errors into all xWrite() and
  1249. # xUnlock() calls. This causes the hot-journal rollback to fail and
  1250. # the pager to declare its locking state UNKNOWN.
  1251. #
  1252. # 3) Same again.
  1253. #
  1254. # 4a) Stop injecting errors. Allow the rollback to succeed. Check that
  1255. # the database is Ok. Or,
  1256. #
  1257. # 4b) Close and reopen the db. Check that the db is Ok.
  1258. #
  1259. proc custom_injectinstall {} {
  1260. testvfs custom -default true
  1261. custom filter {xWrite xUnlock}
  1262. }
  1263. proc custom_injectuninstall {} {
  1264. catch {db close}
  1265. catch {db2 close}
  1266. custom delete
  1267. }
  1268. proc custom_injectstart {iFail} {
  1269. custom ioerr $iFail 1
  1270. }
  1271. proc custom_injectstop {} {
  1272. custom ioerr
  1273. }
  1274. set ::FAULTSIM(custom) [list \
  1275. -injectinstall custom_injectinstall \
  1276. -injectstart custom_injectstart \
  1277. -injectstop custom_injectstop \
  1278. -injecterrlist {{1 {disk I/O error}}} \
  1279. -injectuninstall custom_injectuninstall \
  1280. ]
  1281. do_test pagerfault-29-pre {
  1282. faultsim_delete_and_reopen
  1283. db func a_string a_string
  1284. execsql {
  1285. PRAGMA page_size = 1024;
  1286. PRAGMA cache_size = 5;
  1287. BEGIN;
  1288. CREATE TABLE t2(a UNIQUE, b UNIQUE);
  1289. INSERT INTO t2 VALUES( a_string(800), a_string(800) );
  1290. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1291. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1292. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1293. INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
  1294. COMMIT;
  1295. }
  1296. expr {[file size test.db] >= 50*1024}
  1297. } {1}
  1298. faultsim_save_and_close
  1299. foreach {tn tt} {
  1300. 29 { catchsql ROLLBACK }
  1301. 30 { db close ; sqlite3 db test.db }
  1302. } {
  1303. do_faultsim_test pagerfault-$tn -faults custom -prep {
  1304. faultsim_restore_and_reopen
  1305. db func a_string a_string
  1306. execsql {
  1307. PRAGMA cache_size = 5;
  1308. BEGIN;
  1309. UPDATE t2 SET a = a_string(799);
  1310. }
  1311. } -body {
  1312. catchsql ROLLBACK
  1313. catchsql ROLLBACK
  1314. catchsql ROLLBACK
  1315. } -test {
  1316. eval $::tt
  1317. if {"ok" != [db one {PRAGMA integrity_check}]} {
  1318. error "integrity check failed"
  1319. }
  1320. }
  1321. }
  1322. do_test pagerfault-31-pre {
  1323. sqlite3_shutdown
  1324. sqlite3_config_uri 1
  1325. } {SQLITE_OK}
  1326. do_faultsim_test pagerfault-31 -faults oom* -body {
  1327. sqlite3 db {file:one?mode=memory&cache=shared}
  1328. db eval {
  1329. CREATE TABLE t1(x);
  1330. INSERT INTO t1 VALUES(1);
  1331. SELECT * FROM t1;
  1332. }
  1333. } -test {
  1334. faultsim_test_result {0 1} {1 {}}
  1335. catch { db close }
  1336. }
  1337. sqlite3_shutdown
  1338. sqlite3_config_uri 0
  1339. do_test pagerfault-32-pre {
  1340. reset_db
  1341. execsql {
  1342. CREATE TABLE t1(x);
  1343. INSERT INTO t1 VALUES('one');
  1344. }
  1345. } {}
  1346. faultsim_save_and_close
  1347. do_faultsim_test pagerfault-32 -prep {
  1348. faultsim_restore_and_reopen
  1349. db eval { SELECT * FROM t1; }
  1350. } -body {
  1351. execsql { SELECT * FROM t1; }
  1352. } -test {
  1353. faultsim_test_result {0 one}
  1354. }
  1355. sqlite3_shutdown
  1356. sqlite3_config_uri 0
  1357. do_faultsim_test pagerfault-33a -prep {
  1358. sqlite3 db :memory:
  1359. execsql {
  1360. CREATE TABLE t1(a, b);
  1361. INSERT INTO t1 VALUES(1, 2);
  1362. }
  1363. } -body {
  1364. execsql { VACUUM }
  1365. } -test {
  1366. faultsim_test_result {0 {}}
  1367. }
  1368. do_faultsim_test pagerfault-33b -prep {
  1369. sqlite3 db ""
  1370. execsql {
  1371. CREATE TABLE t1(a, b);
  1372. INSERT INTO t1 VALUES(1, 2);
  1373. }
  1374. } -body {
  1375. execsql { VACUUM }
  1376. } -test {
  1377. faultsim_test_result {0 {}}
  1378. }
  1379. do_test pagerfault-34-pre {
  1380. reset_db
  1381. execsql {
  1382. CREATE TABLE t1(x PRIMARY KEY);
  1383. }
  1384. } {}
  1385. faultsim_save_and_close
  1386. do_faultsim_test pagerfault-34 -prep {
  1387. faultsim_restore_and_reopen
  1388. execsql {
  1389. BEGIN;
  1390. INSERT INTO t1 VALUES( randomblob(4000) );
  1391. DELETE FROM t1;
  1392. }
  1393. } -body {
  1394. execsql COMMIT
  1395. } -test {
  1396. faultsim_test_result {0 {}}
  1397. }
  1398. do_test pagerfault-35-pre {
  1399. faultsim_delete_and_reopen
  1400. execsql {
  1401. CREATE TABLE t1(x PRIMARY KEY, y);
  1402. INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
  1403. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1404. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1405. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1406. }
  1407. faultsim_save_and_close
  1408. } {}
  1409. testvfs tv -default 1
  1410. tv sectorsize 8192;
  1411. tv devchar [list]
  1412. do_faultsim_test pagerfault-35 -prep {
  1413. faultsim_restore_and_reopen
  1414. } -body {
  1415. execsql { UPDATE t1 SET x=randomblob(200) }
  1416. } -test {
  1417. faultsim_test_result {0 {}}
  1418. }
  1419. catch {db close}
  1420. tv delete
  1421. sqlite3_shutdown
  1422. sqlite3_config_uri 1
  1423. do_test pagerfault-36-pre {
  1424. faultsim_delete_and_reopen
  1425. execsql {
  1426. CREATE TABLE t1(x PRIMARY KEY, y);
  1427. INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
  1428. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1429. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1430. INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  1431. }
  1432. faultsim_save_and_close
  1433. } {}
  1434. do_faultsim_test pagerfault-36 -prep {
  1435. faultsim_restore
  1436. sqlite3 db file:test.db?cache=shared
  1437. sqlite3 db2 file:test.db?cache=shared
  1438. db2 eval {
  1439. BEGIN;
  1440. SELECT count(*) FROM sqlite_master;
  1441. }
  1442. db eval {
  1443. PRAGMA cache_size = 1;
  1444. BEGIN;
  1445. UPDATE t1 SET x = randomblob(200);
  1446. }
  1447. } -body {
  1448. execsql ROLLBACK db
  1449. } -test {
  1450. catch { db eval {UPDATE t1 SET x = randomblob(200)} }
  1451. faultsim_test_result {0 {}}
  1452. catch { db close }
  1453. catch { db2 close }
  1454. }
  1455. sqlite3_shutdown
  1456. sqlite3_config_uri 0
  1457. finish_test