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