From 69e777f3308e307fda78c6d5ddfb8fe3806558a6 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Wed, 14 Jun 2006 10:38:02 +0000 Subject: [PATCH] Add some tests for sqlite3_load_extension(). (CVS 3239) FossilOrigin-Name: 402a77c43d4e4dcd2e1197cfaaa2ed51249a1b8f --- Makefile.linux-gcc | 6 +++ main.mk | 7 +++ manifest | 22 +++++---- manifest.uuid | 2 +- src/loadext.c | 23 +++++---- src/test1.c | 56 ++++++++++++++++++++- src/test_loadext.c | 57 +++++++++++++++++++++ test/loadext.test | 121 +++++++++++++++++++++++++++++++++++++++++++++ test/quick.test | 3 +- 9 files changed, 274 insertions(+), 23 deletions(-) create mode 100644 src/test_loadext.c create mode 100644 test/loadext.test diff --git a/Makefile.linux-gcc b/Makefile.linux-gcc index 210cb685d1..c865024b44 100644 --- a/Makefile.linux-gcc +++ b/Makefile.linux-gcc @@ -83,6 +83,12 @@ AR = ar cr RANLIB = ranlib #RANLIB = /opt/mingw/bin/i386-mingw32-ranlib +MKSHLIB = gcc -shared +SO = so +SHPREFIX = lib +# SO = dll +# SHPREFIX = + #### Extra compiler options needed for programs that use the TCL library. # #TCL_FLAGS = diff --git a/main.mk b/main.mk index de072755fa..1691de3146 100644 --- a/main.mk +++ b/main.mk @@ -400,6 +400,13 @@ sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) \ sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ libsqlite3.a $(LIBTCL) $(THREADLIB) +TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO) +$(TEST_EXTENSION): $(TOP)/src/test_loadext.c + $(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION) + +extensiontest: testfixture$(EXE) $(TEST_EXTENSION) + ./testfixture$(EXE) $(TOP)/test/loadext.test + # Rules used to build documentation # arch.html: $(TOP)/www/arch.tcl diff --git a/manifest b/manifest index b3a7573de0..239f69edb0 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Add\stests\sfor\sthe\snew\sMATCH\soperator.\s(CVS\s3238) -D 2006-06-14T08:48:26 +C Add\ssome\stests\sfor\ssqlite3_load_extension().\s(CVS\s3239) +D 2006-06-14T10:38:03 F Makefile.in 200f6dc376ecfd9b01e5359c4e0c10c02f649b34 -F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec +F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F VERSION 301ed2b2c08f5cca242ea56e50a9ed0264a3eb76 F aclocal.m4 a8df0ae21d1ac797fa7d7eaa1703412bc61b973f @@ -19,7 +19,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 -F main.mk 2f02a26044baa6126127e7231b1cea172355d721 +F main.mk 3fe86a381432abf3ba96d0276ea85618bcf9e5a1 F mkdll.sh 919df5efde876194e3102c6ebc60657d38949909 F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5 @@ -48,7 +48,7 @@ F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564 F src/insert.c 2c3eeb4bcde13c1006824ef14953c2fdad31cf36 F src/legacy.c fa15d505dd4e45044177ee4d1c6aeaf8c836d390 -F src/loadext.c 0215a9c83b7f720aba30f06f183fe6fb3c56a009 +F src/loadext.c d8c7bd14e6ebc4e9f1ff269475bf63e131919449 F src/main.c f4397bf95216496e49db2153789788f4b1207b91 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235 @@ -77,7 +77,7 @@ F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75 F src/sqliteInt.h e8710fd5c10c03ca4a2fb49802b8aae6689f27a0 F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e F src/tclsqlite.c 4ad22f354b6e4e137889000e9f585a0590ca39c5 -F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50 +F src/test1.c 40f20775903bc76d3be3e7c026dddcbc221c1cb0 F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b F src/test3.c 86e99724ee898b119ed575ef9f98618afe7e5e5d F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 @@ -86,6 +86,7 @@ F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3 F src/test8.c 0ad60b5e5c1e5c219f39b190a404a34c9766422c F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3 +F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8 F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3 F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c F src/test_tclvar.c d434037c1730cfffbf007ac82f1c405d7155a92a @@ -194,6 +195,7 @@ F test/lastinsert.test 9d7241f562d7adcf61730de83176417d7e30d76b F test/laststmtchanges.test 19a6d0c11f7a31dc45465b495f7b845a62cbec17 F test/like.test 5f7d76574752a9101cac13372c8a85999d0d91e6 F test/limit.test 71884068d47b18f614735f0686690319b32cdc22 +F test/loadext.test 1704f48b39ba6d9d15b46bf0c0eb1ea82fb06f1f F test/lock.test 9b7afcb24f53d24da502abb33daaad2cd6d44107 F test/lock2.test d83ba79d3c4fffdb5b926c7d8ca7a36c34288a55 F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9 @@ -222,7 +224,7 @@ F test/pagesize.test 05c74ea49f790734ec1e9ab765d9bf1cce79b8f2 F test/pragma.test 2ca8f71989dc4b9ad68210d1943040321c663a19 F test/printf.test cdd8e20dd901382a385afcbaa777b9377815c2ad F test/progress.test 8b22b4974b0a95272566385f8cb8c341c7130df8 x -F test/quick.test e220b3b6e62fe4fb4e2a703ab2ba730fedfe0424 +F test/quick.test fc44005d54bc6b43609e3942ddf22babd8230fcc F test/quote.test 5891f2338980916cf7415484b4ce785294044adb F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b F test/rollback.test 673cd8c44c685ad54987fe7f0eeba84efa09685d @@ -364,7 +366,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P f459f034f659a4c418aa1bc72135cc93d04565df -R ea0e08f5993556739ac65af3b6ec4b97 +P b4024c394d25e5a0abdb07be779ae41581834c42 +R 961f649a82865eb21d2c12799e526db2 U danielk1977 -Z 19fda68a524896e3f72b47e2caafc4a8 +Z 72c502f9c1fb513a156342339f64fbd9 diff --git a/manifest.uuid b/manifest.uuid index 48170262a0..7911295584 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b4024c394d25e5a0abdb07be779ae41581834c42 \ No newline at end of file +402a77c43d4e4dcd2e1197cfaaa2ed51249a1b8f \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index da9e978f0a..b0902e8d04 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -233,16 +233,6 @@ int sqlite3_load_extension( char *zErrmsg = 0; SQLITE_LIBRARY_TYPE *aHandle; - db->nExtension++; - aHandle = sqliteMalloc(sizeof(handle)*db->nExtension); - if( aHandle==0 ){ - return SQLITE_NOMEM; - } - if( db->nExtension>0 ){ - memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1)); - } - sqliteFree(db->aExtension); - db->aExtension = aHandle; if( zProc==0 ){ int i, j, n; char *z; @@ -294,6 +284,19 @@ int sqlite3_load_extension( SQLITE_CLOSE_LIBRARY(handle); return SQLITE_ERROR; } + + /* Append the new shared library handle to the db->aExtension array. */ + db->nExtension++; + aHandle = sqliteMalloc(sizeof(handle)*db->nExtension); + if( aHandle==0 ){ + return SQLITE_NOMEM; + } + if( db->nExtension>0 ){ + memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1)); + } + sqliteFree(db->aExtension); + db->aExtension = aHandle; + ((SQLITE_LIBRARY_TYPE*)db->aExtension)[db->nExtension-1] = handle; return SQLITE_OK; #else diff --git a/src/test1.c b/src/test1.c index 0c18ea1292..79f3ec2f5b 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.210 2006/06/11 23:41:56 drh Exp $ +** $Id: test1.c,v 1.211 2006/06/14 10:38:03 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -1094,6 +1094,57 @@ static int test_table_column_metadata( } #endif +/* +** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? +*/ +static int test_load_extension( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_CmdInfo cmdInfo; + sqlite3 *db; + int rc; + char *zDb; + char *zFile; + char *zProc = 0; + char *zErr = 0; + + if( objc!=4 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[1]); + zFile = Tcl_GetString(objv[2]); + if( objc==4 ){ + zProc = Tcl_GetString(objv[3]); + } + + /* Extract the C database handle from the Tcl command name */ + if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); + return TCL_ERROR; + } + db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + assert(db); + + /* Call the underlying C function. If an error occurs, set rc to + ** TCL_ERROR and load any error string into the interpreter. If no + ** error occurs, set rc to TCL_OK. + */ + rc = sqlite3_load_extension(db, zFile, zProc, &zErr); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); + rc = TCL_ERROR; + }else{ + rc = TCL_OK; + } + sqlite3_free(zErr); + + return rc; +} + /* ** Usage: sqlite_abort ** @@ -3694,6 +3745,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_libversion_number", test_libversion_number, 0 }, #ifdef SQLITE_ENABLE_COLUMN_METADATA { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + { "sqlite3_load_extension", test_load_extension, 0 }, #endif }; static int bitmask_size = sizeof(Bitmask)*8; diff --git a/src/test_loadext.c b/src/test_loadext.c new file mode 100644 index 0000000000..12049713d3 --- /dev/null +++ b/src/test_loadext.c @@ -0,0 +1,57 @@ +/* +** 2006 June 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Test extension for testing the sqlite3_load_extension() function. +** +** $Id: test_loadext.c,v 1.1 2006/06/14 10:38:03 danielk1977 Exp $ +*/ + +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +/* +** The half() SQL function returns half of its input value. +*/ +static void halfFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0])); +} + +/* +** Extension load function. +*/ +int testloadext_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0); + return 0; +} + +/* +** Another extension entry point. This one always fails. +*/ +int testbrokenext_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + char *zErr; + SQLITE_EXTENSION_INIT2(pApi); + zErr = sqlite3_mprintf("broken!"); + *pzErrMsg = zErr; + return 1; +} diff --git a/test/loadext.test b/test/loadext.test new file mode 100644 index 0000000000..9381f04763 --- /dev/null +++ b/test/loadext.test @@ -0,0 +1,121 @@ +# 2006 July 14 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this script is in-memory database backend. +# +# $Id: loadext.test,v 1.1 2006/06/14 10:38:03 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +if {$::tcl_platform(platform) eq "windows"} { + set testextension testloadext.dll +} else { + set testextension libtestloadext.so +} + +if {![file exists $testextension]} { + puts "Skipping loadext tests: Test extension not built..." + finish_test + return +} + +# Test that loading the extension produces the expected results - adding +# the half() function to the specified database handle. +# +do_test loadext-1.1 { + catchsql { + SELECT half(1.0); + } +} {1 {no such function: half}} +do_test loadext-1.2 { + sqlite3_load_extension db $testextension + catchsql { + SELECT half(1.0); + } +} {0 0.5} + +# Test that a second database connection (db2) can load the extension also. +# +do_test loadext-1.3 { + sqlite3 db2 test.db + catchsql { + SELECT half(1.0); + } db2 +} {1 {no such function: half}} +do_test loadext-1.4 { + sqlite3_load_extension db2 $testextension + catchsql { + SELECT half(1.0); + } db2 +} {0 0.5} + +# Close the first database connection. Then check that the second database +# can still use the half() function without a problem. +# +do_test loadext-1.5 { + db close + catchsql { + SELECT half(1.0); + } db2 +} {0 0.5} + +db2 close +sqlite3 db test.db + +# Try to load an extension for which the file does not exist. +# +do_test loadext-2.1 { + set rc [catch { + sqlite3_load_extension db "xx${testextension}" + } msg] + list $rc $msg +} [list 1 [subst -nocommands \ + {unable to open shared library [xx${testextension}]} +]] + +# Try to load an extension for which the file is not a shared object +# +do_test loadext-2.2 { + set fd [open "xx${testextension}" w] + puts $fd blah + close $fd + set rc [catch { + sqlite3_load_extension db "xx${testextension}" + } msg] + list $rc $msg +} [list 1 [subst -nocommands \ + {unable to open shared library [xx${testextension}]} +]] + +# Try to load an extension for which the file is present but the +# entry point is not. +# +do_test loadext-2.3 { + set rc [catch { + sqlite3_load_extension db $testextension icecream + } msg] + list $rc $msg +} [list 1 [subst -nocommands \ + {no entry point [icecream] in shared library [$testextension]} +]] + +# Try to load an extension for which the entry point fails (returns non-zero) +# +do_test loadext-2.4 { + set rc [catch { + sqlite3_load_extension db $testextension testbrokenext_init + } msg] + list $rc $msg +} {1 {error during initialization: broken!}} + +finish_test + diff --git a/test/quick.test b/test/quick.test index 5d03b6f157..13c29f0c78 100644 --- a/test/quick.test +++ b/test/quick.test @@ -6,7 +6,7 @@ #*********************************************************************** # This file runs all tests. # -# $Id: quick.test,v 1.43 2006/02/14 10:48:40 danielk1977 Exp $ +# $Id: quick.test,v 1.44 2006/06/14 10:38:03 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l @@ -43,6 +43,7 @@ set EXCLUDE { btree6.test corrupt.test crash.test + loadext.test malloc.test malloc2.test malloc3.test