xref: /sqlite-3.40.0/test/syscall.test (revision d5578433)
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