# 2002 May 24 # # 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 file is testing the SQLite routines used for converting between the # various suported unicode encodings (UTF-8, UTF-16, UTF-16le and # UTF-16be). # # $Id: enc2.test,v 1.8 2004/06/10 14:01:08 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl db close # Return the UTF-8 representation of the supplied UTF-16 string $str. proc utf8 {str} { # If $str ends in two 0x00 0x00 bytes, knock these off before # converting to UTF-8 using TCL. binary scan $str \c* vals if {[lindex $vals end]==0 && [lindex $vals end-1]==0} { set str [binary format \c* [lrange $vals 0 end-2]] } set r [encoding convertfrom unicode $str] return $r } # # This proc contains all the tests in this file. It is run # three times. Each time the file 'test.db' contains a database # with the following contents: set dbcontents { CREATE TABLE t1(a PRIMARY KEY, b, c); INSERT INTO t1 VALUES('one', 'I', 1); } # This proc tests that we can open and manipulate the test.db # database, and that it is possible to retreive values in # various text encodings. # proc run_test_script {t enc} { # Open the database and pull out a (the) row. do_test $t.1 { set DB [sqlite db test.db] execsql {SELECT * FROM t1} } {one I 1} # Insert some data do_test $t.2 { execsql {INSERT INTO t1 VALUES('two', 'II', 2);} execsql {SELECT * FROM t1} } {one I 1 two II 2} # Insert some data do_test $t.3 { execsql { INSERT INTO t1 VALUES('three','III',3); INSERT INTO t1 VALUES('four','IV',4); INSERT INTO t1 VALUES('five','V',5); } execsql {SELECT * FROM t1} } {one I 1 two II 2 three III 3 four IV 4 five V 5} # Use the index do_test $t.4 { execsql { SELECT * FROM t1 WHERE a = 'one'; } } {one I 1} do_test $t.5 { execsql { SELECT * FROM t1 WHERE a = 'four'; } } {four IV 4} do_test $t.6 { execsql { SELECT * FROM t1 WHERE a IN ('one', 'two'); } } {one I 1 two II 2} # Now check that we can retrieve data in both UTF-16 and UTF-8 do_test $t.7 { set STMT [sqlite3_prepare $DB "SELECT a FROM t1 WHERE c>3;" -1 TAIL] sqlite3_step $STMT sqlite3_column_text $STMT 0 } {four} do_test $t.8 { sqlite3_step $STMT utf8 [sqlite3_column_text16 $STMT 0] } {five} do_test $t.9 { sqlite3_finalize $STMT } SQLITE_OK do_test $t.10 { db eval {PRAGMA encoding} } $enc } # The three unicode encodings understood by SQLite. set encodings [list UTF-8 UTF-16le UTF-16be] set i 1 foreach enc $encodings { file delete -force test.db sqlite db test.db db eval "PRAGMA encoding = \"$enc\"" execsql $dbcontents db close run_test_script enc2-$i $enc incr i } # Test that it is an error to try to attach a database with a different # encoding to the main database. do_test enc2-4.1 { file delete -force test.db sqlite db test.db db eval "PRAGMA encoding = 'UTF-8'" db eval "CREATE TABLE abc(a, b, c);" } {} do_test enc2-4.2 { file delete -force test2.db sqlite db2 test2.db db2 eval "PRAGMA encoding = 'UTF-16'" db2 eval "CREATE TABLE abc(a, b, c);" } {} do_test enc2-4.3 { catchsql { ATTACH 'test2.db' as aux; } } {1 {attached databases must use the same text encoding as main database}} db2 close db close # The following tests - enc2-5.* - test that SQLite selects the correct # collation sequence when more than one is available. set ::values [list one two three four five] set ::test_collate_enc INVALID proc test_collate {enc lhs rhs} { set ::test_collate_enc $enc set l [lsearch -exact $::values $lhs] set r [lsearch -exact $::values $rhs] set res [expr $l - $r] # puts "test_collate $enc $lhs $rhs -> $res" return $res } file delete -force test.db set DB [sqlite db test.db] do_test enc2-5.0 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); INSERT INTO t5 VALUES('five'); INSERT INTO t5 VALUES('three'); INSERT INTO t5 VALUES('four'); } } {} do_test enc2-5.1 { add_test_collate $DB 1 1 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-8} do_test enc2-5.2 { add_test_collate $DB 0 1 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16LE} breakpoint do_test enc2-5.3 { add_test_collate $DB 0 0 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16BE} file delete -force test.db set DB [sqlite db test.db] execsql {pragma encoding = 'UTF-16LE'} do_test enc2-5.4 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); INSERT INTO t5 VALUES('five'); INSERT INTO t5 VALUES('three'); INSERT INTO t5 VALUES('four'); } } {} do_test enc2-5.5 { add_test_collate $DB 1 1 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16LE} do_test enc2-5.6 { add_test_collate $DB 1 0 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16BE} breakpoint do_test enc2-5.7 { add_test_collate $DB 1 0 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-8} file delete -force test.db set DB [sqlite db test.db] execsql {pragma encoding = 'UTF-16BE'} do_test enc2-5.8 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); INSERT INTO t5 VALUES('five'); INSERT INTO t5 VALUES('three'); INSERT INTO t5 VALUES('four'); } } {} do_test enc2-5.9 { add_test_collate $DB 1 1 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16BE} do_test enc2-5.10 { add_test_collate $DB 1 1 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16LE} breakpoint do_test enc2-5.11 { add_test_collate $DB 1 0 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-8} finish_test