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