sysfault.test 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. # 2011 March 28
  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 {[llength [info commands test_syscall]]==0} {
  17. finish_test
  18. return
  19. }
  20. set testprefix sysfault
  21. set FAULTSIM(vfsfault-transient) [list \
  22. -injectinstall vfsfault_install \
  23. -injectstart vfsfault_injectstart_t \
  24. -injectstop vfsfault_injectstop \
  25. -injecterrlist {} \
  26. -injectuninstall {test_syscall uninstall} \
  27. ]
  28. set FAULTSIM(vfsfault-persistent) [list \
  29. -injectinstall vfsfault_install \
  30. -injectstart vfsfault_injectstart_p \
  31. -injectstop vfsfault_injectstop \
  32. -injecterrlist {} \
  33. -injectuninstall {test_syscall uninstall} \
  34. ]
  35. proc vfsfault_injectstart_t {iFail} { test_syscall fault $iFail 0 }
  36. proc vfsfault_injectstart_p {iFail} { test_syscall fault $iFail 1 }
  37. proc vfsfault_injectstop {} { test_syscall fault }
  38. faultsim_save_and_close
  39. set open_and_write_body {
  40. sqlite3 db test.db
  41. db eval {
  42. CREATE TABLE t1(a, b);
  43. INSERT INTO t1 VALUES(1, 2);
  44. PRAGMA journal_mode = WAL;
  45. INSERT INTO t1 VALUES(3, 4);
  46. SELECT * FROM t1;
  47. CREATE TEMP TABLE t2(x);
  48. INSERT INTO t2 VALUES('y');
  49. }
  50. }
  51. proc vfsfault_install {} { test_syscall install {open getcwd} }
  52. do_faultsim_test 1 -faults vfsfault-* -prep {
  53. faultsim_restore
  54. } -body $open_and_write_body -test {
  55. faultsim_test_result {0 {wal 1 2 3 4}} \
  56. {1 {unable to open database file}} \
  57. {1 {attempt to write a readonly database}}
  58. }
  59. #-------------------------------------------------------------------------
  60. # Errors in the fstat() function when opening and writing a file. Cases
  61. # where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both
  62. # tested. EOVERFLOW is interpreted as meaning that a file on disk is
  63. # too large to be opened by the OS.
  64. #
  65. foreach {tn errno errlist} {
  66. 1 ENOMEM {{disk I/O error}}
  67. 2 EOVERFLOW {{disk I/O error} {large file support is disabled}}
  68. } {
  69. proc vfsfault_install {} { test_syscall install fstat }
  70. set errs [list]
  71. foreach e $errlist { lappend errs [list 1 $e] }
  72. do_faultsim_test 1.2.$tn -faults vfsfault-* -prep {
  73. faultsim_restore
  74. } -body "
  75. test_syscall errno fstat $errno
  76. $open_and_write_body
  77. " -test "
  78. faultsim_test_result {0 {wal 1 2 3 4}} $errs
  79. "
  80. }
  81. #-------------------------------------------------------------------------
  82. # Various errors in locking functions.
  83. #
  84. foreach vfs {unix unix-excl} {
  85. foreach {tn errno errlist} {
  86. 1 EAGAIN {{database is locked} {disk I/O error}}
  87. 2 ETIMEDOUT {{database is locked} {disk I/O error}}
  88. 3 EBUSY {{database is locked} {disk I/O error}}
  89. 4 EINTR {{database is locked} {disk I/O error}}
  90. 5 ENOLCK {{database is locked} {disk I/O error}}
  91. 6 EACCES {{database is locked} {disk I/O error}}
  92. 7 EPERM {{access permission denied} {disk I/O error}}
  93. 8 EDEADLK {{disk I/O error}}
  94. 9 ENOMEM {{disk I/O error}}
  95. } {
  96. proc vfsfault_install {} { test_syscall install fcntl }
  97. set errs [list]
  98. foreach e $errlist { lappend errs [list 1 $e] }
  99. set body [string map [list %VFS% $vfs] {
  100. sqlite3 db test.db
  101. db eval {
  102. CREATE TABLE t1(a, b);
  103. INSERT INTO t1 VALUES(1, 2);
  104. }
  105. set fd [open test.db-journal w]
  106. puts $fd "hello world"
  107. close $fd
  108. sqlite3 db test.db -vfs %VFS%
  109. db eval {
  110. SELECT * FROM t1;
  111. }
  112. }]
  113. do_faultsim_test 1.3.$vfs.$tn -faults vfsfault-* -prep {
  114. faultsim_restore
  115. } -body "
  116. test_syscall errno fcntl $errno
  117. $body
  118. " -test "
  119. faultsim_test_result {0 {1 2}} $errs
  120. "
  121. }
  122. }
  123. #-------------------------------------------------------------------------
  124. # Check that a single EINTR error does not affect processing.
  125. #
  126. proc vfsfault_install {} {
  127. test_syscall reset
  128. test_syscall install {open ftruncate close read pread pread64 write fallocate}
  129. }
  130. forcedelete test.db test.db2
  131. sqlite3 db test.db
  132. do_test 2.setup {
  133. execsql {
  134. CREATE TABLE t1(a, b, c, PRIMARY KEY(a));
  135. INSERT INTO t1 VALUES('abc', 'def', 'ghi');
  136. ATTACH 'test.db2' AS 'aux';
  137. CREATE TABLE aux.t2(x);
  138. INSERT INTO t2 VALUES(1);
  139. }
  140. faultsim_save_and_close
  141. } {}
  142. do_faultsim_test 2.1 -faults vfsfault-transient -prep {
  143. catch { db close }
  144. faultsim_restore
  145. } -body {
  146. test_syscall errno open EINTR
  147. test_syscall errno ftruncate EINTR
  148. test_syscall errno close EINTR
  149. test_syscall errno read EINTR
  150. test_syscall errno pread EINTR
  151. test_syscall errno pread64 EINTR
  152. test_syscall errno write EINTR
  153. test_syscall errno fallocate EINTR
  154. sqlite3 db test.db
  155. file_control_chunksize_test db main 8192
  156. set res [db eval {
  157. ATTACH 'test.db2' AS 'aux';
  158. SELECT * FROM t1;
  159. PRAGMA journal_mode = truncate;
  160. BEGIN;
  161. INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
  162. INSERT INTO t1 VALUES(randomblob(10000), 0, 0);
  163. UPDATE t2 SET x = 2;
  164. COMMIT;
  165. DELETE FROM t1 WHERE length(a)>3;
  166. SELECT * FROM t1;
  167. SELECT * FROM t2;
  168. }]
  169. db close
  170. set res
  171. } -test {
  172. faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}}
  173. }
  174. do_faultsim_test 2.2 -faults vfsfault-* -prep {
  175. catch { db close }
  176. faultsim_restore
  177. } -body {
  178. sqlite3 db test.db
  179. set res [db eval {
  180. ATTACH 'test.db2' AS 'aux';
  181. SELECT * FROM t1;
  182. PRAGMA journal_mode = truncate;
  183. BEGIN;
  184. INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
  185. UPDATE t2 SET x = 2;
  186. COMMIT;
  187. SELECT * FROM t1;
  188. SELECT * FROM t2;
  189. }]
  190. db close
  191. set res
  192. } -test {
  193. faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} \
  194. {1 {unable to open database file}} \
  195. {1 {unable to open database: test.db2}} \
  196. {1 {attempt to write a readonly database}} \
  197. {1 {disk I/O error}}
  198. }
  199. #-------------------------------------------------------------------------
  200. proc vfsfault_install {} {
  201. test_syscall reset
  202. test_syscall install {fstat fallocate}
  203. }
  204. do_faultsim_test 3 -faults vfsfault-* -prep {
  205. faultsim_delete_and_reopen
  206. file_control_chunksize_test db main 8192
  207. execsql {
  208. CREATE TABLE t1(a, b);
  209. BEGIN;
  210. SELECT * FROM t1;
  211. }
  212. } -body {
  213. test_syscall errno fstat EIO
  214. test_syscall errno fallocate EIO
  215. execsql {
  216. INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000));
  217. SELECT length(a) + length(b) FROM t1;
  218. COMMIT;
  219. }
  220. } -test {
  221. faultsim_test_result {0 20000}
  222. }
  223. #-------------------------------------------------------------------------
  224. # Test errors in mmap().
  225. #
  226. proc vfsfault_install {} {
  227. test_syscall reset
  228. test_syscall install {mmap}
  229. }
  230. faultsim_delete_and_reopen
  231. execsql {
  232. CREATE TABLE t1(a, b);
  233. INSERT INTO t1 VALUES(1, 2);
  234. }
  235. faultsim_save_and_close
  236. do_faultsim_test 4 -faults vfsfault-* -prep {
  237. faultsim_restore_and_reopen
  238. file_control_chunksize_test db main 8192
  239. execsql {
  240. PRAGMA mmap_size = 1000000;
  241. }
  242. } -body {
  243. test_syscall errno mmap EACCES
  244. execsql {
  245. SELECT * FROM t1;
  246. }
  247. } -test {
  248. faultsim_test_result {0 {1 2}} {1 {disk I/O error}}
  249. }
  250. finish_test