dan | 0fd7d86 | 2011-03-29 10:04:23 +0000 | [diff] [blame] | 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 | } |
dan | 0fd7d86 | 2011-03-29 10:04:23 +0000 | [diff] [blame] | 22 | |
dan | 51438a7 | 2011-04-02 17:00:47 +0000 | [diff] [blame] | 23 | if {[test_syscall defaultvfs] != "unix"} { |
| 24 | finish_test |
| 25 | return |
| 26 | } |
| 27 | set testprefix syscall |
dan | 0fd7d86 | 2011-03-29 10:04:23 +0000 | [diff] [blame] | 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 | # |
dan | 51438a7 | 2011-04-02 17:00:47 +0000 | [diff] [blame] | 59 | foreach s { |
| 60 | open close access getcwd stat fstat ftruncate |
| 61 | fcntl read pread write pwrite fchmod fallocate |
drh | 1eaaf93 | 2011-12-19 00:31:09 +0000 | [diff] [blame] | 62 | pread64 pwrite64 unlink openDirectory mkdir rmdir |
drh | 6226ca2 | 2015-11-24 15:06:28 +0000 | [diff] [blame] | 63 | statvfs fchown geteuid umask mmap munmap mremap |
dan | af1b36b | 2016-01-25 18:43:05 +0000 | [diff] [blame] | 64 | getpagesize readlink lstat |
dan | 51438a7 | 2011-04-02 17:00:47 +0000 | [diff] [blame] | 65 | } { |
| 66 | if {[test_syscall exists $s]} {lappend syscall_list $s} |
| 67 | } |
| 68 | do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list] |
dan | 0fd7d86 | 2011-03-29 10:04:23 +0000 | [diff] [blame] | 69 | |
dan | 60939d0 | 2011-03-29 15:40:55 +0000 | [diff] [blame] | 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. |
| 74 | # |
| 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); |
| 83 | } |
| 84 | |
| 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 | } |
| 104 | |
| 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 | } |
dan | 60939d0 | 2011-03-29 15:40:55 +0000 | [diff] [blame] | 114 | } |
| 115 | |
dan | 5ef47bf | 2011-03-29 18:28:35 +0000 | [diff] [blame] | 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. |
| 119 | # |
| 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: |
| 123 | # |
| 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). |
| 128 | # |
| 129 | catch { db close } |
| 130 | forcedelete test.db test.db2 |
| 131 | |
| 132 | do_multiclient_test tn { |
| 133 | code1 { |
| 134 | sqlite3 dbX1 test.db |
| 135 | sqlite3 dbX2 test.db |
| 136 | } |
| 137 | |
| 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 | } {} |
| 146 | |
| 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}} |
| 151 | |
| 152 | do_test syscall-5.$tn.4 { |
| 153 | code1 { |
| 154 | dbX1 close |
| 155 | dbX2 close |
| 156 | } |
| 157 | } {} |
| 158 | |
| 159 | do_test syscall-5.$tn.5 { |
| 160 | csql2 { INSERT INTO t1 VALUES(5, 6) } |
| 161 | } {1 {database is locked}} |
| 162 | |
| 163 | do_test syscall-5.$tn.6 { sql1 { COMMIT } } {} |
| 164 | |
| 165 | do_test syscall-5.$tn.7 { |
| 166 | csql2 { INSERT INTO t1 VALUES(5, 6) } |
| 167 | } {0 {}} |
| 168 | } |
| 169 | |
| 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 "" |
| 176 | |
| 177 | db2 close |
| 178 | db3 close |
| 179 | dbM close |
| 180 | db1 close |
| 181 | } {} |
| 182 | |
| 183 | do_test 6.2 { |
| 184 | sqlite3 db test.db |
| 185 | execsql { |
| 186 | PRAGMA temp_store = file; |
| 187 | |
| 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 | } |
| 201 | |
| 202 | db close |
| 203 | } {} |
| 204 | |
dan | 661d71a | 2011-03-30 19:08:03 +0000 | [diff] [blame] | 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. |
| 208 | # |
| 209 | catch { db close } |
| 210 | forcedelete test.db test.db2 |
| 211 | |
| 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 |
| 217 | } |
| 218 | |
| 219 | foreach {nByte res} { |
| 220 | 1 {0 {}} |
| 221 | 2 {1 {file is encrypted or is not a database}} |
| 222 | 3 {1 {file is encrypted or is not a database}} |
| 223 | } { |
| 224 | do_test 7.$nByte { |
| 225 | create_db_file $nByte |
dan | 26ec621 | 2011-04-04 07:05:38 +0000 | [diff] [blame] | 226 | list [catch { |
| 227 | sqlite3 db test.db |
| 228 | execsql { CREATE TABLE t1(a, b) } |
| 229 | } msg] $msg |
dan | 661d71a | 2011-03-30 19:08:03 +0000 | [diff] [blame] | 230 | } $res |
| 231 | catch { db close } |
| 232 | } |
| 233 | |
| 234 | #------------------------------------------------------------------------- |
| 235 | # |
| 236 | catch { db close } |
| 237 | forcedelete test.db test.db2 |
| 238 | |
| 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} |
dan | 661d71a | 2011-03-30 19:08:03 +0000 | [diff] [blame] | 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 |
| 255 | } |
| 256 | |
dan | dc5df0f | 2011-04-06 19:15:45 +0000 | [diff] [blame] | 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 |
| 275 | } |
| 276 | |
dan | 51438a7 | 2011-04-02 17:00:47 +0000 | [diff] [blame] | 277 | test_syscall reset |
dan | 0fd7d86 | 2011-03-29 10:04:23 +0000 | [diff] [blame] | 278 | finish_test |