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