github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/loadext.test (about)

     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.*found.*}
    65    set dlerror_notadll    {dlopen.%1$s, 10.: .*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. -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_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 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  # disable all extension loading
   260  do_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.
   269  do_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  
   276  source $testdir/malloc_common.tcl
   277  
   278  
   279  # Malloc failure in sqlite3_auto_extension and sqlite3_load_extension
   280  #
   281  do_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  #
   290  if {$::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  
   297  autoinstall_test_functions
   298  
   299  finish_test