# Commands covered: string # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # This differs from the original string tests in that the tests call # things in procs, which uses the compiled string code instead of # the runtime parse string code. The tests of import should match # their equivalent number in string.test. # # Copyright (c) 2001 by ActiveState Corporation. # Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: stringComp.test,v 1.15 2007/12/13 15:26:07 dgp Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import -force ::tcltest::* } # Some tests require the testobj command testConstraint testobj [expr {[info commands testobj] != {}}] test stringComp-1.1 {error conditions} { proc foo {} {string gorp a b} list [catch {foo} msg] $msg } {1 {unknown or ambiguous subcommand "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}} test stringComp-1.2 {error conditions} { proc foo {} {string} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string subcommand ?argument ...?"}} test stringComp-1.3 {error condition - undefined method during compile} { # We don't want this to complain about 'never' because it may never # be called, or string may get redefined. This must compile OK. proc foo {str i} { if {"yes" == "no"} { string never called but complains here } string index $str $i } foo abc 0 } a test stringComp-2.1 {string compare, too few args} { proc foo {} {string compare a} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}} test stringComp-2.2 {string compare, bad args} { proc foo {} {string compare a b c} list [catch {foo} msg] $msg } {1 {bad option "a": must be -nocase or -length}} test stringComp-2.3 {string compare, bad args} { list [catch {string compare -length -nocase str1 str2} msg] $msg } {1 {expected integer but got "-nocase"}} test stringComp-2.4 {string compare, too many args} { list [catch {string compare -length 10 -nocase str1 str2 str3} msg] $msg } {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}} test stringComp-2.5 {string compare with length unspecified} { list [catch {string compare -length 10 10} msg] $msg } {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}} test stringComp-2.6 {string compare} { proc foo {} {string compare abcde abdef} foo } -1 test stringComp-2.7 {string compare, shortest method name} { proc foo {} {string c abcde ABCDE} foo } 1 test stringComp-2.8 {string compare} { proc foo {} {string compare abcde abcde} foo } 0 test stringComp-2.9 {string compare with length} { proc foo {} {string compare -length 2 abcde abxyz} foo } 0 test stringComp-2.10 {string compare with special index} { proc foo {} {string compare -length end-3 abcde abxyz} list [catch {foo} msg] $msg } {1 {expected integer but got "end-3"}} test stringComp-2.11 {string compare, unicode} { proc foo {} {string compare ab\u7266 ab\u7267} foo } -1 test stringComp-2.12 {string compare, high bit} { # This test will fail if the underlying comparaison # is using signed chars instead of unsigned chars. # (like SunOS's default memcmp thus the compat/memcmp.c) proc foo {} {string compare "\x80" "@"} foo # Nb this tests works also in utf8 space because \x80 is # translated into a 2 or more bytelength but whose first byte has # the high bit set. } 1 test stringComp-2.13 {string compare -nocase} { proc foo {} {string compare -nocase abcde abdef} foo } -1 test stringComp-2.14 {string compare -nocase} { proc foo {} {string c -nocase abcde ABCDE} foo } 0 test stringComp-2.15 {string compare -nocase} { proc foo {} {string compare -nocase abcde abcde} foo } 0 test stringComp-2.16 {string compare -nocase with length} { proc foo {} {string compare -length 2 -nocase abcde Abxyz} foo } 0 test stringComp-2.17 {string compare -nocase with length} { proc foo {} {string compare -nocase -length 3 abcde Abxyz} foo } -1 test stringComp-2.18 {string compare -nocase with length <= 0} { proc foo {} {string compare -nocase -length -1 abcde AbCdEf} foo } -1 test stringComp-2.19 {string compare -nocase with excessive length} { proc foo {} {string compare -nocase -length 50 AbCdEf abcde} foo } 1 test stringComp-2.20 {string compare -len unicode} { # These are strings that are 6 BYTELENGTH long, but the length # shouldn't make a different because there are actually 3 CHARS long proc foo {} {string compare -len 5 \334\334\334 \334\334\374} foo } -1 test stringComp-2.21 {string compare -nocase with special index} { proc foo {} {string compare -nocase -length end-3 Abcde abxyz} list [catch {foo} msg] $msg } {1 {expected integer but got "end-3"}} test stringComp-2.22 {string compare, null strings} { proc foo {} {string compare "" ""} foo } 0 test stringComp-2.23 {string compare, null strings} { proc foo {} {string compare "" foo} foo } -1 test stringComp-2.24 {string compare, null strings} { proc foo {} {string compare foo ""} foo } 1 test stringComp-2.25 {string compare -nocase, null strings} { proc foo {} {string compare -nocase "" ""} foo } 0 test stringComp-2.26 {string compare -nocase, null strings} { proc foo {} {string compare -nocase "" foo} foo } -1 test stringComp-2.27 {string compare -nocase, null strings} { proc foo {} {string compare -nocase foo ""} foo } 1 test stringComp-2.28 {string compare with length, unequal strings} { proc foo {} {string compare -length 2 abc abde} foo } 0 test stringComp-2.29 {string compare with length, unequal strings} { proc foo {} {string compare -length 2 ab abde} foo } 0 test stringComp-2.30 {string compare with NUL character vs. other ASCII} { # Be careful here, since UTF-8 rep comparison with memcmp() of # these puts chars in the wrong order proc foo {} {string compare \x00 \x01} foo } -1 test stringComp-2.31 {string compare, high bit} { proc foo {} {string compare "a\x80" "a@"} foo } 1 test stringComp-2.32 {string compare, high bit} { proc foo {} {string compare "a\x00" "a\x01"} foo } -1 test stringComp-2.33 {string compare, high bit} { proc foo {} {string compare "\x00\x00" "\x00\x01"} foo } -1 # only need a few tests on equal, since it uses the same code as # string compare, but just modifies the return output test stringComp-3.1 {string equal} { proc foo {} {string equal abcde abdef} foo } 0 test stringComp-3.2 {string equal} { proc foo {} {string eq abcde ABCDE} foo } 0 test stringComp-3.3 {string equal} { proc foo {} {string equal abcde abcde} foo } 1 test stringComp-3.4 {string equal -nocase} { proc foo {} {string equal -nocase \334\334\334\334\374\374\374\374 \334\334\334\334\334\334\334\334} foo } 1 test stringComp-3.5 {string equal -nocase} { proc foo {} {string equal -nocase abcde abdef} foo } 0 test stringComp-3.6 {string equal -nocase} { proc foo {} {string eq -nocase abcde ABCDE} foo } 1 test stringComp-3.7 {string equal -nocase} { proc foo {} {string equal -nocase abcde abcde} foo } 1 test stringComp-3.8 {string equal with length, unequal strings} { proc foo {} {string equal -length 2 abc abde} foo } 1 test stringComp-4.1 {string first, too few args} { proc foo {} {string first a} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}} test stringComp-4.2 {string first, bad args} { proc foo {} {string first a b c} list [catch {foo} msg] $msg } {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}} test stringComp-4.3 {string first, too many args} { proc foo {} {string first a b 5 d} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}} test stringComp-4.4 {string first} { proc foo {} {string first bq abcdefgbcefgbqrs} foo } 12 test stringComp-4.5 {string first} { proc foo {} {string fir bcd abcdefgbcefgbqrs} foo } 1 test stringComp-4.6 {string first} { proc foo {} {string f b abcdefgbcefgbqrs} foo } 1 test stringComp-4.7 {string first} { proc foo {} {string first xxx x123xx345xxx789xxx012} foo } 9 test stringComp-4.8 {string first} { proc foo {} {string first "" x123xx345xxx789xxx012} foo } -1 test stringComp-4.9 {string first, unicode} { proc foo {} {string first x abc\u7266x} foo } 4 test stringComp-4.10 {string first, unicode} { proc foo {} {string first \u7266 abc\u7266x} foo } 3 test stringComp-4.11 {string first, start index} { proc foo {} {string first \u7266 abc\u7266x 3} foo } 3 test stringComp-4.12 {string first, start index} { proc foo {} {string first \u7266 abc\u7266x 4} foo } -1 test stringComp-4.13 {string first, start index} { proc foo {} {string first \u7266 abc\u7266x end-2} foo } 3 test stringComp-4.14 {string first, negative start index} { proc foo {} {string first b abc -1} foo } 1 test stringComp-5.1 {string index} { proc foo {} {string index} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string index string charIndex"}} test stringComp-5.2 {string index} { proc foo {} {string index a b c} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string index string charIndex"}} test stringComp-5.3 {string index} { proc foo {} {string index abcde 0} foo } a test stringComp-5.4 {string index} { proc foo {} {string in abcde 4} foo } e test stringComp-5.5 {string index} { proc foo {} {string index abcde 5} foo } {} test stringComp-5.6 {string index} { proc foo {} {string index abcde -10} list [catch {foo} msg] $msg } {0 {}} test stringComp-5.7 {string index} { proc foo {} {string index a xyz} list [catch {foo} msg] $msg } {1 {bad index "xyz": must be integer?[+-]integer? or end?[+-]integer?}} test stringComp-5.8 {string index} { proc foo {} {string index abc end} foo } c test stringComp-5.9 {string index} { proc foo {} {string index abc end-1} foo } b test stringComp-5.10 {string index, unicode} { proc foo {} {string index abc\u7266d 4} foo } d test stringComp-5.11 {string index, unicode} { proc foo {} {string index abc\u7266d 3} foo } \u7266 test stringComp-5.12 {string index, unicode over char length, under byte length} { proc foo {} {string index \334\374\334\374 6} foo } {} test stringComp-5.13 {string index, bytearray object} { proc foo {} {string index [binary format a5 fuz] 0} foo } f test stringComp-5.14 {string index, bytearray object} { proc foo {} {string index [binary format I* {0x50515253 0x52}] 3} foo } S test stringComp-5.15 {string index, bytearray object} { proc foo {} { set b [binary format I* {0x50515253 0x52}] set i1 [string index $b end-6] set i2 [string index $b 1] string compare $i1 $i2 } foo } 0 test stringComp-5.16 {string index, bytearray object with string obj shimmering} { proc foo {} { set str "0123456789\x00 abcdedfghi" binary scan $str H* dump string compare [string index $str 10] \x00 } foo } 0 test stringComp-5.17 {string index, bad integer} -body { proc foo {} {string index "abc" 0o8} list [catch {foo} msg] $msg } -match glob -result {1 {*invalid octal number*}} test stringComp-5.18 {string index, bad integer} -body { proc foo {} {string index "abc" end-0o0289} list [catch {foo} msg] $msg } -match glob -result {1 {*invalid octal number*}} test stringComp-5.19 {string index, bytearray object out of bounds} { proc foo {} {string index [binary format I* {0x50515253 0x52}] -1} foo } {} test stringComp-5.20 {string index, bytearray object out of bounds} { proc foo {} {string index [binary format I* {0x50515253 0x52}] 20} foo } {} proc largest_int {} { # This will give us what the largest valid int on this machine is, # so we can test for overflow properly below on >32 bit systems set int 1 set exp 7; # assume we get at least 8 bits while {$int > 0} { set int [expr {1 << [incr exp]}] } return [expr {$int-1}] } ## string is ## not yet bc catch {rename largest_int {}} ## string last ## not yet bc ## string length ## not yet bc test stringComp-8.1 {string bytelength} { proc foo {} {string bytelength} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string bytelength string"}} test stringComp-8.2 {string bytelength} { proc foo {} {string bytelength a b} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string bytelength string"}} test stringComp-8.3 {string bytelength} { proc foo {} {string bytelength "\u00c7"} foo } 2 test stringComp-8.4 {string bytelength} { proc foo {} {string b ""} foo } 0 ## string length ## test stringComp-9.1 {string length} { proc foo {} {string length} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string length string"}} test stringComp-9.2 {string length} { proc foo {} {string length a b} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string length string"}} test stringComp-9.3 {string length} { proc foo {} {string length "a little string"} foo } 15 test stringComp-9.4 {string length} { proc foo {} {string le ""} foo } 0 test stringComp-9.5 {string length, unicode} { proc foo {} {string le "abcd\u7266"} foo } 5 test stringComp-9.6 {string length, bytearray object} { proc foo {} {string length [binary format a5 foo]} foo } 5 test stringComp-9.7 {string length, bytearray object} { proc foo {} {string length [binary format I* {0x50515253 0x52}]} foo } 8 ## string map ## not yet bc ## string match ## test stringComp-11.1 {string match, too few args} { proc foo {} {string match a} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string match ?-nocase? pattern string"}} test stringComp-11.2 {string match, too many args} { proc foo {} {string match a b c d} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string match ?-nocase? pattern string"}} test stringComp-11.3 {string match} { proc foo {} {string match abc abc} foo } 1 test stringComp-11.4 {string match} { proc foo {} {string mat abc abd} foo } 0 test stringComp-11.5 {string match} { proc foo {} {string match ab*c abc} foo } 1 test stringComp-11.6 {string match} { proc foo {} {string match ab**c abc} foo } 1 test stringComp-11.7 {string match} { proc foo {} {string match ab* abcdef} foo } 1 test stringComp-11.8 {string match} { proc foo {} {string match *c abc} foo } 1 test stringComp-11.9 {string match} { proc foo {} {string match *3*6*9 0123456789} foo } 1 test stringComp-11.10 {string match} { proc foo {} {string match *3*6*9 01234567890} foo } 0 test stringComp-11.11 {string match} { proc foo {} {string match a?c abc} foo } 1 test stringComp-11.12 {string match} { proc foo {} {string match a??c abc} foo } 0 test stringComp-11.13 {string match} { proc foo {} {string match ?1??4???8? 0123456789} foo } 1 test stringComp-11.14 {string match} { proc foo {} {string match {[abc]bc} abc} foo } 1 test stringComp-11.15 {string match} { proc foo {} {string match {a[abc]c} abc} foo } 1 test stringComp-11.16 {string match} { proc foo {} {string match {a[xyz]c} abc} foo } 0 test stringComp-11.17 {string match} { proc foo {} {string match {12[2-7]45} 12345} foo } 1 test stringComp-11.18 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12345} foo } 1 test stringComp-11.19 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12b45} foo } 1 test stringComp-11.20 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12d45} foo } 1 test stringComp-11.21 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12145} foo } 0 test stringComp-11.22 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12545} foo } 0 test stringComp-11.23 {string match} { proc foo {} {string match {a\*b} a*b} foo } 1 test stringComp-11.24 {string match} { proc foo {} {string match {a\*b} ab} foo } 0 test stringComp-11.25 {string match} { proc foo {} {string match {a\*\?\[\]\\\x} "a*?\[\]\\x"} foo } 1 test stringComp-11.26 {string match} { proc foo {} {string match ** ""} foo } 1 test stringComp-11.27 {string match} { proc foo {} {string match *. ""} foo } 0 test stringComp-11.28 {string match} { proc foo {} {string match "" ""} foo } 1 test stringComp-11.29 {string match} { proc foo {} {string match \[a a} foo } 1 test stringComp-11.30 {string match, bad args} { proc foo {} {string match - b c} list [catch {foo} msg] $msg } {1 {bad option "-": must be -nocase}} test stringComp-11.31 {string match case} { proc foo {} {string match a A} foo } 0 test stringComp-11.32 {string match nocase} { proc foo {} {string match -n a A} foo } 1 test stringComp-11.33 {string match nocase} { proc foo {} {string match -nocase a\334 A\374} foo } 1 test stringComp-11.34 {string match nocase} { proc foo {} {string match -nocase a*f ABCDEf} foo } 1 test stringComp-11.35 {string match case, false hope} { # This is true because '_' lies between the A-Z and a-z ranges proc foo {} {string match {[A-z]} _} foo } 1 test stringComp-11.36 {string match nocase range} { # This is false because although '_' lies between the A-Z and a-z ranges, # we lower case the end points before checking the ranges. proc foo {} {string match -nocase {[A-z]} _} foo } 0 test stringComp-11.37 {string match nocase} { proc foo {} {string match -nocase {[A-fh-Z]} g} foo } 0 test stringComp-11.38 {string match case, reverse range} { proc foo {} {string match {[A-fh-Z]} g} foo } 1 test stringComp-11.39 {string match, *\ case} { proc foo {} {string match {*\abc} abc} foo } 1 test stringComp-11.40 {string match, *special case} { proc foo {} {string match {*[ab]} abc} foo } 0 test stringComp-11.41 {string match, *special case} { proc foo {} {string match {*[ab]*} abc} foo } 1 test stringComp-11.42 {string match, *special case} { proc foo {} {string match "*\\" "\\"} foo } 0 test stringComp-11.43 {string match, *special case} { proc foo {} {string match "*\\\\" "\\"} foo } 1 test stringComp-11.44 {string match, *special case} { proc foo {} {string match "*???" "12345"} foo } 1 test stringComp-11.45 {string match, *special case} { proc foo {} {string match "*???" "12"} foo } 0 test stringComp-11.46 {string match, *special case} { proc foo {} {string match "*\\*" "abc*"} foo } 1 test stringComp-11.47 {string match, *special case} { proc foo {} {string match "*\\*" "*"} foo } 1 test stringComp-11.48 {string match, *special case} { proc foo {} {string match "*\\*" "*abc"} foo } 0 test stringComp-11.49 {string match, *special case} { proc foo {} {string match "?\\*" "a*"} foo } 1 test stringComp-11.50 {string match, *special case} { proc foo {} {string match "\\" "\\"} foo } 0 test stringComp-11.51 {string match; *, -nocase and UTF-8} { proc foo {} {string match -nocase [binary format I 717316707] \ [binary format I 2028036707]} foo } 1 test stringComp-11.52 {string match, null char in string} { proc foo {} { set ptn "*abc*" foreach elem [list "\u0000@abc" "@abc" "\u0000@abc\u0000" "blahabcblah"] { lappend out [string match $ptn $elem] } set out } foo } {1 1 1 1} test stringComp-11.53 {string match, null char in pattern} { proc foo {} { set out "" foreach {ptn elem} [list \ "*\u0000abc\u0000" "\u0000abc\u0000" \ "*\u0000abc\u0000" "\u0000abc\u0000ef" \ "*\u0000abc\u0000*" "\u0000abc\u0000ef" \ "*\u0000abc\u0000" "@\u0000abc\u0000ef" \ "*\u0000abc\u0000*" "@\u0000abc\u0000ef" \ ] { lappend out [string match $ptn $elem] } set out } foo } {1 0 1 0 1} test stringComp-11.54 {string match, failure} { proc foo {} { set longString "" for {set i 0} {$i < 10} {incr i} { append longString "abcdefghijklmnopqrstuvwxy\u0000z01234567890123" } list [string match *cba* $longString] \ [string match *a*l*\u0000* $longString] \ [string match *a*l*\u0000*123 $longString] \ [string match *a*l*\u0000*123* $longString] \ [string match *a*l*\u0000*cba* $longString] \ [string match *===* $longString] } foo } {0 1 1 1 0 0} ## string range ## not yet bc ## string repeat ## not yet bc ## string replace ## not yet bc ## string tolower ## not yet bc ## string toupper ## not yet bc ## string totitle ## not yet bc ## string trim* ## not yet bc ## string word* ## not yet bc # cleanup ::tcltest::cleanupTests return