hiccup-0.40: atests.tcl
source include.tcl
source testlib.tcl
source atests/string_tests.tcl
source atests/list_tests.tcl
source atests/array_tests.tcl
source atests/ns_tests.tcl
test "upvar" {
proc uptest {var v} {
upvar $var loc
set loc $v
}
set x 4
uptest x 3
checkthat $x == 3
proc uptest2 {var2 v} {
proc inner {a b} {
upvar 2 $b whee
set whee $a
}
upvar $var2 lark
inner $v $var2
incr lark
}
set y 99
uptest2 y 3
checkthat $y == 4
}
test "info vars" {
checkthat [llength [info vars]] == 0
set x 4
checkthat [info vars] eq "x"
checkthat [info vars y] eq {}
checkthat [info vars ?] eq "x"
}
test "info exists" {
checkthat [info exists x] == 0
set x 4
checkthat [info exists x] == 1
checkthat [info exists current_test] == 0
variable testlib::current_test
checkthat [info exists current_test] == 1
set arr(4) 2
checkthat [info exists arr(3)] == 0
checkthat [info exists arr(4)] == 1
# TODO: Check upvar'd exists
}
test "info level" {
checkthat [uplevel {info level}] == 0
checkthat [info level] == 1
proc getlevel {} {
return [info level]
}
checkthat [getlevel] == 2
}
test "upvar create" {
proc xxx {} { upvar up local; set local 5 }
checkthat [info exists up] == 0
xxx
checkthat $up == 5
proc xxx2 {} { upvar up2 local }
checkthat [info exists up2] == 0
xxx2
checkthat [info exists up2] == 0
}
test "error on bad upvar level" {
assertErr { upvar 1000 x x }
}
test "unevaluated blocks aren't parsed" {
if {== 3 4} {
"This should be no problem. $woo_etcetera.;
"
} else {
assertPass
}
}
test "unused args" {
proc addem {a b} {
return [+ $a $a]
return [+ $b $a]
}
checkthat [addem 5 "balloon"] == 10
}
test "incr test" {
set count 0
incr count
incr count
incr count
checkthat $count == 3
incr count 2
checkthat $count == 5
incr count -2
checkthat $count == 3
decr count
decr count
decr count
checkthat $count == 0
}
test "math test" {
checkthat [pow 2 2] == 4
checkthat [pow 2 10] == 1024
checkthat [expr { sqrt(2 + 2) }] eq 2.0
checkthat [+ 3.5 3.5] == 7.0
checkthat [* 2 1.5] == 3.0
checkthat [+ 1 1 1 1 1 1] == 6
checkthat [* 1 1 1 1 1 1 2] == 2
}
test "expr fun parse" {
checkthat [expr { sin(0.0) + 10 }] == 10.0
checkthat[expr { !(3 == 4) }]
checkthat[expr { !0 }]
checkthat[expr { !true }] == 0
assert_err { expr {} }
# TODO: Not yet
# assert_noerr { expr {[set x ""]} }
}
test "double compare" {
checkthat [< 0.3 0.9]
checkthat [<= 0.3 0.9]
checkthat [<= 0.9 0.9]
checkthat [<= 0.9 0.3] == 0
checkthat [> 1.9 1]
checkthat [== 3.8 3.8]
checkthat [expr { double(3) }] == 3.0
}
test "abs mathfunc" {
checkthat [expr { abs(-3) }] eq 3
checkthat [expr { abs(3) }] eq 3
}
test "bool test" {
checkthat [expr { true || false }] == 1
checkthat [expr { false || true }] == 1
checkthat [expr { false || false }] == 0
checkthat [expr { true && false }] == 0
checkthat [expr { false && true }] == 0
checkthat [expr { false && false }] == 0
checkthat [expr { true && true }] == 1
checkthat [expr { on || off }] == 1
checkthat [! true] == 0
checkthat [! false] == 1
checkthat [! [! [! true]]] == 0
}
test "test if, elseif, else" {
if { eq "one" "two" } {
die "Should not have hit this."
} elseif { == 1 1 } {
assertPass
} else {
die "Should not have hit this."
}
}
test "test args parameter" {
set total 0
proc argstest {tot args} {
upvar $tot total
set i 0
while {< $i [llength $args]} {
set total [+ [lindex $args $i] $total]
incr i
}
}
checkthat $total == 0
argstest total 1 2 3 4 5 6 7 8
checkthat $total == 36
}
test "basic control flow" {
set sval 0
set sval2 1
while {<= $sval 10} {
incr sval
if {<= 8 $sval} {
break
}
if {<= 4 $sval} {
continue
}
incr sval2
}
checkthat $sval == 8
checkthat $sval2 == 4
}
test "test append" {
set somestr "one"
append somestr " two" " three" " four"
checkthat $somestr eq "one two three four"
append avar a b c
checkthat $avar eq "abc"
}
test "foreach" {
set numbers {1 2 3 4 5}
set result 0
foreach number $numbers {
set result [+ $number $result]
}
checkthat $result == 15
set fer "old"
foreach feitem {"a b" "c d"} {
set fer $feitem
}
checkthat $fer eq "c d"
}
test "foreach multi-bind" {
foreach {x y z} [list 1 2 3] {}
checkthat $x == 1
checkthat $y == 2
checkthat $z == 3
foreach {x y z} [list 1 2 3 4] {}
checkthat $x == 4
checkthat $y eq ""
checkthat $z eq ""
}
test "foreach break and continue" {
set v 0
foreach x { 1 2 3 4 5 } {
set v $x
continue
set v 0
}
checkthat $v == 5
set v 0
foreach x { 1 2 3 4 5 } {
set v $x
break
}
checkthat $v == 1
}
test "foreach misc" {
set misc { 1 2 3 4 5 6 }
proc join2 { lsx mid } {
set res ""
set first_time 1
foreach ind $lsx {
if { == $first_time 1 } {
set res $ind
set first_time 0
} else {
set res "$res$mid$ind"
}
}
return $res
}
checkthat [join2 $misc +] eq "1+2+3+4+5+6"
}
test "for loop" {
set res 0
for {set i 0} { < $i 20 } { incr i } {
incr res $i
}
checkthat $res == 190
checkthat $i == 20
set val 0
for {set i 20} { > $i 0 } { decr i } {
incr val
}
checkthat $val == 20
}
test "eval tests" {
checkthat [eval {* 4 4}] == 16
assertNoErr { eval "" }
assertNoErr { eval " " }
assertErr { eval } # Eval needs 1 or more args
checkthat [eval * 4 4] == 16 # Eval concats multiple args
}
test "expr" {
checkthat [expr 4 + 4] == 8
checkthat [expr {4 + 4}] == 8
checkthat [expr {9 + (1 * 1)}] == 10
set x 10
checkthat [expr { $x + $x }] == 20
checkthat [expr { [+ 1 1] * 2 }] == 4
checkthat [expr { 3 < 4.5 }]
checkthat [expr { 3 <= 4.5 }]
checkthat [expr { 4.5 <= 4.5 }]
checkthat [expr { 4.5 == "4.5" }]
checkthat [expr { 4.5 != 4 }]
checkthat [expr { 4.9 > 2 }]
checkthat [expr { 4.9 >= 2 }]
checkthat [expr { 4.9 >= 4.9 }]
checkthat [expr { "one" eq "one" }]
checkthat [expr { "two" ne "one" }]
checkthat [expr { "1" eq 1 }]
}
test "set returns correctly" {
set babytime 444
checkthat [set babytime] == 444
checkthat [set babytime 512] == 512
checkthat $babytime == 512
}
test "errors and catch" {
assertErr { error "oh noes" }
checkthat [catch { puts "$thisdoesntexist" }] == 1
checkthat [catch { + 1 1 }] == 0
catch { set x [+ $x 4] } reason
checkthat $reason eq {can't read "x": no such variable}
set x 4
catch { incr x } result
checkthat $result == 5
}
test "catching return, break and continue" {
checkthat [catch return] == 2
checkthat [catch break] == 3
checkthat [catch continue] == 4
}
test "whitespace escaping" {
set x \
13
checkthat $x == 13
set boo \ redrum
checkthat $boo eq " redrum"
set lala \
checkthat $lala eq " "
}
test "int parsing" {
checkthat 1 != "1 2 3 4"
}
set whagganog ""
set otherthing ""
test "global test" {
proc testglobal {bah} {
proc modother { m } {
global whagganog otherthing
set otherthing $whagganog$m
}
global whagganog
append whagganog $bah
modother $bah
return $whagganog
}
checkthat [testglobal 1] == 1
checkthat $::otherthing == 11
checkthat [testglobal 2] == 12
checkthat $::otherthing == 122
}
unset whagganog
unset otherthing
test "parsing corners" {
checkthat [+ 15 -5] == 10 # Check that negatives parse.
set { shh.. ?} 425
checkthat " 425 " eq " ${ shh.. ?} "
checkthat "whee $ stuff" eq "whee \$ stuff"
checkthat "whee \$ stuff" eq "whee \$ stuff"
checkthat "whee \$\" stuff" eq "whee $\" stuff"
assertNoErr {
if { == 3 3 } { } else { die "bad" }
}
set x four
checkthat "$x: 4" eq "four: 4"
}
test "ns parsing with array lookup" {
assert_noerr {
set x(::) 4
set y $x(::)
}
}
test "equality of strings and nums" {
set x 10
set y " 10 "
checkthat $x == $y
checkthat $x ne $y
checkthat 33 eq 33
assert { == "cobra" "cobra" }
checkthat " 1 " ne 1
checkthat " 1 " == 1
assert { eq "cobra" "cobra" }
assert { == 4 4 }
}
test "equality 2" {
checkthat [list 1 2] eq "1 2"
checkthat [ne [list 1 2] {1 2}] eq 0
}
test "early return" {
set moo 4
finalize { proc yay } {
proc yay {} {
upvar moo moo2
return
set moo2 5
}
yay
checkthat $moo == 4
}
}
test "arg count check" {
proc blah {a b} {
+ $a $b
}
assertErr { blah 4 }
assertErr { blah 4 5 6 }
assertNoErr { blah 4 5 }
proc blah2 {a b args} {
+ $a [+ $b [llength $args]]
}
assertErr { blah2 1 }
assertErr { blah2 }
checkthat [blah2 1 2 3] == 4
checkthat [blah2 1 2] == 3
checkthat [blah2 1 2 1 1 1] == 6
}
test "bad continue/break test" {
proc whee {} {
break
}
assertErr { whee }
proc whee2 {} {
continue
}
assertErr { whee2 }
proc whee3 {} {
return
}
assertNoErr { whee3 }
}
test "incomplete parse" {
assertErr { set bean 4 " }
assertNoErr { set bean 4() }
assertErr { " }
}
test "default proc args" {
proc plus { t { y 1 } } {
+ $t $y
}
proc plus2 { x {y 1} } {
+ $x $y
}
proc plus3 { " a 5 " "b 1" } {
+ $a $b
}
proc weirdorder { { a1 "boo" } a2 } {
return $a1$a2
}
proc withargs { i {j 4} args } {
+ [llength $args] [+ $i $j]
}
checkthat [plus 3 3] == 6
checkthat [plus2 3 3] == 6
checkthat [plus3 3 3] == 6
checkthat [plus 3] == 4
checkthat [plus2 3] == 4
checkthat [plus3 3] == 4
checkthat [plus3] == 6
checkthat [weirdorder "xx" "yy"] eq "xxyy"
assertErr { weirdorder "xx" }
checkthat [withargs 1] == 5
checkthat [withargs 1 3] == 4
checkthat [withargs 1 3 1] == 5
checkthat [withargs 1 3 1 1 1 8 1] == 9
}
test "lone subcommand" {
proc id {x} { return $x }
set x 0
[id "set"] x 11
checkthat $x == 11
}
test "unset" {
set y 4
checkthat $y == 4
checkthat [info exists y] == 1
checkthat [unset y] eq ""
assertErr { incr y }
checkthat [info exists y] == 0
}
test "unset with upvar" {
proc unset_x {} {
with_test "in proc" {
upvar x boo
checkthat [info exists boo] == 1
checkthat $boo == 0
unset boo
checkthat [info exists boo] == 0
}
}
set x 0
checkthat $x == 0
checkthat [info exists x] == 1
unset_x
checkthat [info exists x] == 0
finalize { proc unset_x }
}
test "unset array elt" {
set x(4) 4
set x(5) 5
checkthat [array size x] == 2
checkthat $x(4) == 4
unset x(4)
checkthat [array size x] == 1
}
test "proc must be complete" {
assertErr { proc banana }
assertErr { proc banana { puts "banana" } }
assertNoErr { proc banana { } { puts "banana" } }
assertNoErr { proc banana {} { puts "banana" } }
}
test "rename" {
assertErr { rename one one_ }
proc one {} { return 1 }
checkthat [one] == 1
rename one one_
assertErr { one }
checkthat [one_] == 1
rename one_ ""
assertErr { one_ }
}
test "for loop 2" {
set val 0
for {set x 1} {< $x 10} {incr x} {
set val $x
}
checkthat $val == 9
checkthat $x == 10
for {set x 1} {< $x 10} {incr x} {
break
}
checkthat $x == 1
set val -1
for {set x 1} {< $x 10} {incr x} {
continue
set val $x
}
checkthat $val == -1
}
proc ignore _ { return {} }
proc no_ignore code { uplevel $code }
test "global ns proc" {
checkthat [::+ 1 1] == 2
checkthat [+ 1 1] == 2
}
test "switch" {
set x 4
switch $x {
1 { assertFail "bad switch" }
3 { assertFail "bad switch" }
4 { assertPass }
}
}
test "switch fallthrough" {
set x 4
switch $x {
1 { assertFail "bad switch" }
3 { assertFail "bad switch" }
4 -
5 { assertPass }
4 { assertFail "bad switch" }
}
set val 0
switch $x {
1 - 2 - 3 - 4 - 5 { incr val }
}
checkthat $val == 1
}
test "switch default" {
set res "failed"
set x 4
switch $x {
1 { assertFail "bad switch" }
3 { assertFail "bad switch" }
default { set res "worked" }
}
checkthat $res eq "worked"
}
test "switch return" {
set x 2
set result \
[switch $x {
1 { + 1 2 }
2 { + 2 2 }
3 { + 3 2 }
}]
checkthat $result == 4
}
test "switch exact" {
set x 4
switch -exact $x {
2 { assertFail "bad Switch" }
4 { assertPass }
default { assertFail "bad Swich" }
}
}
test "switch glob" {
set x been
switch -glob $x {
2 { assertFail "bad Switch1" }
b*d { assertFail "bad Switch2" }
b??n { assertPass }
been { assertFail "wtf" }
default { assertFail "bad Switch3" }
}
}
test "switch --" {
set x 4
switch -- $x {
2 { assertFail "bad Switch" }
4 { assertPass }
default { assertFail "bad Swich" }
}
}
test "expand" {
checkthat [+ {*}[list 1 1]] == 2
checkthat [+ {*}5 {*}5] == 10
set boo [list 3 3]
checkthat [list {*}$boo] eq $boo
checkthat [concat {*}$boo] eq "3 3"
}
test "list escaping" {
set x [list 1 2 3 \{ \} 6]
checkthat [llength $x] == 6
}
test "split" {
set res [split "one two three four"]
checkthat [llength $res] == 4
set res [split "comp.lang.misc.fuzzyx" ".x"]
checkthat [lindex $res 2] eq "misc"
checkthat [llength $res] == 5
checkthat [llength [split "Hey you" {}]] == 7
}
test "namespaces" {
set ::x 4
checkthat $::x == 4
unset ::x
assertErr { checkthat $::x == 4 }
}
test "exists and unset global" {
set ::gv 9
checkthat [info exists ::gv] == 1
unset ::gv
checkthat [info exists ::gv] == 0
}
test "incr global" {
set ::gv 1
incr ::gv
checkthat $::gv == 2
unset ::gv
}
test "set global" {
set ::x 4
checkthat [set ::x] == 4
unset ::x
}
test "unknown" {
set oops 0
set missed {}
rename banana ""
proc unknown {name args} {
uplevel {incr oops}
uplevel "set missed $name"
}
checkthat $oops == 0
banana 44
checkthat $oops == 1
checkthat $missed eq banana
rename unknown ""
}
test "uplevel issue" {
set level [info level]
catch { uplevel { error "Oh no" } }
checkthat [info level] == $level
}
test "global namespace" {
uplevel { set a_global 9 }
checkthat [info exists a_global] == 0
checkthat $::a_global == 9
uplevel { unset a_global }
}
test "namespace exists" {
checkthat [namespace exists imaginary] == 0
checkthat [namespace exists ::]
verify { namespace exists {} }
namespace eval boo {
checkthat [namespace exists ::]
checkthat [namespace exists {}] == 0 "empty doesn't exist when not in global"
}
}
test "ns level" {
finalize { namespace abc } {
set ::lev 0
namespace eval abc {
set ::lev [info level]
}
checkthat [info level] == [- $::lev 1]
unset ::lev
}
}
test "upvar in uplevel" {
proc set_to_3 vn {
upvar $vn x
set x 3
}
proc thingee {} {
uplevel { set_to_3 y }
}
set y 4
thingee
checkthat $y == 3
finalize { proc thingee proc set_to_3 }
}
test "upvar in uplevel 2" {
proc bind_to_x vn {
uplevel {
upvar $vn x
}
}
proc thingee vn {
bind_to_x $vn
set x 3
}
set y 4
thingee y
checkthat $y == 3
finalize { proc thingee proc bind_to_x }
}
test "procs declared in namespace global" {
proc ::woot {} { return 4545 }
checkthat [::woot] == 4545
}
test "procs declared in foo namespace" {
namespace eval foo {}
proc foo::ret5 {} { return 5 }
checkthat [foo::ret5] == 5
checkthat [::foo::ret5] == 5
proc ::foo::ret6 {} { return 6 }
checkthat [foo::ret6] == 6
checkthat [::foo::ret6] == 6
finalize { namespace foo }
}
test "proc in namespace that doesn't exist fails" {
assertErr {
proc foo::bar {} { return 1 }
}
assertErr {
proc ::foo::bar {} { return 1 }
}
namespace eval foo {}
assertNoErr {
proc foo::bar {} { return 1 }
}
finalize { namespace foo }
}
test "rename with ns qualifiers" {
namespace eval foo {
proc bar {} { return "omg!" }
}
assertNoErr { ::foo::bar }
rename ::foo::bar ::foo::baz
assertErr { ::foo::bar }
checkthat [::foo::baz] eq "omg!"
rename ::foo::baz whatnot
assertErr { ::foo::baz }
checkthat [whatnot] eq "omg!"
finalize { namespace foo proc whatnot }
}
test "uplevel in ns" {
set g 0
namespace eval foo {
uplevel { set g [namespace current] }
}
checkthat $g eq {::}
}
test "globally qualified proc in ns" {
namespace eval foo {
proc ::blah {} { return 4 }
}
assertErr { ::foo::blah }
assertNoErr { ::blah; blah }
assertNoErr {
namespace eval foo {
rename ::blah {}
}
}
assertErr { ::blah }
finalize { ns foo }
}
test "list eval" {
checkthat [eval [list * 3 5]] == 15
}
test "odd procs" {
set one [+ 1 0]
proc $one {} { return ONE }
checkthat [eval $one] eq ONE
set ffff [+ 55 0.55]
proc $ffff {} { return FFFF }
checkthat [eval $ffff] eq FFFF
finalize { proc 1 proc 55.55 }
}
run_tests