| OLD | NEW | 
 | (Empty) | 
|    1 # 2007 September 10 |  | 
|    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 #   This file contains tests that attempt to break the pcache module |  | 
|   13 #   by bombarding it with simultaneous requests from multiple threads. |  | 
|   14 #      |  | 
|   15 # $Id: thread003.test,v 1.8 2009/03/26 14:48:07 danielk1977 Exp $ |  | 
|   16  |  | 
|   17 set testdir [file dirname $argv0] |  | 
|   18  |  | 
|   19 source $testdir/tester.tcl |  | 
|   20 if {[run_thread_tests]==0} { finish_test ; return } |  | 
|   21  |  | 
|   22 # Set up a couple of different databases full of pseudo-randomly  |  | 
|   23 # generated data. |  | 
|   24 # |  | 
|   25 do_test thread003.1.1 { |  | 
|   26   execsql { |  | 
|   27     BEGIN; |  | 
|   28     CREATE TABLE t1(a, b, c); |  | 
|   29   } |  | 
|   30   for {set ii 0} {$ii < 5000} {incr ii} { |  | 
|   31     execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))} |  | 
|   32   } |  | 
|   33   execsql {  |  | 
|   34     CREATE INDEX i1 ON t1(a, b);  |  | 
|   35     COMMIT; |  | 
|   36   } |  | 
|   37 } {} |  | 
|   38 do_test thread003.1.2 { |  | 
|   39   expr {([file size test.db] / 1024) > 2000} |  | 
|   40 } {1} |  | 
|   41 do_test thread003.1.3 { |  | 
|   42   db close |  | 
|   43   file delete -force test2.db |  | 
|   44   sqlite3 db test2.db |  | 
|   45 } {} |  | 
|   46 do_test thread003.1.4 { |  | 
|   47   execsql { |  | 
|   48     BEGIN; |  | 
|   49     CREATE TABLE t1(a, b, c); |  | 
|   50   } |  | 
|   51   for {set ii 0} {$ii < 5000} {incr ii} { |  | 
|   52     execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))} |  | 
|   53   } |  | 
|   54   execsql {  |  | 
|   55     CREATE INDEX i1 ON t1(a, b);  |  | 
|   56     COMMIT; |  | 
|   57   } |  | 
|   58 } {} |  | 
|   59 do_test thread003.1.5 { |  | 
|   60   expr {([file size test.db] / 1024) > 2000} |  | 
|   61 } {1} |  | 
|   62 do_test thread003.1.6 { |  | 
|   63   db close |  | 
|   64 } {} |  | 
|   65  |  | 
|   66  |  | 
|   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. |  | 
|   71 # |  | 
|   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. |  | 
|   76 # |  | 
|   77 set nSecond 30 |  | 
|   78 puts "Starting thread003.2 (should run for ~$nSecond seconds)" |  | 
|   79 do_test thread003.2 { |  | 
|   80   foreach zFile {test.db test2.db} { |  | 
|   81     set SCRIPT [format { |  | 
|   82       set iEnd [expr {[clock_seconds] + %d}] |  | 
|   83       set ::DB [sqlthread open %s] |  | 
|   84    |  | 
|   85       # Set the cache size to 15 pages per cache. 30 available globally. |  | 
|   86       execsql { PRAGMA cache_size = 15 } |  | 
|   87    |  | 
|   88       while {[clock_seconds] < $iEnd} { |  | 
|   89         set iQuery [expr {int(rand()*5000)}] |  | 
|   90         execsql " SELECT * FROM t1 WHERE a = $iQuery " |  | 
|   91       } |  | 
|   92    |  | 
|   93       sqlite3_close $::DB |  | 
|   94       expr 1 |  | 
|   95     } $nSecond $zFile] |  | 
|   96    |  | 
|   97     unset -nocomplain finished($zFile) |  | 
|   98     thread_spawn finished($zFile) $thread_procs $SCRIPT |  | 
|   99   } |  | 
|  100   foreach zFile {test.db test2.db} { |  | 
|  101     if {![info exists finished($zFile)]} { |  | 
|  102       vwait finished($zFile) |  | 
|  103     } |  | 
|  104   } |  | 
|  105   expr 0 |  | 
|  106 } {0} |  | 
|  107  |  | 
|  108 # This test is the same as the test above, except that each thread also |  | 
|  109 # writes to the database. This causes pages to be moved back and forth  |  | 
|  110 # between the caches internal dirty and clean lists, which is another |  | 
|  111 # opportunity for a thread-related bug to present itself. |  | 
|  112 # |  | 
|  113 set nSecond 30 |  | 
|  114 puts "Starting thread003.3 (should run for ~$nSecond seconds)" |  | 
|  115 do_test thread003.3 { |  | 
|  116   foreach zFile {test.db test2.db} { |  | 
|  117     set SCRIPT [format { |  | 
|  118       set iStart [clock_seconds] |  | 
|  119       set iEnd [expr {[clock_seconds] + %d}] |  | 
|  120       set ::DB [sqlthread open %s] |  | 
|  121    |  | 
|  122       # Set the cache size to 15 pages per cache. 30 available globally. |  | 
|  123       execsql { PRAGMA cache_size = 15 } |  | 
|  124    |  | 
|  125       while {[clock_seconds] < $iEnd} { |  | 
|  126         set iQuery [expr {int(rand()*5000)}] |  | 
|  127         execsql "SELECT * FROM t1 WHERE a = $iQuery" |  | 
|  128         execsql "UPDATE t1 SET b = randomblob(200)  |  | 
|  129                  WHERE a < $iQuery AND a > $iQuery + 20 |  | 
|  130         " |  | 
|  131       } |  | 
|  132    |  | 
|  133       sqlite3_close $::DB |  | 
|  134       expr 1 |  | 
|  135     } $nSecond $zFile] |  | 
|  136    |  | 
|  137     unset -nocomplain finished($zFile) |  | 
|  138     thread_spawn finished($zFile) $thread_procs $SCRIPT |  | 
|  139   } |  | 
|  140   foreach zFile {test.db test2.db} { |  | 
|  141     if {![info exists finished($zFile)]} { |  | 
|  142       vwait finished($zFile) |  | 
|  143     } |  | 
|  144   } |  | 
|  145   expr 0 |  | 
|  146 } {0} |  | 
|  147  |  | 
|  148 # In this test case, one thread is continually querying the database. |  | 
|  149 # The other thread does not have a database connection, but calls |  | 
|  150 # sqlite3_release_memory() over and over again. |  | 
|  151 # |  | 
|  152 set nSecond 30 |  | 
|  153 puts "Starting thread003.4 (should run for ~$nSecond seconds)" |  | 
|  154 unset -nocomplain finished(1) |  | 
|  155 unset -nocomplain finished(2) |  | 
|  156 do_test thread003.4 { |  | 
|  157   thread_spawn finished(1) $thread_procs [format { |  | 
|  158     set iEnd [expr {[clock_seconds] + %d}] |  | 
|  159     set ::DB [sqlthread open test.db] |  | 
|  160  |  | 
|  161     # Set the cache size to 15 pages per cache. 30 available globally. |  | 
|  162     execsql { PRAGMA cache_size = 15 } |  | 
|  163  |  | 
|  164     while {[clock_seconds] < $iEnd} { |  | 
|  165       set iQuery [expr {int(rand()*5000)}] |  | 
|  166       execsql "SELECT * FROM t1 WHERE a = $iQuery" |  | 
|  167     } |  | 
|  168  |  | 
|  169     sqlite3_close $::DB |  | 
|  170     expr 1 |  | 
|  171   } $nSecond]  |  | 
|  172   thread_spawn finished(2) [format { |  | 
|  173     set iEnd [expr {[clock_seconds] + %d}] |  | 
|  174  |  | 
|  175     while {[clock_seconds] < $iEnd} { |  | 
|  176       sqlite3_release_memory 1000 |  | 
|  177     } |  | 
|  178   } $nSecond] |  | 
|  179    |  | 
|  180   foreach ii {1 2} { |  | 
|  181     if {![info exists finished($ii)]} { |  | 
|  182       vwait finished($ii) |  | 
|  183     } |  | 
|  184   } |  | 
|  185   expr 0 |  | 
|  186 } {0} |  | 
|  187  |  | 
|  188 set sqlite_open_file_count 0 |  | 
|  189 finish_test |  | 
| OLD | NEW |