Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / lang / sql / sqlite / test / thread003.test
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 key ""
84       if {[sqlite -has-codec]} {
85         set key "xyzzy"
86       }
87       set ::DB [sqlthread open %s $key]
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 key ""
125       if {[sqlite -has-codec]} {
126         set key "xyzzy"
127       }
128       set ::DB [sqlthread open %s $key]
129   
130       # Set the cache size to 15 pages per cache. 30 available globally.
131       execsql { PRAGMA cache_size = 15 }
132   
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
138         "
139       }
140   
141       sqlite3_close $::DB
142       expr 1
143     } $nSecond $zFile]
144   
145     unset -nocomplain finished($zFile)
146     thread_spawn finished($zFile) $thread_procs $SCRIPT
147   }
148   foreach zFile {test.db test2.db} {
149     if {![info exists finished($zFile)]} {
150       vwait finished($zFile)
151     }
152   }
153   expr 0
154 } {0}
155
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.
159 #
160 set nSecond 30
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}]
167     set key ""
168     if {[sqlite -has-codec]} {
169       set key "xyzzy"
170     }
171     set ::DB [sqlthread open test.db $key]
172
173     # Set the cache size to 15 pages per cache. 30 available globally.
174     execsql { PRAGMA cache_size = 15 }
175
176     while {[clock_seconds] < $iEnd} {
177       set iQuery [expr {int(rand()*5000)}]
178       execsql "SELECT * FROM t1 WHERE a = $iQuery"
179     }
180
181     sqlite3_close $::DB
182     expr 1
183   } $nSecond] 
184   thread_spawn finished(2) [format {
185     set iEnd [expr {[clock_seconds] + %d}]
186
187     while {[clock_seconds] < $iEnd} {
188       sqlite3_release_memory 1000
189     }
190   } $nSecond]
191   
192   foreach ii {1 2} {
193     if {![info exists finished($ii)]} {
194       vwait finished($ii)
195     }
196   }
197   expr 0
198 } {0}
199
200 set sqlite_open_file_count 0
201 finish_test