|
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 |
|
17 set testdir [file dirname $argv0] |
|
18 source $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. |
|
23 ifcapable memorymanage { |
|
24 finish_test |
|
25 return |
|
26 } |
|
27 |
|
28 |
|
29 # Skip this whole file if the thread testing code is not enabled |
|
30 # |
|
31 if {[llength [info command thread_step]]==0 || [sqlite3 -has-codec]} { |
|
32 finish_test |
|
33 return |
|
34 } |
|
35 if {![info exists threadsOverrideEachOthersLocks]} { |
|
36 finish_test |
|
37 return |
|
38 } |
|
39 |
|
40 # Create some data to work with |
|
41 # |
|
42 do_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 # |
|
56 do_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} |
|
64 do_test thread2-1.3 { |
|
65 thread_step A |
|
66 thread_result A |
|
67 } {SQLITE_ROW} |
|
68 do_test thread2-1.4 { |
|
69 thread_argv A 0 |
|
70 } {1} |
|
71 do_test thread2-1.5 { |
|
72 thread_finalize A |
|
73 thread_result A |
|
74 } {SQLITE_OK} |
|
75 do_test thread2-1.6 { |
|
76 thread_compile B {SELECT a FROM t1 LIMIT 1} |
|
77 thread_result B |
|
78 } {SQLITE_OK} |
|
79 do_test thread2-1.7 { |
|
80 thread_step B |
|
81 thread_result B |
|
82 } {SQLITE_ROW} |
|
83 do_test thread2-1.8 { |
|
84 thread_argv B 0 |
|
85 } {1} |
|
86 do_test thread2-1.9 { |
|
87 thread_finalize B |
|
88 thread_result B |
|
89 } {SQLITE_OK} |
|
90 |
|
91 # Swap them again. |
|
92 # |
|
93 do_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} |
|
98 do_test thread2-2.3 { |
|
99 thread_step A |
|
100 thread_result A |
|
101 } {SQLITE_ROW} |
|
102 do_test thread2-2.4 { |
|
103 thread_argv A 0 |
|
104 } {1} |
|
105 do_test thread2-2.5 { |
|
106 thread_finalize A |
|
107 thread_result A |
|
108 } {SQLITE_OK} |
|
109 do_test thread2-2.6 { |
|
110 thread_compile B {SELECT a FROM t1 LIMIT 1} |
|
111 thread_result B |
|
112 } {SQLITE_OK} |
|
113 do_test thread2-2.7 { |
|
114 thread_step B |
|
115 thread_result B |
|
116 } {SQLITE_ROW} |
|
117 do_test thread2-2.8 { |
|
118 thread_argv B 0 |
|
119 } {1} |
|
120 do_test thread2-2.9 { |
|
121 thread_finalize B |
|
122 thread_result B |
|
123 } {SQLITE_OK} |
|
124 thread_halt A |
|
125 thread_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 # |
|
131 set orig_threadOverride $threadsOverrideEachOthersLocks |
|
132 |
|
133 # Pretend we are on a system (like RedHat9) were threads do not |
|
134 # override each others locks. |
|
135 # |
|
136 set threadsOverrideEachOthersLocks 0 |
|
137 |
|
138 # Verify that we can move database connections between threads as |
|
139 # long as no locks are held. |
|
140 # |
|
141 do_test thread2-3.1 { |
|
142 thread_create A test.db |
|
143 set DB [thread_db_get A] |
|
144 thread_halt A |
|
145 } {} |
|
146 do_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 |
|
150 do_test thread2-3.3 { |
|
151 sqlite3_column_int $STMT 0 |
|
152 } 1 |
|
153 do_test thread2-3.4 { |
|
154 sqlite3_finalize $STMT |
|
155 } SQLITE_OK |
|
156 do_test thread2-3.5 { |
|
157 set STMT [sqlite3_prepare $DB {SELECT max(a) FROM t1} -1 TAIL] |
|
158 sqlite3_step $STMT |
|
159 } SQLITE_ROW |
|
160 do_test thread2-3.6 { |
|
161 sqlite3_column_int $STMT 0 |
|
162 } 8 |
|
163 do_test thread2-3.7 { |
|
164 sqlite3_finalize $STMT |
|
165 } SQLITE_OK |
|
166 do_test thread2-3.8 { |
|
167 sqlite3_close $DB |
|
168 } {SQLITE_OK} |
|
169 |
|
170 do_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 } {} |
|
178 do_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 |
|
182 do_test thread2-3.12 { |
|
183 sqlite3_column_int $STMT 0 |
|
184 } 1 |
|
185 do_test thread2-3.13 { |
|
186 sqlite3_finalize $STMT |
|
187 } SQLITE_OK |
|
188 do_test thread2-3.14 { |
|
189 sqlite3_close $DB |
|
190 } SQLITE_OK |
|
191 |
|
192 do_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 } {} |
|
200 do_test thread2-3.21 { |
|
201 sqlite3_step $STMT |
|
202 } SQLITE_ROW |
|
203 do_test thread2-3.22 { |
|
204 sqlite3_column_int $STMT 0 |
|
205 } 2 |
|
206 do_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 |
|
212 do_test thread2-3.25 { |
|
213 sqlite3_close $DB |
|
214 } SQLITE_OK |
|
215 |
|
216 do_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 } {} |
|
227 do_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 |
|
231 do_test thread2-3.32 { |
|
232 sqlite3_finalize $STMT |
|
233 } SQLITE_MISUSE |
|
234 do_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 # |
|
240 set threadsOverrideEachOthersLocks $orig_threadOverride |
|
241 |
|
242 # Also important to halt the worker threads, which are using spin |
|
243 # locks and eating away CPU cycles. |
|
244 # |
|
245 thread_halt * |
|
246 finish_test |