blob: 8c7440c82ee6f3b4abf749bd054b3cbc2d5a5447 [file] [log] [blame]
danielk197751d2d032008-08-28 08:31:48 +00001# 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#
danielk19776d961002009-03-26 14:48:07 +000015# $Id: thread003.test,v 1.8 2009/03/26 14:48:07 danielk1977 Exp $
danielk197751d2d032008-08-28 08:31:48 +000016
17set testdir [file dirname $argv0]
18
19source $testdir/tester.tcl
danielk19776d961002009-03-26 14:48:07 +000020if {[run_thread_tests]==0} { finish_test ; return }
danielk197751d2d032008-08-28 08:31:48 +000021
22# Set up a couple of different databases full of pseudo-randomly
23# generated data.
24#
25do_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} {}
38do_test thread003.1.2 {
39 expr {([file size test.db] / 1024) > 2000}
40} {1}
41do_test thread003.1.3 {
42 db close
mistachkinfda06be2011-08-02 00:57:34 +000043 forcedelete test2.db
danielk197751d2d032008-08-28 08:31:48 +000044 sqlite3 db test2.db
45} {}
46do_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} {}
59do_test thread003.1.5 {
60 expr {([file size test.db] / 1024) > 2000}
61} {1}
62do_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#
77set nSecond 30
78puts "Starting thread003.2 (should run for ~$nSecond seconds)"
79do_test thread003.2 {
80 foreach zFile {test.db test2.db} {
81 set SCRIPT [format {
danielk197781fa1932008-08-28 13:55:10 +000082 set iEnd [expr {[clock_seconds] + %d}]
drh0ee469c2011-08-30 19:52:32 +000083 set ::DB [sqlthread open %s xyzzy]
danielk197751d2d032008-08-28 08:31:48 +000084
85 # Set the cache size to 15 pages per cache. 30 available globally.
86 execsql { PRAGMA cache_size = 15 }
87
danielk197781fa1932008-08-28 13:55:10 +000088 while {[clock_seconds] < $iEnd} {
danielk197751d2d032008-08-28 08:31:48 +000089 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
danielk1977f599a192008-08-28 10:21:16 +0000108# 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#
113set nSecond 30
114puts "Starting thread003.3 (should run for ~$nSecond seconds)"
115do_test thread003.3 {
116 foreach zFile {test.db test2.db} {
117 set SCRIPT [format {
danielk197781fa1932008-08-28 13:55:10 +0000118 set iStart [clock_seconds]
119 set iEnd [expr {[clock_seconds] + %d}]
drh0ee469c2011-08-30 19:52:32 +0000120 set ::DB [sqlthread open %s xyzzy]
danielk1977f599a192008-08-28 10:21:16 +0000121
122 # Set the cache size to 15 pages per cache. 30 available globally.
123 execsql { PRAGMA cache_size = 15 }
124
danielk197781fa1932008-08-28 13:55:10 +0000125 while {[clock_seconds] < $iEnd} {
danielk1977f599a192008-08-28 10:21:16 +0000126 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#
152set nSecond 30
danielk197720736d82009-03-12 14:43:27 +0000153puts "Starting thread003.4 (should run for ~$nSecond seconds)"
danielk19773dbb0572008-08-30 09:10:16 +0000154unset -nocomplain finished(1)
155unset -nocomplain finished(2)
danielk1977f599a192008-08-28 10:21:16 +0000156do_test thread003.4 {
157 thread_spawn finished(1) $thread_procs [format {
danielk197781fa1932008-08-28 13:55:10 +0000158 set iEnd [expr {[clock_seconds] + %d}]
drh0ee469c2011-08-30 19:52:32 +0000159 set ::DB [sqlthread open test.db xyzzy]
danielk1977f599a192008-08-28 10:21:16 +0000160
161 # Set the cache size to 15 pages per cache. 30 available globally.
162 execsql { PRAGMA cache_size = 15 }
163
danielk197781fa1932008-08-28 13:55:10 +0000164 while {[clock_seconds] < $iEnd} {
danielk1977f599a192008-08-28 10:21:16 +0000165 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 {
danielk197781fa1932008-08-28 13:55:10 +0000173 set iEnd [expr {[clock_seconds] + %d}]
danielk1977f599a192008-08-28 10:21:16 +0000174
danielk197781fa1932008-08-28 13:55:10 +0000175 while {[clock_seconds] < $iEnd} {
danielk1977f599a192008-08-28 10:21:16 +0000176 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
drha32e0d02009-02-12 17:06:41 +0000188set sqlite_open_file_count 0
danielk197751d2d032008-08-28 08:31:48 +0000189finish_test