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