Home | History | Annotate | Download | only in test
      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