update changelog to reflect upstream SQLite version
[sqlcipher.git] / test / syscall.test
blob19313a5e67e06d94eecd635d9a557b336e399373
1 # 2011 March 29
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
15 source $testdir/lock_common.tcl
16 source $testdir/malloc_common.tcl
18 if {[llength [info commands test_syscall]]==0} {
19   finish_test
20   return
21
23 if {[test_syscall defaultvfs] != "unix"} {
24   finish_test
25   return
27 set testprefix syscall
29 #-------------------------------------------------------------------------
30 # Tests for the xSetSystemCall method.
32 do_test 1.1.1 {
33   list [catch { test_syscall reset open } msg] $msg
34 } {0 {}}
35 do_test 1.1.2 {
36   list [catch { test_syscall reset nosuchcall } msg] $msg
37 } {1 SQLITE_NOTFOUND}
38 do_test 1.1.3 {
39   list [catch { test_syscall reset open } msg] $msg
40 } {0 {}}
41 do_test 1.1.4 {
42   list [catch { test_syscall reset ""} msg] $msg
43 } {1 SQLITE_NOTFOUND}
45 do_test 1.2 { test_syscall reset } {}
47 do_test 1.3.1 { test_syscall install {open getcwd access} } {}
48 do_test 1.3.2 { test_syscall reset } {}
50 #-------------------------------------------------------------------------
51 # Tests for the xGetSystemCall method.
53 do_test 2.1.1 { test_syscall exists open } 1
54 do_test 2.1.2 { test_syscall exists nosuchcall } 0
56 #-------------------------------------------------------------------------
57 # Tests for the xNextSystemCall method.
59 foreach s {
60     open close access getcwd stat fstat ftruncate
61     fcntl read pread write pwrite fchmod fallocate
62     pread64 pwrite64 unlink openDirectory mkdir rmdir 
63     statvfs fchown geteuid umask mmap munmap mremap
64     getpagesize readlink lstat ioctl
65 } {
66   if {[test_syscall exists $s]} {lappend syscall_list $s}
68 do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]
70 #-------------------------------------------------------------------------
71 # This test verifies that if a call to open() fails and errno is set to
72 # EINTR, the call is retried. If it succeeds, execution continues as if
73 # nothing happened. 
75 test_syscall reset
76 forcedelete test.db2
77 do_execsql_test 4.1 {
78   CREATE TABLE t1(x, y);
79   INSERT INTO t1 VALUES(1, 2);
80   ATTACH 'test.db2' AS aux;
81   CREATE TABLE aux.t2(x, y);
82   INSERT INTO t2 VALUES(3, 4);
85 db_save_and_close
86 test_syscall install open
87 foreach jrnl [list wal delete] {
88   for {set i 1} {$i < 20} {incr i} {
89     db_restore_and_reopen
90     test_syscall fault $i 0
91     test_syscall errno open EINTR
92   
93     do_test 4.2.$jrnl.$i {
94       sqlite3 db test.db
95       execsql { ATTACH 'test.db2' AS aux }
96       execsql "PRAGMA main.journal_mode = $jrnl"
97       execsql "PRAGMA aux.journal_mode = $jrnl"
98       execsql {
99         BEGIN;
100           INSERT INTO t1 VALUES(5, 6);
101           INSERT INTO t2 VALUES(7, 8);
102         COMMIT;
103       }
105       db close
106       sqlite3 db test.db
107       execsql { ATTACH 'test.db2' AS aux }
108       execsql {
109         SELECT * FROM t1;
110         SELECT * FROM t2;
111       }
112     } {1 2 5 6 3 4 7 8}
113   }
116 #-------------------------------------------------------------------------
117 # This test verifies that closing database handles does not drop locks
118 # held by other database handles in the same process on the same file.
120 # The os_unix.c module has to take precautions to prevent this as the
121 # close() system call drops locks held by other file-descriptors on the
122 # same file. From the Linux man page:
124 #   close() closes a file descriptor, so that it no longer refers to any file
125 #   and may be reused. Any record locks (see fcntl(2)) held on the file it 
126 #   was associated with, and owned by the process, are removed (regardless 
127 #   of the file descriptor that was used to obtain the lock).
129 catch { db close }
130 forcedelete test.db test.db2
132 do_multiclient_test tn {
133   code1 {
134     sqlite3 dbX1 test.db
135     sqlite3 dbX2 test.db
136   }
138   do_test syscall-5.$tn.1 {
139     sql1 {
140       CREATE TABLE t1(a, b);
141       INSERT INTO t1 VALUES(1, 2);
142       BEGIN;
143         INSERT INTO t1 VALUES(3, 4);
144     }
145   } {}
147   do_test syscall-5.$tn.2 { sql2 { SELECT * FROM t1 } } {1 2}
148   do_test syscall-5.$tn.3 { 
149     csql2 { INSERT INTO t1 VALUES(5, 6) }
150   } {1 {database is locked}}
152   do_test syscall-5.$tn.4 { 
153     code1 {
154       dbX1 close
155       dbX2 close
156     }
157   } {}
159   do_test syscall-5.$tn.5 { 
160     csql2 { INSERT INTO t1 VALUES(5, 6) }
161   } {1 {database is locked}}
163   do_test syscall-5.$tn.6 { sql1 { COMMIT } } {}
165   do_test syscall-5.$tn.7 { 
166     csql2 { INSERT INTO t1 VALUES(5, 6) }
167   } {0 {}}
170 catch {db close}
171 do_test 6.1 {
172   sqlite3 db1 test.db1
173   sqlite3 db2 test.db2
174   sqlite3 db3 test.db3
175   sqlite3 dbM ""
177   db2 close
178   db3 close
179   dbM close
180   db1 close
181 } {}
183 do_test 6.2 {
184   sqlite3 db test.db
185   execsql {
186     PRAGMA temp_store = file;
188     PRAGMA main.cache_size = 10;
189     PRAGMA temp.cache_size = 10;
190     CREATE TABLE temp.tt(a, b);
191     INSERT INTO tt VALUES(randomblob(500), randomblob(600));
192     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
193     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
194     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
195     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
196     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
197     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
198     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
199     INSERT INTO tt SELECT randomblob(500), randomblob(600) FROM tt;
200   }
202   db close
203 } {}
205 #-------------------------------------------------------------------------
206 # Test that a database file a single byte in size is treated as an empty
207 # file. Whereas a file 2 bytes or larger might be considered corrupt.
209 catch { db close }
210 forcedelete test.db test.db2
212 proc create_db_file {nByte} {
213   set fd [open test.db w]
214   fconfigure $fd -translation binary -encoding binary
215   puts -nonewline $fd [string range "xSQLite" 1 $nByte]
216   close $fd
219 foreach {nByte res} {
220   1      {0 {}}
221   2      {1 {file is not a database}}
222   3      {1 {file is not a database}}
223 } {
224   do_test 7.$nByte {
225     create_db_file $nByte
226     list [catch {
227       sqlite3 db test.db
228       execsql { CREATE TABLE t1(a, b) }
229     } msg] $msg
230   } $res
231   catch { db close }
234 #-------------------------------------------------------------------------
236 catch { db close }
237 forcedelete test.db test.db2
239 do_test 8.1 {
240   sqlite3 db test.db
241   file_control_chunksize_test db main 4096
242   file size test.db
243 } {0}
244 foreach {tn hint size} {
245   1  1000    4096 
246   2  1000    4096 
247   3  3000    4096 
248   4  4096    4096 
249   5  4197    8192 
250 } {
251   do_test 8.2.$tn {
252     file_control_sizehint_test db main $hint
253     file size test.db
254   } $size
257 do_test 8.3 {
258   db close
259   forcedelete test.db test.db2
260   sqlite3 db test.db
261   file_control_chunksize_test db main 16
262   file size test.db
263 } {0}
264 foreach {tn hint size} {
265   1  5       16 
266   2  13      16 
267   3  45      48 
268   4  48      48 
269   5  49      64 
270 } {
271   do_test 8.4.$tn {
272     file_control_sizehint_test db main $hint
273     file size test.db
274   } $size
277 test_syscall reset
278 finish_test