1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/thread003.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,194 @@
1.4 +# 2007 September 10
1.5 +#
1.6 +# The author disclaims copyright to this source code. In place of
1.7 +# a legal notice, here is a blessing:
1.8 +#
1.9 +# May you do good and not evil.
1.10 +# May you find forgiveness for yourself and forgive others.
1.11 +# May you share freely, never taking more than you give.
1.12 +#
1.13 +#***********************************************************************
1.14 +#
1.15 +# This file contains tests that attempt to break the pcache module
1.16 +# by bombarding it with simultaneous requests from multiple threads.
1.17 +#
1.18 +# $Id: thread003.test,v 1.4 2008/08/30 09:10:17 danielk1977 Exp $
1.19 +
1.20 +set testdir [file dirname $argv0]
1.21 +
1.22 +source $testdir/tester.tcl
1.23 +source $testdir/thread_common.tcl
1.24 +if {[info commands sqlthread] eq ""} {
1.25 + finish_test
1.26 + return
1.27 +}
1.28 +
1.29 +# Set up a couple of different databases full of pseudo-randomly
1.30 +# generated data.
1.31 +#
1.32 +do_test thread003.1.1 {
1.33 + execsql {
1.34 + BEGIN;
1.35 + CREATE TABLE t1(a, b, c);
1.36 + }
1.37 + for {set ii 0} {$ii < 5000} {incr ii} {
1.38 + execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
1.39 + }
1.40 + execsql {
1.41 + CREATE INDEX i1 ON t1(a, b);
1.42 + COMMIT;
1.43 + }
1.44 +} {}
1.45 +do_test thread003.1.2 {
1.46 + expr {([file size test.db] / 1024) > 2000}
1.47 +} {1}
1.48 +do_test thread003.1.3 {
1.49 + db close
1.50 + file delete -force test2.db
1.51 + sqlite3 db test2.db
1.52 +} {}
1.53 +do_test thread003.1.4 {
1.54 + execsql {
1.55 + BEGIN;
1.56 + CREATE TABLE t1(a, b, c);
1.57 + }
1.58 + for {set ii 0} {$ii < 5000} {incr ii} {
1.59 + execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
1.60 + }
1.61 + execsql {
1.62 + CREATE INDEX i1 ON t1(a, b);
1.63 + COMMIT;
1.64 + }
1.65 +} {}
1.66 +do_test thread003.1.5 {
1.67 + expr {([file size test.db] / 1024) > 2000}
1.68 +} {1}
1.69 +do_test thread003.1.6 {
1.70 + db close
1.71 +} {}
1.72 +
1.73 +
1.74 +# This test opens a connection on each of the large (>2MB) database files
1.75 +# created by the previous block. The connections do not share a cache.
1.76 +# Both "cache_size" parameters are set to 15, so there is a maximum of
1.77 +# 30 pages available globally.
1.78 +#
1.79 +# Then, in separate threads, the databases are randomly queried over and
1.80 +# over again. This will force the connections to recycle clean pages from
1.81 +# each other. If there is a thread-safety problem, a segfault or assertion
1.82 +# failure may eventually occur.
1.83 +#
1.84 +set nSecond 30
1.85 +puts "Starting thread003.2 (should run for ~$nSecond seconds)"
1.86 +do_test thread003.2 {
1.87 + foreach zFile {test.db test2.db} {
1.88 + set SCRIPT [format {
1.89 + set iEnd [expr {[clock_seconds] + %d}]
1.90 + set ::DB [sqlthread open %s]
1.91 +
1.92 + # Set the cache size to 15 pages per cache. 30 available globally.
1.93 + execsql { PRAGMA cache_size = 15 }
1.94 +
1.95 + while {[clock_seconds] < $iEnd} {
1.96 + set iQuery [expr {int(rand()*5000)}]
1.97 + execsql " SELECT * FROM t1 WHERE a = $iQuery "
1.98 + }
1.99 +
1.100 + sqlite3_close $::DB
1.101 + expr 1
1.102 + } $nSecond $zFile]
1.103 +
1.104 + unset -nocomplain finished($zFile)
1.105 + thread_spawn finished($zFile) $thread_procs $SCRIPT
1.106 + }
1.107 + foreach zFile {test.db test2.db} {
1.108 + if {![info exists finished($zFile)]} {
1.109 + vwait finished($zFile)
1.110 + }
1.111 + }
1.112 + expr 0
1.113 +} {0}
1.114 +
1.115 +# This test is the same as the test above, except that each thread also
1.116 +# writes to the database. This causes pages to be moved back and forth
1.117 +# between the caches internal dirty and clean lists, which is another
1.118 +# opportunity for a thread-related bug to present itself.
1.119 +#
1.120 +set nSecond 30
1.121 +puts "Starting thread003.3 (should run for ~$nSecond seconds)"
1.122 +do_test thread003.3 {
1.123 + foreach zFile {test.db test2.db} {
1.124 + set SCRIPT [format {
1.125 + set iStart [clock_seconds]
1.126 + set iEnd [expr {[clock_seconds] + %d}]
1.127 + set ::DB [sqlthread open %s]
1.128 +
1.129 + # Set the cache size to 15 pages per cache. 30 available globally.
1.130 + execsql { PRAGMA cache_size = 15 }
1.131 +
1.132 + while {[clock_seconds] < $iEnd} {
1.133 + set iQuery [expr {int(rand()*5000)}]
1.134 + execsql "SELECT * FROM t1 WHERE a = $iQuery"
1.135 + execsql "UPDATE t1 SET b = randomblob(200)
1.136 + WHERE a < $iQuery AND a > $iQuery + 20
1.137 + "
1.138 + }
1.139 +
1.140 + sqlite3_close $::DB
1.141 + expr 1
1.142 + } $nSecond $zFile]
1.143 +
1.144 + unset -nocomplain finished($zFile)
1.145 + thread_spawn finished($zFile) $thread_procs $SCRIPT
1.146 + }
1.147 + foreach zFile {test.db test2.db} {
1.148 + if {![info exists finished($zFile)]} {
1.149 + vwait finished($zFile)
1.150 + }
1.151 + }
1.152 + expr 0
1.153 +} {0}
1.154 +
1.155 +# In this test case, one thread is continually querying the database.
1.156 +# The other thread does not have a database connection, but calls
1.157 +# sqlite3_release_memory() over and over again.
1.158 +#
1.159 +set nSecond 30
1.160 +puts "Starting thread003.3 (should run for ~$nSecond seconds)"
1.161 +unset -nocomplain finished(1)
1.162 +unset -nocomplain finished(2)
1.163 +do_test thread003.4 {
1.164 + thread_spawn finished(1) $thread_procs [format {
1.165 + set iEnd [expr {[clock_seconds] + %d}]
1.166 + set ::DB [sqlthread open test.db]
1.167 +
1.168 + # Set the cache size to 15 pages per cache. 30 available globally.
1.169 + execsql { PRAGMA cache_size = 15 }
1.170 +
1.171 + while {[clock_seconds] < $iEnd} {
1.172 + set iQuery [expr {int(rand()*5000)}]
1.173 + execsql "SELECT * FROM t1 WHERE a = $iQuery"
1.174 + }
1.175 +
1.176 + sqlite3_close $::DB
1.177 + expr 1
1.178 + } $nSecond]
1.179 + thread_spawn finished(2) [format {
1.180 + set iEnd [expr {[clock_seconds] + %d}]
1.181 +
1.182 + while {[clock_seconds] < $iEnd} {
1.183 + sqlite3_release_memory 1000
1.184 + }
1.185 + } $nSecond]
1.186 +
1.187 + foreach ii {1 2} {
1.188 + if {![info exists finished($ii)]} {
1.189 + vwait finished($ii)
1.190 + }
1.191 + }
1.192 + expr 0
1.193 +} {0}
1.194 +
1.195 +finish_test
1.196 +
1.197 +