OLD | NEW |
| (Empty) |
1 # 2006 July 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 extension loading. | |
13 # | |
14 # $Id: loadext.test,v 1.17 2009/03/20 09:09:37 danielk1977 Exp $ | |
15 | |
16 set testdir [file dirname $argv0] | |
17 source $testdir/tester.tcl | |
18 | |
19 ifcapable !load_ext { | |
20 finish_test | |
21 return | |
22 } | |
23 | |
24 # The name of the test extension varies by operating system. | |
25 # | |
26 if {$::tcl_platform(platform) eq "windows"} { | |
27 set testextension ./testloadext.dll | |
28 } else { | |
29 set testextension ./libtestloadext.so | |
30 } | |
31 set gcc_shared "-shared -fPIC" | |
32 if {$::tcl_platform(os) eq "Darwin"} { | |
33 set gcc_shared -dynamiclib | |
34 } | |
35 | |
36 # The error messages tested by this file are operating system dependent | |
37 # (because they are returned by sqlite3OsDlError()). For now, they only | |
38 # work with UNIX (and probably only certain kinds of UNIX). | |
39 # | |
40 # When a shared-object cannot be opened because it does not exist, the | |
41 # format of the message returned is: | |
42 # | |
43 # [format $dlerror_nosuchfile <shared-object-name>] | |
44 # | |
45 # When a shared-object cannot be opened because it consists of the 4 | |
46 # characters "blah" only, we expect the error message to be: | |
47 # | |
48 # [format $dlerror_notadll <shared-object-name>] | |
49 # | |
50 # When a symbol cannot be found within an open shared-object, the error | |
51 # message should be: | |
52 # | |
53 # [format $dlerror_nosymbol <shared-object-name> <symbol-name>] | |
54 # | |
55 # The exact error messages are not important. The important bit is | |
56 # that SQLite is correctly copying the message from xDlError(). | |
57 # | |
58 set dlerror_nosuchfile \ | |
59 {%s: cannot open shared object file: No such file or directory} | |
60 set dlerror_notadll {%s: file too short} | |
61 set dlerror_nosymbol {%s: undefined symbol: %s} | |
62 | |
63 if {$::tcl_platform(os) eq "Darwin"} { | |
64 set dlerror_nosuchfile {dlopen(%s, 10): image not found} | |
65 set dlerror_notadll {dlopen(%1$s, 10): no suitable image found.*} | |
66 set dlerror_nosymbol {dlsym(XXX, %2$s): symbol not found} | |
67 } | |
68 | |
69 if {$::tcl_platform(platform) eq "windows"} { | |
70 set dlerror_nosuchfile {The specified module could not be found.*} | |
71 set dlerror_notadll {%%1 is not a valid Win32 application.*} | |
72 set dlerror_nosymbol {The specified procedure could not be found.*} | |
73 } | |
74 | |
75 # Make sure the test extension actually exists. If it does not | |
76 # exist, try to create it. If unable to create it, then skip this | |
77 # test file. | |
78 # | |
79 if {![file exists $testextension]} { | |
80 set srcdir [file dir $testdir]/src | |
81 set testextsrc $srcdir/test_loadext.c | |
82 | |
83 set cmdline [concat exec gcc $gcc_shared] | |
84 lappend cmdline -Wall -I$srcdir -I. -g $testextsrc -o $testextension | |
85 | |
86 if {[catch $cmdline msg]} { | |
87 puts "Skipping loadext tests: Test extension not built..." | |
88 puts $msg | |
89 finish_test | |
90 return | |
91 } | |
92 } | |
93 | |
94 # Test that loading the extension produces the expected results - adding | |
95 # the half() function to the specified database handle. | |
96 # | |
97 do_test loadext-1.1 { | |
98 catchsql { | |
99 SELECT half(1.0); | |
100 } | |
101 } {1 {no such function: half}} | |
102 do_test loadext-1.2 { | |
103 db enable_load_extension 1 | |
104 sqlite3_load_extension db $testextension testloadext_init | |
105 catchsql { | |
106 SELECT half(1.0); | |
107 } | |
108 } {0 0.5} | |
109 | |
110 # Test that a second database connection (db2) can load the extension also. | |
111 # | |
112 do_test loadext-1.3 { | |
113 sqlite3 db2 test.db | |
114 sqlite3_enable_load_extension db2 1 | |
115 catchsql { | |
116 SELECT half(1.0); | |
117 } db2 | |
118 } {1 {no such function: half}} | |
119 do_test loadext-1.4 { | |
120 sqlite3_load_extension db2 $testextension testloadext_init | |
121 catchsql { | |
122 SELECT half(1.0); | |
123 } db2 | |
124 } {0 0.5} | |
125 | |
126 # Close the first database connection. Then check that the second database | |
127 # can still use the half() function without a problem. | |
128 # | |
129 do_test loadext-1.5 { | |
130 db close | |
131 catchsql { | |
132 SELECT half(1.0); | |
133 } db2 | |
134 } {0 0.5} | |
135 | |
136 db2 close | |
137 sqlite3 db test.db | |
138 sqlite3_enable_load_extension db 1 | |
139 | |
140 # Try to load an extension for which the file does not exist. | |
141 # | |
142 do_test loadext-2.1 { | |
143 forcedelete ${testextension}xx | |
144 set rc [catch { | |
145 sqlite3_load_extension db "${testextension}xx" | |
146 } msg] | |
147 list $rc $msg | |
148 } /[list 1 [format $dlerror_nosuchfile ${testextension}xx.*]]/ | |
149 | |
150 # Try to load an extension for which the file is not a shared object | |
151 # | |
152 do_test loadext-2.2 { | |
153 set fd [open "./notasharedlib.so" w] | |
154 puts $fd blah | |
155 close $fd | |
156 set fd [open "./notasharedlib.dll" w] | |
157 puts $fd blah | |
158 close $fd | |
159 set rc [catch { | |
160 sqlite3_load_extension db "./notasharedlib" | |
161 } msg] | |
162 list $rc $msg | |
163 } /[list 1 [format $dlerror_notadll ./notasharedlib.*]]/ | |
164 | |
165 # Try to load an extension for which the file is present but the | |
166 # entry point is not. | |
167 # | |
168 do_test loadext-2.3 { | |
169 set rc [catch { | |
170 sqlite3_load_extension db $testextension icecream | |
171 } msg] | |
172 if {$::tcl_platform(os) eq "Darwin"} { | |
173 regsub {0x[1234567890abcdefABCDEF]*} $msg XXX msg | |
174 } | |
175 list $rc $msg | |
176 } /[list 1 [format $dlerror_nosymbol $testextension icecream]]/ | |
177 | |
178 # Try to load an extension for which the entry point fails (returns non-zero) | |
179 # | |
180 do_test loadext-2.4 { | |
181 set rc [catch { | |
182 sqlite3_load_extension db $testextension testbrokenext_init | |
183 } msg] | |
184 list $rc $msg | |
185 } {1 {error during initialization: broken!}} | |
186 | |
187 ############################################################################ | |
188 # Tests for the load_extension() SQL function | |
189 # | |
190 | |
191 db close | |
192 sqlite3 db test.db | |
193 sqlite3_enable_load_extension db 1 | |
194 do_test loadext-3.1 { | |
195 catchsql { | |
196 SELECT half(5); | |
197 } | |
198 } {1 {no such function: half}} | |
199 do_test loadext-3.2 { | |
200 set res [catchsql { | |
201 SELECT load_extension($::testextension) | |
202 }] | |
203 if {$::tcl_platform(os) eq "Darwin"} { | |
204 regsub {0x[1234567890abcdefABCDEF]*} $res XXX res | |
205 } | |
206 set res | |
207 } /[list 1 [format $dlerror_nosymbol $testextension sqlite3_.*_init]]/ | |
208 do_test loadext-3.3 { | |
209 catchsql { | |
210 SELECT load_extension($::testextension,'testloadext_init') | |
211 } | |
212 } {0 {{}}} | |
213 do_test loadext-3.4 { | |
214 catchsql { | |
215 SELECT half(5); | |
216 } | |
217 } {0 2.5} | |
218 do_test loadext-3.5 { | |
219 db eval { | |
220 SELECT sqlite3_status('MEMORY_USED') AS mused | |
221 } break | |
222 puts -nonewline " (memory_used=$mused) " | |
223 expr {$mused>0} | |
224 } {1} | |
225 do_test loadext-3.6 { | |
226 catchsql { | |
227 SELECT sqlite3_status('MEMORY_USED_X') AS mused | |
228 } | |
229 } {1 {unknown status property: MEMORY_USED_X}} | |
230 do_test loadext-3.7 { | |
231 catchsql { | |
232 SELECT sqlite3_status(4.53) AS mused | |
233 } | |
234 } {1 {unknown status type}} | |
235 do_test loadext-3.8 { | |
236 catchsql { | |
237 SELECT sqlite3_status(23) AS mused | |
238 } | |
239 } {1 {sqlite3_status(23,...) returns 21}} | |
240 | |
241 # Ticket #1863 | |
242 # Make sure the extension loading mechanism will not work unless it | |
243 # is explicitly enabled. | |
244 # | |
245 db close | |
246 sqlite3 db test.db | |
247 do_test loadext-4.1 { | |
248 catchsql { | |
249 SELECT load_extension($::testextension,'testloadext_init') | |
250 } | |
251 } {1 {not authorized}} | |
252 do_test loadext-4.2 { | |
253 sqlite3_enable_load_extension db 1 | |
254 catchsql { | |
255 SELECT load_extension($::testextension,'testloadext_init') | |
256 } | |
257 } {0 {{}}} | |
258 | |
259 do_test loadext-4.3 { | |
260 sqlite3_enable_load_extension db 0 | |
261 catchsql { | |
262 SELECT load_extension($::testextension,'testloadext_init') | |
263 } | |
264 } {1 {not authorized}} | |
265 | |
266 source $testdir/malloc_common.tcl | |
267 | |
268 | |
269 # Malloc failure in sqlite3_auto_extension and sqlite3_load_extension | |
270 # | |
271 do_malloc_test loadext-5 -tclprep { | |
272 sqlite3_reset_auto_extension | |
273 } -tclbody { | |
274 if {[autoinstall_test_functions]==7} {error "out of memory"} | |
275 } | |
276 | |
277 # On Windows, this malloc test must be skipped because the winDlOpen | |
278 # function itself can fail due to "out of memory" conditions. | |
279 # | |
280 if {$::tcl_platform(platform) ne "windows"} { | |
281 do_malloc_test loadext-6 -tclbody { | |
282 db enable_load_extension 1 | |
283 sqlite3_load_extension db $::testextension testloadext_init | |
284 } | |
285 } | |
286 | |
287 autoinstall_test_functions | |
288 | |
289 finish_test | |
OLD | NEW |