xref: /sqlite-3.40.0/test/syscall.test (revision cd423525)
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 geteuid umask mmap munmap mremap
64    getpagesize readlink lstat
65} {
66  if {[test_syscall exists $s]} {lappend syscall_list $s}
67}
68do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]
69
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#
75test_syscall reset
76forcedelete test.db2
77do_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
85db_save_and_close
86test_syscall install open
87foreach 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  }
114}
115
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#
129catch { db close }
130forcedelete test.db test.db2
131
132do_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
170catch {db close}
171do_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
183do_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
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#
209catch { db close }
210forcedelete test.db test.db2
211
212proc 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
219foreach {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
226    list [catch {
227      sqlite3 db test.db
228      execsql { CREATE TABLE t1(a, b) }
229    } msg] $msg
230  } $res
231  catch { db close }
232}
233
234#-------------------------------------------------------------------------
235#
236catch { db close }
237forcedelete test.db test.db2
238
239do_test 8.1 {
240  sqlite3 db test.db
241  file_control_chunksize_test db main 4096
242  file size test.db
243} {0}
244foreach {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
257do_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}
264foreach {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
277test_syscall reset
278finish_test
279