1# 2006 January 14 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# This file implements regression tests for SQLite library. The 12# focus of this script is multithreading behavior 13# 14# $Id: thread2.test,v 1.3 2008/10/07 15:25:49 drh Exp $ 15 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20ifcapable !mutex { 21 finish_test 22 return 23} 24 25 26# Skip this whole file if the thread testing code is not enabled 27# 28if {[llength [info command thread_step]]==0 || [sqlite3 -has-codec]} { 29 finish_test 30 return 31} 32if {![info exists threadsOverrideEachOthersLocks]} { 33 finish_test 34 return 35} 36 37# Create some data to work with 38# 39do_test thread1-1.1 { 40 execsql { 41 CREATE TABLE t1(a,b); 42 INSERT INTO t1 VALUES(1,'abcdefgh'); 43 INSERT INTO t1 SELECT a+1, b||b FROM t1; 44 INSERT INTO t1 SELECT a+2, b||b FROM t1; 45 INSERT INTO t1 SELECT a+4, b||b FROM t1; 46 SELECT count(*), max(length(b)) FROM t1; 47 } 48} {8 64} 49 50# Use the thread_swap command to move the database connections between 51# threads, then verify that they still work. 52# 53do_test thread2-1.2 { 54 db close 55 thread_create A test.db 56 thread_create B test.db 57 thread_swap A B 58 thread_compile A {SELECT a FROM t1 LIMIT 1} 59 thread_result A 60} {SQLITE_OK} 61do_test thread2-1.3 { 62 thread_step A 63 thread_result A 64} {SQLITE_ROW} 65do_test thread2-1.4 { 66 thread_argv A 0 67} {1} 68do_test thread2-1.5 { 69 thread_finalize A 70 thread_result A 71} {SQLITE_OK} 72do_test thread2-1.6 { 73 thread_compile B {SELECT a FROM t1 LIMIT 1} 74 thread_result B 75} {SQLITE_OK} 76do_test thread2-1.7 { 77 thread_step B 78 thread_result B 79} {SQLITE_ROW} 80do_test thread2-1.8 { 81 thread_argv B 0 82} {1} 83do_test thread2-1.9 { 84 thread_finalize B 85 thread_result B 86} {SQLITE_OK} 87 88# Swap them again. 89# 90do_test thread2-2.2 { 91 thread_swap A B 92 thread_compile A {SELECT a FROM t1 LIMIT 1} 93 thread_result A 94} {SQLITE_OK} 95do_test thread2-2.3 { 96 thread_step A 97 thread_result A 98} {SQLITE_ROW} 99do_test thread2-2.4 { 100 thread_argv A 0 101} {1} 102do_test thread2-2.5 { 103 thread_finalize A 104 thread_result A 105} {SQLITE_OK} 106do_test thread2-2.6 { 107 thread_compile B {SELECT a FROM t1 LIMIT 1} 108 thread_result B 109} {SQLITE_OK} 110do_test thread2-2.7 { 111 thread_step B 112 thread_result B 113} {SQLITE_ROW} 114do_test thread2-2.8 { 115 thread_argv B 0 116} {1} 117do_test thread2-2.9 { 118 thread_finalize B 119 thread_result B 120} {SQLITE_OK} 121thread_halt A 122thread_halt B 123 124# Save the original (correct) value of threadsOverrideEachOthersLocks 125# so that it can be restored. If this value is left set incorrectly, lots 126# of things will go wrong in future tests. 127# 128set orig_threadOverride $threadsOverrideEachOthersLocks 129 130# Pretend we are on a system (like RedHat9) were threads do not 131# override each others locks. 132# 133set threadsOverrideEachOthersLocks 0 134 135# Verify that we can move database connections between threads as 136# long as no locks are held. 137# 138do_test thread2-3.1 { 139 thread_create A test.db 140 set DB [thread_db_get A] 141 thread_halt A 142} {} 143do_test thread2-3.2 { 144 set STMT [sqlite3_prepare $DB {SELECT a FROM t1 LIMIT 1} -1 TAIL] 145 sqlite3_step $STMT 146} SQLITE_ROW 147do_test thread2-3.3 { 148 sqlite3_column_int $STMT 0 149} 1 150do_test thread2-3.4 { 151 sqlite3_finalize $STMT 152} SQLITE_OK 153do_test thread2-3.5 { 154 set STMT [sqlite3_prepare $DB {SELECT max(a) FROM t1} -1 TAIL] 155 sqlite3_step $STMT 156} SQLITE_ROW 157do_test thread2-3.6 { 158 sqlite3_column_int $STMT 0 159} 8 160do_test thread2-3.7 { 161 sqlite3_finalize $STMT 162} SQLITE_OK 163do_test thread2-3.8 { 164 sqlite3_close $DB 165} {SQLITE_OK} 166 167do_test thread2-3.10 { 168 thread_create A test.db 169 thread_compile A {SELECT a FROM t1 LIMIT 1} 170 thread_step A 171 thread_finalize A 172 set DB [thread_db_get A] 173 thread_halt A 174} {} 175do_test thread2-3.11 { 176 set STMT [sqlite3_prepare $DB {SELECT a FROM t1 LIMIT 1} -1 TAIL] 177 sqlite3_step $STMT 178} SQLITE_ROW 179do_test thread2-3.12 { 180 sqlite3_column_int $STMT 0 181} 1 182do_test thread2-3.13 { 183 sqlite3_finalize $STMT 184} SQLITE_OK 185do_test thread2-3.14 { 186 sqlite3_close $DB 187} SQLITE_OK 188 189do_test thread2-3.20 { 190 thread_create A test.db 191 thread_compile A {SELECT a FROM t1 LIMIT 3} 192 thread_step A 193 set STMT [thread_stmt_get A] 194 set DB [thread_db_get A] 195 thread_halt A 196} {} 197do_test thread2-3.21 { 198 sqlite3_step $STMT 199} SQLITE_ROW 200do_test thread2-3.22 { 201 sqlite3_column_int $STMT 0 202} 2 203do_test thread2-3.23 { 204 # The unlock fails here. But because we never check the return 205 # code from sqlite3OsUnlock (because we cannot do anything about it 206 # if it fails) we do not realize that an error has occurred. 207 sqlite3_finalize $STMT 208} SQLITE_OK 209do_test thread2-3.25 { 210 sqlite3_close $DB 211} SQLITE_OK 212 213do_test thread2-3.30 { 214 thread_create A test.db 215 thread_compile A {BEGIN} 216 thread_step A 217 thread_finalize A 218 thread_compile A {SELECT a FROM t1 LIMIT 1} 219 thread_step A 220 thread_finalize A 221 set DB [thread_db_get A] 222 thread_halt A 223} {} 224do_test thread2-3.31 { 225 set STMT [sqlite3_prepare $DB {INSERT INTO t1 VALUES(99,'error')} -1 TAIL] 226 sqlite3_step $STMT 227} SQLITE_ERROR 228do_test thread2-3.32 { 229 sqlite3_finalize $STMT 230} SQLITE_MISUSE 231do_test thread2-3.33 { 232 sqlite3_close $DB 233} SQLITE_OK 234 235# VERY important to set the override flag back to its true value. 236# 237set threadsOverrideEachOthersLocks $orig_threadOverride 238 239# Also important to halt the worker threads, which are using spin 240# locks and eating away CPU cycles. 241# 242thread_halt * 243finish_test 244