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 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18 19ifcapable !load_ext { 20 finish_test 21 return 22} 23 24# The name of the test extension varies by operating system. 25# 26if {$::tcl_platform(platform) eq "windows"} { 27 set testextension ./testloadext.dll 28} else { 29 set testextension ./libtestloadext.so 30} 31set gcc_shared "-shared -fPIC" 32if {$::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# 58set dlerror_nosuchfile \ 59 {%s: cannot open shared object file: No such file or directory} 60set dlerror_notadll {%s: file too short} 61set dlerror_nosymbol {%s: undefined symbol: %s} 62 63if {$::tcl_platform(os) eq "Darwin"} { 64 set dlerror_nosuchfile {dlopen.%s, 10.: .*image.*found.*} 65 set dlerror_notadll {dlopen.%1$s, 10.: .*image.*found.*} 66 set dlerror_nosymbol {dlsym.XXX, %2$s.: symbol not found} 67} 68 69if {$::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# 79if {![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. -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# 97do_test loadext-1.1 { 98 catchsql { 99 SELECT half(1.0); 100 } 101} {1 {no such function: half}} 102do_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# 112do_test loadext-1.3 { 113 sqlite3 db2 test.db 114 sqlite3_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1 115 catchsql { 116 SELECT half(1.0); 117 } db2 118} {1 {no such function: half}} 119do_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# 129do_test loadext-1.5 { 130 db close 131 catchsql { 132 SELECT half(1.0); 133 } db2 134} {0 0.5} 135 136db2 close 137sqlite3 db test.db 138sqlite3_enable_load_extension db 1 139 140# Try to load an extension for which the file does not exist. 141# 142do_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# 152do_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# 168do_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# 180do_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 191db close 192sqlite3 db test.db 193sqlite3_enable_load_extension db 1 194do_test loadext-3.1 { 195 catchsql { 196 SELECT half(5); 197 } 198} {1 {no such function: half}} 199do_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]]/ 208do_test loadext-3.3 { 209 catchsql { 210 SELECT load_extension($::testextension,'testloadext_init') 211 } 212} {0 {{}}} 213do_test loadext-3.4 { 214 catchsql { 215 SELECT half(5); 216 } 217} {0 2.5} 218do_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} 225do_test loadext-3.6 { 226 catchsql { 227 SELECT sqlite3_status('MEMORY_USED_X') AS mused 228 } 229} {1 {unknown status property: MEMORY_USED_X}} 230do_test loadext-3.7 { 231 catchsql { 232 SELECT sqlite3_status(4.53) AS mused 233 } 234} {1 {unknown status type}} 235do_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# 245db close 246sqlite3 db test.db 247do_test loadext-4.1 { 248 catchsql { 249 SELECT load_extension($::testextension,'testloadext_init') 250 } 251} {1 {not authorized}} 252do_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# disable all extension loading 260do_test loadext-4.3 { 261 sqlite3_enable_load_extension db 0 262 catchsql { 263 SELECT load_extension($::testextension,'testloadext_init') 264 } 265} {1 {not authorized}} 266 267# enable C-api extension loading only. Show that the SQL function 268# still does not work. 269do_test loadext-4.4 { 270 sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1 271 catchsql { 272 SELECT load_extension($::testextension,'testloadext_init') 273 } 274} {1 {not authorized}} 275 276source $testdir/malloc_common.tcl 277 278 279# Malloc failure in sqlite3_auto_extension and sqlite3_load_extension 280# 281do_malloc_test loadext-5 -tclprep { 282 sqlite3_reset_auto_extension 283} -tclbody { 284 if {[autoinstall_test_functions]==7} {error "out of memory"} 285} 286 287# On Windows, this malloc test must be skipped because the winDlOpen 288# function itself can fail due to "out of memory" conditions. 289# 290if {$::tcl_platform(platform) ne "windows"} { 291 do_malloc_test loadext-6 -tclbody { 292 db enable_load_extension 1 293 sqlite3_load_extension db $::testextension testloadext_init 294 } 295} 296 297autoinstall_test_functions 298 299finish_test 300