|
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.4 2008/08/30 09:10:17 danielk1977 Exp $ |
|
16 |
|
17 set testdir [file dirname $argv0] |
|
18 |
|
19 source $testdir/tester.tcl |
|
20 source $testdir/thread_common.tcl |
|
21 if {[info commands sqlthread] eq ""} { |
|
22 finish_test |
|
23 return |
|
24 } |
|
25 |
|
26 # Set up a couple of different databases full of pseudo-randomly |
|
27 # generated data. |
|
28 # |
|
29 do_test thread003.1.1 { |
|
30 execsql { |
|
31 BEGIN; |
|
32 CREATE TABLE t1(a, b, c); |
|
33 } |
|
34 for {set ii 0} {$ii < 5000} {incr ii} { |
|
35 execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))} |
|
36 } |
|
37 execsql { |
|
38 CREATE INDEX i1 ON t1(a, b); |
|
39 COMMIT; |
|
40 } |
|
41 } {} |
|
42 do_test thread003.1.2 { |
|
43 expr {([file size test.db] / 1024) > 2000} |
|
44 } {1} |
|
45 do_test thread003.1.3 { |
|
46 db close |
|
47 file delete -force test2.db |
|
48 sqlite3 db test2.db |
|
49 } {} |
|
50 do_test thread003.1.4 { |
|
51 execsql { |
|
52 BEGIN; |
|
53 CREATE TABLE t1(a, b, c); |
|
54 } |
|
55 for {set ii 0} {$ii < 5000} {incr ii} { |
|
56 execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))} |
|
57 } |
|
58 execsql { |
|
59 CREATE INDEX i1 ON t1(a, b); |
|
60 COMMIT; |
|
61 } |
|
62 } {} |
|
63 do_test thread003.1.5 { |
|
64 expr {([file size test.db] / 1024) > 2000} |
|
65 } {1} |
|
66 do_test thread003.1.6 { |
|
67 db close |
|
68 } {} |
|
69 |
|
70 |
|
71 # This test opens a connection on each of the large (>2MB) database files |
|
72 # created by the previous block. The connections do not share a cache. |
|
73 # Both "cache_size" parameters are set to 15, so there is a maximum of |
|
74 # 30 pages available globally. |
|
75 # |
|
76 # Then, in separate threads, the databases are randomly queried over and |
|
77 # over again. This will force the connections to recycle clean pages from |
|
78 # each other. If there is a thread-safety problem, a segfault or assertion |
|
79 # failure may eventually occur. |
|
80 # |
|
81 set nSecond 30 |
|
82 puts "Starting thread003.2 (should run for ~$nSecond seconds)" |
|
83 do_test thread003.2 { |
|
84 foreach zFile {test.db test2.db} { |
|
85 set SCRIPT [format { |
|
86 set iEnd [expr {[clock_seconds] + %d}] |
|
87 set ::DB [sqlthread open %s] |
|
88 |
|
89 # Set the cache size to 15 pages per cache. 30 available globally. |
|
90 execsql { PRAGMA cache_size = 15 } |
|
91 |
|
92 while {[clock_seconds] < $iEnd} { |
|
93 set iQuery [expr {int(rand()*5000)}] |
|
94 execsql " SELECT * FROM t1 WHERE a = $iQuery " |
|
95 } |
|
96 |
|
97 sqlite3_close $::DB |
|
98 expr 1 |
|
99 } $nSecond $zFile] |
|
100 |
|
101 unset -nocomplain finished($zFile) |
|
102 thread_spawn finished($zFile) $thread_procs $SCRIPT |
|
103 } |
|
104 foreach zFile {test.db test2.db} { |
|
105 if {![info exists finished($zFile)]} { |
|
106 vwait finished($zFile) |
|
107 } |
|
108 } |
|
109 expr 0 |
|
110 } {0} |
|
111 |
|
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. |
|
116 # |
|
117 set nSecond 30 |
|
118 puts "Starting thread003.3 (should run for ~$nSecond seconds)" |
|
119 do_test thread003.3 { |
|
120 foreach zFile {test.db test2.db} { |
|
121 set SCRIPT [format { |
|
122 set iStart [clock_seconds] |
|
123 set iEnd [expr {[clock_seconds] + %d}] |
|
124 set ::DB [sqlthread open %s] |
|
125 |
|
126 # Set the cache size to 15 pages per cache. 30 available globally. |
|
127 execsql { PRAGMA cache_size = 15 } |
|
128 |
|
129 while {[clock_seconds] < $iEnd} { |
|
130 set iQuery [expr {int(rand()*5000)}] |
|
131 execsql "SELECT * FROM t1 WHERE a = $iQuery" |
|
132 execsql "UPDATE t1 SET b = randomblob(200) |
|
133 WHERE a < $iQuery AND a > $iQuery + 20 |
|
134 " |
|
135 } |
|
136 |
|
137 sqlite3_close $::DB |
|
138 expr 1 |
|
139 } $nSecond $zFile] |
|
140 |
|
141 unset -nocomplain finished($zFile) |
|
142 thread_spawn finished($zFile) $thread_procs $SCRIPT |
|
143 } |
|
144 foreach zFile {test.db test2.db} { |
|
145 if {![info exists finished($zFile)]} { |
|
146 vwait finished($zFile) |
|
147 } |
|
148 } |
|
149 expr 0 |
|
150 } {0} |
|
151 |
|
152 # In this test case, one thread is continually querying the database. |
|
153 # The other thread does not have a database connection, but calls |
|
154 # sqlite3_release_memory() over and over again. |
|
155 # |
|
156 set nSecond 30 |
|
157 puts "Starting thread003.3 (should run for ~$nSecond seconds)" |
|
158 unset -nocomplain finished(1) |
|
159 unset -nocomplain finished(2) |
|
160 do_test thread003.4 { |
|
161 thread_spawn finished(1) $thread_procs [format { |
|
162 set iEnd [expr {[clock_seconds] + %d}] |
|
163 set ::DB [sqlthread open test.db] |
|
164 |
|
165 # Set the cache size to 15 pages per cache. 30 available globally. |
|
166 execsql { PRAGMA cache_size = 15 } |
|
167 |
|
168 while {[clock_seconds] < $iEnd} { |
|
169 set iQuery [expr {int(rand()*5000)}] |
|
170 execsql "SELECT * FROM t1 WHERE a = $iQuery" |
|
171 } |
|
172 |
|
173 sqlite3_close $::DB |
|
174 expr 1 |
|
175 } $nSecond] |
|
176 thread_spawn finished(2) [format { |
|
177 set iEnd [expr {[clock_seconds] + %d}] |
|
178 |
|
179 while {[clock_seconds] < $iEnd} { |
|
180 sqlite3_release_memory 1000 |
|
181 } |
|
182 } $nSecond] |
|
183 |
|
184 foreach ii {1 2} { |
|
185 if {![info exists finished($ii)]} { |
|
186 vwait finished($ii) |
|
187 } |
|
188 } |
|
189 expr 0 |
|
190 } {0} |
|
191 |
|
192 finish_test |
|
193 |
|
194 |