diff options
Diffstat (limited to 'libraries/sqlite/unix/sqlite-3.5.1/test/ioerr.test')
-rw-r--r-- | libraries/sqlite/unix/sqlite-3.5.1/test/ioerr.test | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/libraries/sqlite/unix/sqlite-3.5.1/test/ioerr.test b/libraries/sqlite/unix/sqlite-3.5.1/test/ioerr.test new file mode 100644 index 0000000..9fb2668 --- /dev/null +++ b/libraries/sqlite/unix/sqlite-3.5.1/test/ioerr.test | |||
@@ -0,0 +1,290 @@ | |||
1 | # 2001 October 12 | ||
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 file is testing for correct handling of I/O errors | ||
13 | # such as writes failing because the disk is full. | ||
14 | # | ||
15 | # The tests in this file use special facilities that are only | ||
16 | # available in the SQLite test fixture. | ||
17 | # | ||
18 | # $Id: ioerr.test,v 1.32 2007/09/01 17:00:13 danielk1977 Exp $ | ||
19 | |||
20 | set testdir [file dirname $argv0] | ||
21 | source $testdir/tester.tcl | ||
22 | |||
23 | |||
24 | # If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error | ||
25 | # on the 8th IO operation in the SQL script below doesn't report an error. | ||
26 | # | ||
27 | # This is because the 8th IO call attempts to read page 2 of the database | ||
28 | # file when the file on disk is only 1 page. The pager layer detects that | ||
29 | # this has happened and suppresses the error returned by the OS layer. | ||
30 | # | ||
31 | do_ioerr_test ioerr-1 -erc 1 -sqlprep { | ||
32 | SELECT * FROM sqlite_master; | ||
33 | } -sqlbody { | ||
34 | CREATE TABLE t1(a,b,c); | ||
35 | SELECT * FROM sqlite_master; | ||
36 | BEGIN TRANSACTION; | ||
37 | INSERT INTO t1 VALUES(1,2,3); | ||
38 | INSERT INTO t1 VALUES(4,5,6); | ||
39 | ROLLBACK; | ||
40 | SELECT * FROM t1; | ||
41 | BEGIN TRANSACTION; | ||
42 | INSERT INTO t1 VALUES(1,2,3); | ||
43 | INSERT INTO t1 VALUES(4,5,6); | ||
44 | COMMIT; | ||
45 | SELECT * FROM t1; | ||
46 | DELETE FROM t1 WHERE a<100; | ||
47 | } -exclude [expr [string match [execsql {pragma auto_vacuum}] 1] ? 4 : 0] | ||
48 | |||
49 | # Test for IO errors during a VACUUM. | ||
50 | # | ||
51 | # The first IO call is excluded from the test. This call attempts to read | ||
52 | # the file-header of the temporary database used by VACUUM. Since the | ||
53 | # database doesn't exist at that point, the IO error is not detected. | ||
54 | # | ||
55 | # Additionally, if auto-vacuum is enabled, the 12th IO error is not | ||
56 | # detected. Same reason as the 8th in the test case above. | ||
57 | # | ||
58 | ifcapable vacuum { | ||
59 | do_ioerr_test ioerr-2 -cksum true -sqlprep { | ||
60 | BEGIN; | ||
61 | CREATE TABLE t1(a, b, c); | ||
62 | INSERT INTO t1 VALUES(1, randstr(50,50), randstr(50,50)); | ||
63 | INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
64 | INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
65 | INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
66 | INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
67 | INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
68 | INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
69 | INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1; | ||
70 | INSERT INTO t1 VALUES(1, randstr(600,600), randstr(600,600)); | ||
71 | CREATE TABLE t2 AS SELECT * FROM t1; | ||
72 | CREATE TABLE t3 AS SELECT * FROM t1; | ||
73 | COMMIT; | ||
74 | DROP TABLE t2; | ||
75 | } -sqlbody { | ||
76 | VACUUM; | ||
77 | } -exclude [list \ | ||
78 | 1 [expr [string match [execsql {pragma auto_vacuum}] 1]?9:-1]] | ||
79 | } | ||
80 | |||
81 | do_ioerr_test ioerr-3 -tclprep { | ||
82 | execsql { | ||
83 | PRAGMA cache_size = 10; | ||
84 | BEGIN; | ||
85 | CREATE TABLE abc(a); | ||
86 | INSERT INTO abc VALUES(randstr(1500,1500)); -- Page 4 is overflow | ||
87 | } | ||
88 | for {set i 0} {$i<150} {incr i} { | ||
89 | execsql { | ||
90 | INSERT INTO abc VALUES(randstr(100,100)); | ||
91 | } | ||
92 | } | ||
93 | execsql COMMIT | ||
94 | } -sqlbody { | ||
95 | CREATE TABLE abc2(a); | ||
96 | BEGIN; | ||
97 | DELETE FROM abc WHERE length(a)>100; | ||
98 | UPDATE abc SET a = randstr(90,90); | ||
99 | COMMIT; | ||
100 | CREATE TABLE abc3(a); | ||
101 | } | ||
102 | |||
103 | # Test IO errors that can occur retrieving a record header that flows over | ||
104 | # onto an overflow page. | ||
105 | do_ioerr_test ioerr-4 -tclprep { | ||
106 | set sql "CREATE TABLE abc(a1" | ||
107 | for {set i 2} {$i<1300} {incr i} { | ||
108 | append sql ", a$i" | ||
109 | } | ||
110 | append sql ");" | ||
111 | execsql $sql | ||
112 | execsql {INSERT INTO abc (a1) VALUES(NULL)} | ||
113 | } -sqlbody { | ||
114 | SELECT * FROM abc; | ||
115 | } | ||
116 | |||
117 | # Test IO errors that may occur during a multi-file commit. | ||
118 | # | ||
119 | # Tests 8 and 17 are excluded when auto-vacuum is enabled for the same | ||
120 | # reason as in test cases ioerr-1.XXX | ||
121 | set ex "" | ||
122 | if {[string match [execsql {pragma auto_vacuum}] 1]} { | ||
123 | set ex [list 4 17] | ||
124 | } | ||
125 | do_ioerr_test ioerr-5 -sqlprep { | ||
126 | ATTACH 'test2.db' AS test2; | ||
127 | } -sqlbody { | ||
128 | BEGIN; | ||
129 | CREATE TABLE t1(a,b,c); | ||
130 | CREATE TABLE test2.t2(a,b,c); | ||
131 | COMMIT; | ||
132 | } -exclude $ex | ||
133 | |||
134 | # Test IO errors when replaying two hot journals from a 2-file | ||
135 | # transaction. This test only runs on UNIX. | ||
136 | ifcapable crashtest { | ||
137 | if {![catch {sqlite3 -has_codec} r] && !$r} { | ||
138 | do_ioerr_test ioerr-6 -tclprep { | ||
139 | execsql { | ||
140 | ATTACH 'test2.db' as aux; | ||
141 | CREATE TABLE tx(a, b); | ||
142 | CREATE TABLE aux.ty(a, b); | ||
143 | } | ||
144 | set rc [crashsql -delay 2 -file test2.db-journal { | ||
145 | ATTACH 'test2.db' as aux; | ||
146 | PRAGMA cache_size = 10; | ||
147 | BEGIN; | ||
148 | CREATE TABLE aux.t2(a, b, c); | ||
149 | CREATE TABLE t1(a, b, c); | ||
150 | COMMIT; | ||
151 | }] | ||
152 | if {$rc!="1 {child process exited abnormally}"} { | ||
153 | error "Wrong error message: $rc" | ||
154 | } | ||
155 | } -sqlbody { | ||
156 | SELECT * FROM sqlite_master; | ||
157 | SELECT * FROM aux.sqlite_master; | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | # Test handling of IO errors that occur while rolling back hot journal | ||
163 | # files. | ||
164 | # | ||
165 | # These tests can't be run on windows because the windows version of | ||
166 | # SQLite holds a mandatory exclusive lock on journal files it has open. | ||
167 | # | ||
168 | btree_breakpoint | ||
169 | if {$tcl_platform(platform)!="windows"} { | ||
170 | do_ioerr_test ioerr-7 -tclprep { | ||
171 | db close | ||
172 | sqlite3 db2 test2.db | ||
173 | db2 eval { | ||
174 | PRAGMA synchronous = 0; | ||
175 | CREATE TABLE t1(a, b); | ||
176 | INSERT INTO t1 VALUES(1, 2); | ||
177 | BEGIN; | ||
178 | INSERT INTO t1 VALUES(3, 4); | ||
179 | } | ||
180 | copy_file test2.db test.db | ||
181 | copy_file test2.db-journal test.db-journal | ||
182 | db2 close | ||
183 | } -tclbody { | ||
184 | sqlite3 db test.db | ||
185 | db eval { | ||
186 | SELECT * FROM t1; | ||
187 | } | ||
188 | } -exclude 1 | ||
189 | } | ||
190 | |||
191 | # For test coverage: Cause an I/O failure while trying to read a | ||
192 | # short field (one that fits into a Mem buffer without mallocing | ||
193 | # for space). | ||
194 | # | ||
195 | do_ioerr_test ioerr-8 -tclprep { | ||
196 | execsql { | ||
197 | CREATE TABLE t1(a,b,c); | ||
198 | INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); | ||
199 | } | ||
200 | db close | ||
201 | sqlite3 db test.db | ||
202 | } -sqlbody { | ||
203 | SELECT c FROM t1; | ||
204 | } | ||
205 | |||
206 | # For test coverage: Cause an IO error whilst reading the master-journal | ||
207 | # name from a journal file. | ||
208 | if {$tcl_platform(platform)=="unix"} { | ||
209 | do_ioerr_test ioerr-9 -tclprep { | ||
210 | execsql { | ||
211 | CREATE TABLE t1(a,b,c); | ||
212 | INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); | ||
213 | BEGIN; | ||
214 | INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); | ||
215 | } | ||
216 | copy_file test.db-journal test2.db-journal | ||
217 | execsql { | ||
218 | COMMIT; | ||
219 | } | ||
220 | copy_file test2.db-journal test.db-journal | ||
221 | set f [open test.db-journal a] | ||
222 | fconfigure $f -encoding binary | ||
223 | puts -nonewline $f "hello" | ||
224 | puts -nonewline $f "\x00\x00\x00\x05\x01\x02\x03\x04" | ||
225 | puts -nonewline $f "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7" | ||
226 | close $f | ||
227 | } -sqlbody { | ||
228 | SELECT a FROM t1; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | # For test coverage: Cause an IO error during statement playback (i.e. | ||
233 | # a constraint). | ||
234 | do_ioerr_test ioerr-10 -tclprep { | ||
235 | execsql { | ||
236 | BEGIN; | ||
237 | CREATE TABLE t1(a PRIMARY KEY, b); | ||
238 | } | ||
239 | for {set i 0} {$i < 500} {incr i} { | ||
240 | execsql {INSERT INTO t1 VALUES(:i, 'hello world');} | ||
241 | } | ||
242 | execsql { | ||
243 | COMMIT; | ||
244 | } | ||
245 | } -tclbody { | ||
246 | |||
247 | catch {execsql { | ||
248 | BEGIN; | ||
249 | INSERT INTO t1 VALUES('abc', 123); | ||
250 | INSERT INTO t1 VALUES('def', 123); | ||
251 | INSERT INTO t1 VALUES('ghi', 123); | ||
252 | INSERT INTO t1 SELECT (a+500)%900, 'good string' FROM t1; | ||
253 | }} msg | ||
254 | |||
255 | if {$msg != "column a is not unique"} { | ||
256 | error $msg | ||
257 | } | ||
258 | } | ||
259 | |||
260 | # Assertion fault bug reported by alex dimitrov. | ||
261 | # | ||
262 | do_ioerr_test ioerr-11 -erc 1 -sqlprep { | ||
263 | CREATE TABLE A(Id INTEGER, Name TEXT); | ||
264 | INSERT INTO A(Id, Name) VALUES(1, 'Name'); | ||
265 | } -sqlbody { | ||
266 | UPDATE A SET Id = 2, Name = 'Name2' WHERE Id = 1; | ||
267 | } | ||
268 | |||
269 | # Test that an io error encountered in a sync() caused by a call to | ||
270 | # sqlite3_release_memory() is handled Ok. Only try this if | ||
271 | # memory-management is enabled. | ||
272 | # | ||
273 | ifcapable memorymanage { | ||
274 | do_ioerr_test memmanage-ioerr1 -sqlprep { | ||
275 | BEGIN; | ||
276 | CREATE TABLE t1(a, b, c); | ||
277 | INSERT INTO t1 VALUES(randstr(50,50), randstr(100,100), randstr(10,10)); | ||
278 | INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1; | ||
279 | INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1; | ||
280 | INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1; | ||
281 | INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1; | ||
282 | INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1; | ||
283 | } -tclbody { | ||
284 | sqlite3_release_memory | ||
285 | } -sqlbody { | ||
286 | COMMIT; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | finish_test | ||