3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
12 # This file contains tests that attempt to break the pcache module
13 # by bombarding it with simultaneous requests from multiple threads.
15 # $Id: thread003.test,v 1.8 2009/03/26 14:48:07 danielk1977 Exp $
17 set testdir [file dirname $argv0]
19 source $testdir/tester.tcl
20 if {[run_thread_tests]==0} { finish_test ; return }
22 # Set up a couple of different databases full of pseudo-randomly
25 do_test thread003.1.1 {
28 CREATE TABLE t1(a, b, c);
30 for {set ii 0} {$ii < 5000} {incr ii} {
31 execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
34 CREATE INDEX i1 ON t1(a, b);
38 do_test thread003.1.2 {
39 expr {([file size test.db] / 1024) > 2000}
41 do_test thread003.1.3 {
43 file delete -force test2.db
46 do_test thread003.1.4 {
49 CREATE TABLE t1(a, b, c);
51 for {set ii 0} {$ii < 5000} {incr ii} {
52 execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
55 CREATE INDEX i1 ON t1(a, b);
59 do_test thread003.1.5 {
60 expr {([file size test.db] / 1024) > 2000}
62 do_test thread003.1.6 {
67 # This test opens a connection on each of the large (>2MB) database files
68 # created by the previous block. The connections do not share a cache.
69 # Both "cache_size" parameters are set to 15, so there is a maximum of
70 # 30 pages available globally.
72 # Then, in separate threads, the databases are randomly queried over and
73 # over again. This will force the connections to recycle clean pages from
74 # each other. If there is a thread-safety problem, a segfault or assertion
75 # failure may eventually occur.
78 puts "Starting thread003.2 (should run for ~$nSecond seconds)"
80 foreach zFile {test.db test2.db} {
82 set iEnd [expr {[clock_seconds] + %d}]
84 if {[sqlite -has-codec]} {
87 set ::DB [sqlthread open %s $key]
89 # Set the cache size to 15 pages per cache. 30 available globally.
90 execsql { PRAGMA cache_size = 15 }
92 while {[clock_seconds] < $iEnd} {
93 set iQuery [expr {int(rand()*5000)}]
94 execsql " SELECT * FROM t1 WHERE a = $iQuery "
101 unset -nocomplain finished($zFile)
102 thread_spawn finished($zFile) $thread_procs $SCRIPT
104 foreach zFile {test.db test2.db} {
105 if {![info exists finished($zFile)]} {
106 vwait finished($zFile)
112 # This test is the same as the test above, except that each thread also
113 # writes to the database. This causes pages to be moved back and forth
114 # between the caches internal dirty and clean lists, which is another
115 # opportunity for a thread-related bug to present itself.
118 puts "Starting thread003.3 (should run for ~$nSecond seconds)"
119 do_test thread003.3 {
120 foreach zFile {test.db test2.db} {
122 set iStart [clock_seconds]
123 set iEnd [expr {[clock_seconds] + %d}]
125 if {[sqlite -has-codec]} {
128 set ::DB [sqlthread open %s $key]
130 # Set the cache size to 15 pages per cache. 30 available globally.
131 execsql { PRAGMA cache_size = 15 }
133 while {[clock_seconds] < $iEnd} {
134 set iQuery [expr {int(rand()*5000)}]
135 execsql "SELECT * FROM t1 WHERE a = $iQuery"
136 execsql "UPDATE t1 SET b = randomblob(200)
137 WHERE a < $iQuery AND a > $iQuery + 20
145 unset -nocomplain finished($zFile)
146 thread_spawn finished($zFile) $thread_procs $SCRIPT
148 foreach zFile {test.db test2.db} {
149 if {![info exists finished($zFile)]} {
150 vwait finished($zFile)
156 # In this test case, one thread is continually querying the database.
157 # The other thread does not have a database connection, but calls
158 # sqlite3_release_memory() over and over again.
161 puts "Starting thread003.4 (should run for ~$nSecond seconds)"
162 unset -nocomplain finished(1)
163 unset -nocomplain finished(2)
164 do_test thread003.4 {
165 thread_spawn finished(1) $thread_procs [format {
166 set iEnd [expr {[clock_seconds] + %d}]
168 if {[sqlite -has-codec]} {
171 set ::DB [sqlthread open test.db $key]
173 # Set the cache size to 15 pages per cache. 30 available globally.
174 execsql { PRAGMA cache_size = 15 }
176 while {[clock_seconds] < $iEnd} {
177 set iQuery [expr {int(rand()*5000)}]
178 execsql "SELECT * FROM t1 WHERE a = $iQuery"
184 thread_spawn finished(2) [format {
185 set iEnd [expr {[clock_seconds] + %d}]
187 while {[clock_seconds] < $iEnd} {
188 sqlite3_release_memory 1000
193 if {![info exists finished($ii)]} {
200 set sqlite_open_file_count 0