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