# # 2007 May 7 # # 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 the sqlite4_create_collation() and # collation_needed() APIs. More specifically, the focus is on testing that # destructor callbacks are invoked correctly. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix collate7 # Implementation of collation sequence callbacks. # proc caseless_cmp {zLeft zRight} { string compare -nocase $zLeft $zRight } proc caseless_mkkey {zIn} { string tolower $zIn } #------------------------------------------------------------------------- # Test the destructor is invoked when a collation sequence is overridden. # do_test 1.1 { set ::caseless_del 0 set del [list incr ::caseless_del] sqlite4_create_collation db CASELESS caseless_cmp caseless_mkkey $del set ::caseless_del } {0} do_test 1.2 { set ::caseless_del 0 sqlite4_create_collation db CASELESS {} {} {} set ::caseless_del } {1} do_catchsql_test 1.3 { CREATE TABLE abc(a COLLATE CASELESS, b, c); } {1 {no such collation sequence: CASELESS}} do_test 1.4 { set ::caseless_del 0 sqlite4_create_collation db CASELESS {} {} {} set ::caseless_del } {0} #------------------------------------------------------------------------- # Test the destructor is invoked when the database handle is closed. # do_test 2.1 { set ::caseless_del 0 set del [list incr ::caseless_del] sqlite4_create_collation db CASELESS caseless_cmp caseless_mkkey $del db close set ::caseless_del } {1} #------------------------------------------------------------------------- # Test the destructor is invoked if an error occurs within # sqlite4_create_collation(). The easiest error to provoke here is # SQLITE4_BUSY - which is returned if an attempt is made to override a # collation while there are active statements. # reset_db do_test 3.1 { set ::caseless_del 0 set del [list incr ::caseless_del] sqlite4_create_collation db CASELESS caseless_cmp caseless_mkkey $del execsql { CREATE TABLE t1(a COLLATE caseless); INSERT INTO t1 VALUES('abc'); INSERT INTO t1 VALUES('def'); } set ::stmt [sqlite4_prepare db "SELECT a FROM t1" -1 DUMMY] sqlite4_step $::stmt } {SQLITE4_ROW} do_test 3.2 { set ::caseless_del2 0 set del [list incr ::caseless_del2] set rc [catch { sqlite4_create_collation db CASELESS caseless_cmp caseless_mkkey $del } msg] list $::caseless_del $caseless_del2 $rc $msg } {0 1 1 SQLITE4_BUSY} do_test 3.3 { sqlite4_errcode db } {SQLITE4_BUSY} do_test 3.4 { sqlite4_errmsg db } {unable to delete/modify collation sequence due to active statements} do_test 3.5 { sqlite4_finalize $::stmt } {SQLITE4_OK} do_test 3.6 { sqlite4_errcode db } {SQLITE4_OK} do_test 3.7 { sqlite4_errmsg db } {not an error} #------------------------------------------------------------------------- # The following tests verify that the collation needed destructor is # invoked: # # 1. When it is overridden, and # 2. When the database connection is closed. # # It would be good to test that if an error occurs within the # collation_needed() the destructor is invoked immediately (as the # documentation says). However there is currently no way to cause # sqlite4_collation_needed() to fail. sqlite4_collation_needed() # currently *always* returns SQLITE4_OK. # do_test 4.1.1 { set ::coll_needed_del 0 sqlite4_collation_needed db coll_needed {incr ::coll_needed_del} set ::coll_needed_del } {0} do_test 4.1.2 { set ::coll_needed_del2 0 sqlite4_collation_needed db coll_needed {incr ::coll_needed_del2} list $::coll_needed_del $::coll_needed_del2 } {1 0} do_test 4.2 { db close list $::coll_needed_del $::coll_needed_del2 } {1 1} finish_test