xref: /sqlite-3.40.0/test/multiplex.test (revision 050d09ab)
1# 2010 October 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/malloc_common.tcl
16
17set g_chunk_size 2147483648
18set g_max_chunks 32
19
20# This handles appending the chunk number
21# to the end of the filename.  if
22# SQLITE_MULTIPLEX_EXT_OVWR is defined, then
23# it overwrites the last 2 bytes of the
24# file name with the chunk number.
25proc multiplex_name {name chunk} {
26  if {$chunk==0} { return $name }
27  set num [format "%02d" $chunk]
28  ifcapable {multiplex_ext_overwrite} {
29    set name [string range $name 0 [expr [string length $name]-2-1]]
30  }
31  return $name$num
32}
33
34# This saves off the parameters and calls the
35# underlying sqlite3_multiplex_set() API.
36proc multiplex_set {chunk_size max_chunks} {
37  global g_chunk_size
38  global g_max_chunks
39  set g_chunk_size $chunk_size
40  set g_max_chunks $max_chunks
41  sqlite3_multiplex_set $chunk_size $max_chunks
42}
43
44# This attempts to delete the base file and
45# and files with the chunk extension.
46proc multiplex_delete {name} {
47  global g_max_chunks
48  for {set i 0} {$i<$g_max_chunks} {incr i} {
49    forcedelete [multiplex_name $name $i]
50    forcedelete [multiplex_name $name-journal $i]
51    forcedelete [multiplex_name $name-wal $i]
52  }
53}
54
55db close
56
57#-------------------------------------------------------------------------
58#   multiplex-1.1.*: Test initialize and shutdown.
59
60do_test multiplex-1.1 { sqlite3_multiplex_initialize nosuchvfs 1 } {SQLITE_ERROR}
61do_test multiplex-1.2 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
62do_test multiplex-1.3 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_MISUSE}
63do_test multiplex-1.4 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
64
65do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 }        {SQLITE_OK}
66do_test multiplex-1.6 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
67do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
68do_test multiplex-1.8 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
69
70do_test multiplex-1.9  { sqlite3_multiplex_initialize "" 1 }       {SQLITE_OK}
71do_test multiplex-1.10.1 { multiplex_set 32768 16 }                {SQLITE_OK}
72do_test multiplex-1.10.2 { multiplex_set 32768 -1 }                {SQLITE_MISUSE}
73do_test multiplex-1.10.3 { multiplex_set -1 16 }                   {SQLITE_MISUSE}
74do_test multiplex-1.10.4 { multiplex_set 31 16 }                   {SQLITE_MISUSE}
75do_test multiplex-1.10.5 { multiplex_set 32768 100 }               {SQLITE_MISUSE}
76do_test multiplex-1.11 { sqlite3_multiplex_shutdown }              {SQLITE_OK}
77
78
79#-------------------------------------------------------------------------
80# Some simple warm-body tests with a single database file in rollback
81# mode:
82#
83#   multiplex-2.1.*: Test simple writing to a multiplex file.
84#
85#   multiplex-2.2.*: More writing.
86#
87#   multiplex-2.3.*: Open and close a second db.
88#
89#   multiplex-2.4.*: Try to shutdown the multiplex system before closing the db
90#                file. Check that this fails and the multiplex system still works
91#                afterwards. Then close the database and successfully shut
92#                down the multiplex system.
93#
94#   multiplex-2.5.*: More reading/writing.
95#
96#   multiplex-2.6.*: More reading/writing with varying small chunk sizes, as
97#                well as varying journal mode.
98
99sqlite3_multiplex_initialize "" 1
100multiplex_set 32768 16
101
102do_test multiplex-2.1.2 {
103  sqlite3 db test.db
104  execsql {
105    PRAGMA page_size=1024;
106    PRAGMA auto_vacuum=OFF;
107    PRAGMA journal_mode=DELETE;
108  }
109  execsql {
110    CREATE TABLE t1(a, b);
111    INSERT INTO t1 VALUES(1, randomblob(1100));
112    INSERT INTO t1 VALUES(2, randomblob(1100));
113  }
114} {}
115do_test multiplex-2.1.3 { file size [multiplex_name test.db 0] } {4096}
116do_test multiplex-2.1.4 {
117  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
118} {}
119
120do_test multiplex-2.2.1 {
121  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
122} {}
123do_test multiplex-2.2.3 { file size [multiplex_name test.db 0] } {6144}
124
125do_test multiplex-2.3.1 {
126  sqlite3 db2 bak.db
127  db2 close
128} {}
129
130do_test multiplex-2.4.1 {
131  sqlite3_multiplex_shutdown
132} {SQLITE_MISUSE}
133do_test multiplex-2.4.2 {
134  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
135} {}
136do_test multiplex-2.4.4 { file size [multiplex_name test.db 0] } {7168}
137do_test multiplex-2.4.99 {
138  db close
139  sqlite3_multiplex_shutdown
140} {SQLITE_OK}
141
142
143do_test multiplex-2.5.1 {
144  multiplex_delete test.db
145  sqlite3_multiplex_initialize "" 1
146  multiplex_set 4096 16
147} {SQLITE_OK}
148
149do_test multiplex-2.5.2 {
150  sqlite3 db test.db
151  execsql {
152    PRAGMA page_size = 1024;
153    PRAGMA journal_mode = delete;
154    PRAGMA auto_vacuum = off;
155    CREATE TABLE t1(a PRIMARY KEY, b);
156  }
157} {delete}
158
159do_test multiplex-2.5.3 {
160  execsql {
161    INSERT INTO t1 VALUES(1, 'one');
162    INSERT INTO t1 VALUES(2, randomblob(4000));
163    INSERT INTO t1 VALUES(3, 'three');
164    INSERT INTO t1 VALUES(4, randomblob(4000));
165    INSERT INTO t1 VALUES(5, 'five')
166  }
167} {}
168
169do_test multiplex-2.5.4 {
170  db eval {SELECT * FROM t1 WHERE a=1}
171} {1 one}
172
173do_test multiplex-2.5.5 {
174  db eval {SELECT * FROM t1 WHERE a=3}
175} {3 three}
176
177do_test multiplex-2.5.6 {
178  db eval {SELECT * FROM t1 WHERE a=5}
179} {5 five}
180
181do_test multiplex-2.5.7 {
182  db eval {SELECT a,length(b) FROM t1 WHERE a=2}
183} {2 4000}
184
185do_test multiplex-2.5.8 {
186  db eval {SELECT a,length(b) FROM t1 WHERE a=4}
187} {4 4000}
188
189do_test multiplex-2.5.9 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
190do_test multiplex-2.5.10 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
191
192do_test multiplex-2.5.99 {
193  db close
194  sqlite3_multiplex_shutdown
195} {SQLITE_OK}
196
197
198set all_journal_modes {delete persist truncate memory off}
199foreach jmode $all_journal_modes {
200  for {set sz 151} {$sz<8000} {set sz [expr $sz+419]} {
201
202    do_test multiplex-2.6.1.$sz.$jmode {
203      multiplex_delete test.db
204      sqlite3_multiplex_initialize "" 1
205      multiplex_set $sz 32
206    } {SQLITE_OK}
207
208    do_test multiplex-2.6.2.$sz.$jmode {
209      sqlite3 db test.db
210      db eval {
211        PRAGMA page_size = 1024;
212        PRAGMA auto_vacuum = off;
213      }
214      db eval "PRAGMA journal_mode = $jmode;"
215    } $jmode
216
217    do_test multiplex-2.6.3.$sz.$jmode {
218      execsql {
219        CREATE TABLE t1(a PRIMARY KEY, b);
220        INSERT INTO t1 VALUES(1, 'one');
221        INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
222      }
223    } {}
224
225    do_test multiplex-2.6.4.$sz.$jmode {
226      db eval {SELECT b FROM t1 WHERE a=1}
227    } {one}
228
229    do_test multiplex-2.6.5.$sz.$jmode {
230      db eval {SELECT length(b) FROM t1 WHERE a=2}
231    } [list $g_chunk_size]
232
233    do_test multiplex-2.6.6.$sz.$jmode { file size [multiplex_name test.db 0] } [list $g_chunk_size]
234
235    do_test multiplex-2.6.99.$sz.$jmode {
236      db close
237      sqlite3_multiplex_shutdown
238    } {SQLITE_OK}
239
240  }
241}
242
243#-------------------------------------------------------------------------
244# Try some tests with more than one connection to a database file. Still
245# in rollback mode.
246#
247#   multiplex-3.1.*: Two connections to a single database file.
248#
249#   multiplex-3.2.*: Two connections to each of several database files (that
250#                are in the same multiplex group).
251#
252do_test multiplex-3.1.1 {
253  multiplex_delete test.db
254  sqlite3_multiplex_initialize "" 1
255  multiplex_set 32768 16
256} {SQLITE_OK}
257do_test multiplex-3.1.2 {
258  sqlite3 db test.db
259  execsql {
260    PRAGMA page_size = 1024;
261    PRAGMA journal_mode = delete;
262    PRAGMA auto_vacuum = off;
263    CREATE TABLE t1(a PRIMARY KEY, b);
264    INSERT INTO t1 VALUES(1, 'one');
265  }
266  file size [multiplex_name test.db 0]
267} {3072}
268do_test multiplex-3.1.3 {
269  sqlite3 db2 test.db
270  execsql { CREATE TABLE t2(a, b) } db2
271} {}
272do_test multiplex-3.1.4 {
273  execsql { CREATE TABLE t3(a, b) }
274} {}
275do_test multiplex-3.1.5 {
276  catchsql { CREATE TABLE t3(a, b) }
277} {1 {table t3 already exists}}
278do_test multiplex-3.1.6 {
279  db close
280  db2 close
281} {}
282
283do_test multiplex-3.2.1a {
284
285  multiplex_delete test.db
286  multiplex_delete test2.db
287
288  sqlite3 db1a test.db
289  sqlite3 db2a test2.db
290
291  foreach db {db1a db2a} {
292    execsql {
293      PRAGMA page_size = 1024;
294      PRAGMA journal_mode = delete;
295      PRAGMA auto_vacuum = off;
296      CREATE TABLE t1(a, b);
297    } $db
298  }
299
300  list [file size [multiplex_name test.db 0]] [file size [multiplex_name test2.db 0]]
301} {2048 2048}
302
303do_test multiplex-3.2.1b {
304  sqlite3 db1b test.db
305  sqlite3 db2b test2.db
306} {}
307
308do_test multiplex-3.2.2 { execsql { INSERT INTO t1 VALUES('x', 'y') } db1a } {}
309do_test multiplex-3.2.3 { execsql { INSERT INTO t1 VALUES('v', 'w') } db1b } {}
310do_test multiplex-3.2.4 { execsql { INSERT INTO t1 VALUES('t', 'u') } db2a } {}
311do_test multiplex-3.2.5 { execsql { INSERT INTO t1 VALUES('r', 's') } db2b } {}
312
313do_test multiplex-3.2.6 {
314  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
315} {}
316do_test multiplex-3.2.7 {
317  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
318} {}
319do_test multiplex-3.2.8 {
320  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
321} {}
322do_test multiplex-3.2.9 {
323  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
324} {}
325
326do_test multiplex-3.3.1 {
327  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
328  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
329  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
330  execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
331} {}
332
333do_test multiplex-3.2.X {
334  foreach db {db1a db2a db2b db1b} { catch { $db close } }
335} {}
336
337#-------------------------------------------------------------------------
338#
339
340sqlite3_multiplex_initialize "" 1
341multiplex_set 32768 16
342
343# Return a list of all currently defined multiplexs.
344proc multiplex_list {} {
345  set allq {}
346  foreach q [sqlite3_multiplex_dump] {
347    lappend allq [lindex $q 0]
348  }
349  return [lsort $allq]
350}
351
352do_test multiplex-4.1.6 {
353  multiplex_delete test2.db
354  sqlite3 db test2.db
355  db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
356  set res [multiplex_list]
357  list [regexp {test2.db} $res]
358} {1}
359do_test multiplex-4.1.6a {
360  sqlite3 db2 test2.db
361  db2 eval {SELECT * FROM t2}
362} {tab-t2}
363do_test multiplex-4.1.7 {
364  execsql {INSERT INTO t2 VALUES(zeroblob(200000))}
365} {}
366do_test multiplex-4.1.8 {
367  sqlite3 db2 test2.db
368  db2 eval {SELECT count(*) FROM t2}
369} {2}
370do_test multiplex-4.1.8a {
371   db2 eval { DELETE FROM t2 WHERE x = 'tab-t2' }
372} {}
373do_test multiplex-4.1.8b {
374  sqlite3 db2 test2.db
375  db2 eval {SELECT count(*) FROM t2}
376} {1}
377
378
379do_test multiplex-4.1.9 {
380  execsql {INSERT INTO t2 VALUES(zeroblob(200000))}
381} {}
382do_test multiplex-4.1.10 {
383  set res [multiplex_list]
384  list [regexp {test2.db} $res]
385} {1}
386do_test multiplex-4.1.11 {
387  db2 close
388  set res [multiplex_list]
389  list [regexp {test2.db} $res]
390} {1}
391do_test multiplex-4.1.12 {
392  db close
393  multiplex_list
394} {}
395
396
397#-------------------------------------------------------------------------
398# The following tests test that the multiplex VFS handles malloc and IO
399# errors.
400#
401
402sqlite3_multiplex_initialize "" 1
403multiplex_set 32768 16
404
405do_faultsim_test multiplex-5.1 -prep {
406  catch {db close}
407} -body {
408  sqlite3 db test2.db
409}
410do_faultsim_test multiplex-5.2 -prep {
411  catch {db close}
412} -body {
413  sqlite3 db test.db
414}
415
416catch { db close }
417multiplex_delete test.db
418multiplex_delete test2.db
419
420do_test multiplex-5.3.prep {
421  sqlite3 db test.db
422  execsql {
423    PRAGMA auto_vacuum = 1;
424    PRAGMA page_size = 1024;
425    CREATE TABLE t1(a, b);
426    INSERT INTO t1 VALUES(10, zeroblob(1200));
427  }
428  faultsim_save_and_close
429} {}
430do_faultsim_test multiplex-5.3 -prep {
431  faultsim_restore_and_reopen
432} -body {
433  execsql { DELETE FROM t1 }
434}
435
436do_test multiplex-5.4.1 {
437  catch { db close }
438  multiplex_delete test.db
439  file mkdir test.db
440  list [catch { sqlite3 db test.db } msg] $msg
441} {1 {unable to open database file}}
442catch { file delete test.db }
443
444do_faultsim_test multiplex-5.5 -prep {
445  catch { sqlite3_multiplex_shutdown }
446} -body {
447  sqlite3_multiplex_initialize "" 1
448  multiplex_set 32768 16
449}
450
451catch { sqlite3_multiplex_shutdown }
452finish_test
453