#$Id: testx.xotcl,v 1.9 2004/07/02 11:22:31 neumann Exp $ package require XOTcl namespace import -force xotcl::* proc ::errorCheck {got expected msg} { if {$got != $expected} { puts stderr "FAILED: $msg\nGot: $got\nExpected: $expected" foreach g $got e $expected { set result [expr {$g == $e}] if {[string length $g]>60} { puts "$result g='$g'\n e='$e'" } else { puts "$result g='$g' e='$e'" } } exit -1 } } proc ::cutSpaces {string} { regsub -all " " $string "" result regsub -all "\n" $result " " result return $result } Class TestX @ @File {description { This is a file which provides a regression test for the features of the XOTcl - Language. } } @ Class TestX TestX nestingClasses @ TestX nestingClasses { description {Regression test object testing the class nesting feature.} } nestingClasses proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { Class x($i) Class x($i)::y ::errorCheck [x($i) info commands y] "y" \ "[self] -- creating Nested Class " Class x($i)::z Class x($i)::z::t Class x($i)::t ::errorCheck [x($i) info classchildren] "::x($i)::t ::x($i)::y ::x($i)::z" \ "[self] -- info classchildren" ::errorCheck [x($i)::z info classparent] "::x($i)" \ "[self] -- info classparent" ::errorCheck [x($i) info commands t] "t" \ "[self] -- MakeClass " x($i) a x($i)::z a x($i)::z::t a x($i)::z::t move x($i)::z::rt x($i)::z::rt a ::errorCheck [x($i)::z info commands rt] "rt" \ "[self] -- renaming leaf " x($i)::z move x($i)::rz ::errorCheck [x($i) info commands rz] "rz" \ "[self] -- renaming node (node itself)" ::errorCheck [x($i)::rz info commands rt] "rt" \ "[self] -- renaming node (leaf in node)" ::errorCheck [x($i)::rz info classchildren] "::x($i)::rz::rt" \ "[self] -- info classchildren (2)" ::errorCheck [x($i)::rz::rt info classparent] "::x($i)::rz" \ "[self] -- info classparent (2)" x($i) move rx ::errorCheck [rx info commands rz] "rz" \ "[self] -- renaming root " ::errorCheck [info commands rx] "rx" \ "[self] -- renaming root " rx destroy } return "PASSED [self]" } TestX nestingObjects @ TestX nestingObjects { description {Regression test object testing the object nesting feature.} } nestingObjects proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { Class C($i) C($i) instproc testinstproc {} { return } C($i) o o proc testproc {} { return } o testproc; o testinstproc C($i) o::y ::errorCheck [o info commands y] "y" \ "[self] -- creating Nested Object " C($i) o::z C($i) o::z::t C($i) o::t ::errorCheck [o info children] "::o::t ::o::y ::o::z" \ "[self] -- info children" ::errorCheck [o::t info parent] "::o" \ "[self] -- info parent" ::errorCheck [o info commands t] "t" \ "[self] -- MakeObject " o::z::t move o::z::rt ::errorCheck [o::z info commands rt] "rt" \ "[self] -- renaming leaf " o::z move o::rz ::errorCheck [o::rz info commands rt] "rt" \ "[self] -- renaming node " ::errorCheck [o info commands rz] "rz" \ "[self] -- renaming node " o move rx ::errorCheck [rx info commands rz] "rz" \ "[self] -- renaming root " ::errorCheck [info commands rx] "rx" \ "[self] -- renaming root " rx destroy C($i) destroy Class A A instproc x {a1 args} { my set var $a1 } A a A a::n -x "1 2 3" ::errorCheck [::a::n set var] "1 2 3" \ "[self] -- arg passing - init dash" } return "PASSED [self]" } TestX assertions @ TestX assertions { description {Regression test object testing the assertions.} } assertions proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { Class C($i) C($i) invar { {$a > 2} {$c < 3} {$d > 5} {#a} {#b} } C($i) instinvar { {$a > 2} {$c < 3} {$d > 5} {#a} {#b} } ::errorCheck [C($i) info invar] {{$a > 2} {$c < 3} {$d > 5} {#a} {#b}} \ "[self] -- Class invar " ::errorCheck [C($i) info invar] {{$a > 2} {$c < 3} {$d > 5} {#a} {#b}} \ "[self] -- Class instinvar " Object b($i) b($i) invar { {$a > 2} {$c < 3} {$d > 5} {#a} {#b} } ::errorCheck [C($i) info invar] {{$a > 2} {$c < 3} {$d > 5} {#a} {#b}} \ "[self] -- Object invar " b($i) proc p {a b c} { return p } {pre1 pre2 pre3} {post1 post2 post3} ::errorCheck [b($i) info pre p] {{pre1} {pre2} {pre3}} \ "[self] -- Obj proc pre assertion " ::errorCheck [b($i) info post p] {{post1} {post2} {post3}} \ "[self] -- Obj proc post assertion " C($i) instproc p {a b c} { return p } {} {post1 post2 post3} ::errorCheck [C($i) info instpre p] "" \ "[self] -- CL proc pre assertion " ::errorCheck [C($i) info instpost p] {{post1} {post2} {post3}} \ "[self] -- CL proc post assertion " C(0) set a 3; C(0) set c 2; C(0) set d 7; C(0) set f 50; C(0) check all C(0) proc checkit {} { C(0) instvar a c d f ::errorCheck [my info check] {invar instinvar pre post} \ "check options != all" # turn obj-invar off C(0) check {pre post instinvar} C(0) set c 10 ::errorCheck [my info check] {instinvar pre post} \ "check options != instinvar pre post" } {{$f > 10}} {{$f < 100}} C(0) checkit } for {set i 0} {$i < $n} {incr i} { b($i) destroy C($i) destroy } Object b b proc p {a b c} { return p } {pre1 pre2 pre3} {post1 post2 post3} ::rename b a ::errorCheck [a info pre p] {{pre1} {pre2} {pre3}} \ "[self] -- Obj proc pre assertion " ::errorCheck [a info post p] {{post1} {post2} {post3}} \ "[self] -- Obj proc post assertion " Class Sensor -parameter {{value 1}} Sensor instinvar { {[regexp {^[0-9]$} [my value]] == 1} } Sensor s s check all Sensor instproc x {} { s value } { {[regexp {^[0-9]$} [my value]] == 1} } {} s x s value # inheritance Class A -parameter {{x 1} {y 1}} A instinvar {{$x == 1}} A instproc xTo2 args { my set x 2 } A instproc yTo2 args { my set y 2 } {} {{$y == 1}} A a -check all if {![catch {a xTo2} err]} { set err "ok" } else { a check {} a set x 1 a check all } ::errorCheck $err {Assertion failed check: {$x == 1} in proc 'xTo2'} \ "[self] inheritance a xTo2" if {![catch {a yTo2} err]} { set err "ok" } ::errorCheck $err {Assertion failed check: {$y == 1} in proc 'yTo2'} \ "[self] inheritance a yTo2" Class B -superclass A B b -check all if {![catch {b xTo2} err]} { set err "ok" } else { b check {} b set x 1 b check all } ::errorCheck $err {Assertion failed check: {$x == 1} in proc 'xTo2'} \ "[self] inheritance b xTo2" if {![catch {b yTo2} err]} { set err "ok" } ::errorCheck $err {Assertion failed check: {$y == 1} in proc 'yTo2'} \ "[self] inheritance b yTo2" return "PASSED [self]" } TestX filterAddRemove @ TestX filterAddRemove { description {Regression test object testing adding/removing of filters.} } filterAddRemove proc run {{n 20}} { set ::filterCount 0 for {set i 0} {$i < $n} {incr i} { Class SA($i) Class SB($i) Class SC($i) -superclass [list SB($i) SA($i)] SA($i) instproc fa args { incr ::filterCount my set x 150 return "[next]-[self class]::[self proc]" } SA($i) instproc f2 args { incr ::filterCount my set x 150 return "[next]-[self class]::[self proc]" } SB($i) instproc f2 args { incr ::filterCount my set x 150 return "[next]-[self class]::[self proc]" } SB($i) instproc fb args { incr ::filterCount my set x 150 return "[next]-[self class]::[self proc]" } SC($i) instproc fc args { incr ::filterCount my set x 150 return "[next]-[self class]::[self proc]" } SC($i) instfilter fc SB($i) instfilter {fb f2} SA($i) instfilter {fa f2} Class T T proc s {} { return } Class Filtered${i} -superclass SC($i) Filtered${i} instproc testfilter args { incr ::filterCount T s return "[next]-[self class]::[self proc]" } Filtered${i} instfilter testfilter Filtered${i} instproc a args { return "in a" } Filtered${i} f${i} set erg [f${i} a] ::errorCheck $erg \ "in a-::SA(${i})::f2-::SA(${i})::fa-::SB(${i})::f2-::SB(${i})::fb-::SC(${i})::fc-::Filtered${i}::testfilter" \ "[self] -- Filter Test - add" SC($i) instfilter {} SB($i) instfilter fb SA($i) instfilter {} set erg [f${i} a] ::errorCheck $erg "in a-::SB(${i})::fb-::Filtered${i}::testfilter" \ "[self] -- Filter Test - remove" f${i} proc procFilter args { return "[next]-[self class]::[self proc]" } f${i} filter {fa f2 procFilter} set erg [f${i} a] ::errorCheck $erg "in a-::SB(${i})::fb-::Filtered${i}::testfilter-::procFilter-::SB(${i})::f2-::SA(${i})::fa" \ "[self] -- Obj Filter Test call three filter + instfilter" ::errorCheck "[f${i} info filter]-[SB($i) info instfilter]-[SC($i) info instfilter]" \ "fa f2 procFilter-::SB(${i})::fb-::Filtered${i}::testfilter-::procFilter-::SB(${i})::f2-::SA(${i})::fa-fb-"\ "[self] -- filter infos" ::errorCheck [f${i} filtersearch fa]-[f${i} filtersearch fb]-[f${i} filtersearch procFilter] "::SA(${i}) instproc fa-::SB(${i})::fb-::Filtered${i}::testfilter-::procFilter-::SB(${i})::f2-::SA(${i})::fa-::SB(${i}) instproc fb-::SB(${i})::fb-::Filtered${i}::testfilter-::procFilter-::SB(${i})::f2-::SA(${i})::fa-::f${i} proc procFilter-::SB(${i})::fb-::Filtered${i}::testfilter-::procFilter-::SB(${i})::f2-::SA(${i})::fa" "[self] -- filtersearch" Filtered${i} instfilter {} SB($i) instfilter {} set erg [f${i} a] ::errorCheck $erg "in a-::procFilter-::SB(${i})::f2-::SA(${i})::fa" \ "[self] -- only obj filter" f${i} filter {} set erg [f${i} a] ::errorCheck $erg "in a" \ "[self] -- obj filter remove" } for {set i 0} {$i < $n} {incr i} { SA($i) destroy SB($i) destroy SC($i) destroy } ::errorCheck $::filterCount 960 \ "[self] -- Filter Test - Filter Count -- Got: $::filterCount" # # instvar test # global filterResult set filterResult "" Object a a set o 12 a set p 13 Class A A set m 14 Object instproc f args { global filterResult a instvar o p A instvar m ::append filterResult " [self] [self calledproc] [self callingproc]" ::append filterResult " $o $p $m" next } proc x {} { set ::a::e xxx } Object instfilter f x ::errorCheck $::a::e xxx \ "filterAddRemove: instvar test -- proc set failed" a set e yyy ::errorCheck $::a::e yyy \ "filterAddRemove: instvar test -- obj set failed" ::errorCheck $filterResult " ::A instvar f 12 13 14 ::a set run 12 13 14" \ "filterAddRemove: instvar test -- instvar filter failed" Object instfilter "" Object instproc f args { next } Object instfilter f ::errorCheck [Object o] "::o" \ "filterAddRemove: Object creation with filter" # This produces a bug, if not # RUNTIME_STATE(in)->returnCode = TCL_OK; # in ObjDispatch -> UNKNOWN handling */ # abrupt stop of program because result is set to XOTCL_UNKNOWN # instead of TCL_ERROR, as it should be catch {puts ${ZZZZZZZZZZZZZZZ::ZZZZZ}} o set r 43 ::errorCheck [o set r] "43" \ "filterAddRemove: Object creation with filter: setting var" Object instfilter "" # test for CmdListReplaceCmd set ::r "" Class A A instproc f2 args {lappend ::r [self class]-[self proc]; next} Class C -superclass A Class D -superclass C D instfilter {f2} D d d filter {f2} C instproc f2 args {lappend ::r [self class]-[self proc]; next} set ::r "" d set r 1 ::errorCheck $::r "::C-f2 ::A-f2" \ "filter method addition" return "PASSED [self]" } TestX filterClassChange @ TestX filterClassChange { description {Regression test object testing class changes of filters.} } filterClassChange proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { Class A($i) Class B A($i) instproc f args { set result pre*[self]*[self proc]*$args lappend result [next] post*[self]*[self proc] return $result } A($i) o($i) o($i) proc change {} { my class B } o($i) proc call {} { return in-call } A($i) instfilter f set erg [o($i) call] ::errorCheck $erg "pre*::o($i)*f* in-call post*::o($i)*f" \ "[self] -- Filter Class Change -- Call before change" o($i) change set erg [o($i) call] ::errorCheck $erg "in-call" \ "[self] -- Filter Class Change -- Call after change" # testing deleting a filter proc Class F F instproc testf args {return filtered} F instfilter testf F f1 ::errorCheck [f1 set r 45] "filtered" "Deleting a filter proc ... before" F instproc testf {} {} ::errorCheck [f1 set r 45] "45" "Deleting a filter proc ... after" # testing deleting a superclass Class F1 Class F2 -superclass F1 Class F3 -superclass F2 F1 instproc testf args {return [next]-filtered} F2 instproc testf2 args {return [next]-filtered} F3 instfilter {testf testf2} F3 f2 ::errorCheck [f2 filtersearch testf2] "::F2 instproc testf2-filtered-filtered" "[self]: filtersearch 2" ::errorCheck [f2 set r 45] "45-filtered-filtered" \ "Deleting a superclass ... before" F3 superclass [F1 info superclass] ::errorCheck [f2 set r 45] "45" "Deleting a superclass ... after" } B destroy for {set i 0} {$i < $n} {incr i} {A($i) destroy} return "PASSED [self]" } TestX filterGuards @ TestX filterGuards { description {Regression test object testing filter guards.} } filterGuards proc run {{n 20}} { global filterResult for {set i 0} {$i < $n} {incr i} { set ::filterResult "" Class A A instproc f2 args { global filterResult append filterResult "-[self]-[self proc]-[self class]-[self calledproc]" next } Class B -superclass A B instproc f1 args { global filterResult append filterResult "-[self]-[self proc]-[self class]-[self calledproc]" next } B instproc f3 args { global filterResult append filterResult "-[self]-[self proc]-[self class]-[self calledproc]" next } B instfilter {{f1 -guard "1<0"}} B b ::errorCheck $filterResult "" \ "[self] -- Filter guard: Filter never to be applied" b destroy A instproc f1 args { global filterResult append filterResult "-[self]-[self proc]-[self class]-[self calledproc]" next } set filterResult "" B b ::errorCheck $filterResult "" \ "[self] -- Filter guard: Filter never to be applied + filter inheritance on this filter" # filter w/o guard -> has to be applied A instfilter f1 b destroy set filterResult "" B b ::errorCheck $filterResult "-::b-f1-::A-configure-::b-f1-::A-init" \ "[self] -- Filter guard: two different filters, same name + different class, one guarded, one not" # two filter w/o guard -> both have to be applied B instfilter f1 b destroy set filterResult "" B b ::errorCheck $filterResult "-::b-f1-::B-configure-::b-f1-::A-configure-::b-f1-::B-init-::b-f1-::A-init" \ "[self] -- Filter guard: two different filters, both not guarded anymore" # three filters with guards, not to be applied, in one chain b destroy A instfilter {} B instfilter {{f1 -guard {0}} {f3 -guard {0}} {f2 -guard {0}}} set filterResult "" B b ::errorCheck $filterResult "" "[self] -- Filter guard: three filters in one chain" # three times the same filter --> guards are and-combined set filterResult "" B instfilter {{f2 -guard {[self calledproc] == "set" || [self] == "::b2"}}} A instfilter {{f2 -guard {[self] == "::b2"}}} B b1 B b2 if {$i == 0} { ::errorCheck $filterResult "-::b2-f2-::A-configure-::b2-f2-::A-init" \ "[self] -- Filter guard: creation with less restrictive guards" } else { ::errorCheck $filterResult "-::b2-f2-::A-cleanup-::b2-f2-::A-configure-::b2-f2-::A-init" \ "[self] -- Filter guard: creation with less restrictive guards (b)" } set filterResult "" b1 set x 45 ::errorCheck $filterResult "-::b1-f2-::A-set" \ "[self] -- Filter guard: setting restricted object" set filterResult "" b1 info class ::errorCheck $filterResult "" \ "[self] -- Filter guard: info restricted object (no guard applies)" set filterResult "" b2 info class ::errorCheck $filterResult "-::b2-f2-::A-info" \ "[self] -- Filter guard: setting restricted object (2nd guard applies)" b1 filter {{f2 -guard {[self calledproc] == "info"}}} set filterResult "" b1 proc a {} { # } ::errorCheck $filterResult "" \ "[self] -- Filter guard: proc on restricted object (no guard applies)" set filterResult "" b1 info class ::errorCheck $filterResult "-::b1-f2-::A-info" \ "[self] -- Filter guard: info filtered by object filter guard" # checking infos ::errorCheck [b1 info filterguard f2]-[B info instfilterguard f2]-[A info instfilterguard f2] \ {[self calledproc] == "info"-[self calledproc] == "set" || [self] == "::b2"-[self] == "::b2"} \ "[self] -- Filter guard: info filtered by object filter guard" # checking info -guards option Class A A instproc f1 args {next} A instproc fx args {next} Class B -superclass A B instproc f1 args {next} B instproc f2 args {next} B b B instfilter {{f1 -guard {[self] == "::b"}} {f2 -guard 0} f1} b filter {{f1 -guard {[self] == "::b"}} {f2 -guard 0}} ::errorCheck [B info instfilter]-[B info instfilter -guards]-[b info filter]-[b info filter -guards] \ {f1 f2-f1 {f2 -guard 0}-f1 f2-{f1 -guard {[self] == "::b"}} {f2 -guard 0}}\ {[self] -- Filter guard: -guards option} A instfilter {f1 fx} A a a proc x args {next} a filter x ::errorCheck [b info filter -order]-[a info filter -order] "{::B instproc f1} {::B instproc f2} {::A instproc f1} {::A instproc fx}-{::a proc x} {::A instproc f1} {::A instproc fx}" \ {[self] -- Filter guard: -order option} ::errorCheck [b info filter -order -guards]-[a info filter -order -guards] {{f1 -guard {[self] == "::b"}} {f2 -guard 0} f1 fx-x f1 fx} \ {[self] -- Filter guard: -order -guards options} Class Foo Foo instproc init {args} {my set bar hello} Foo instproc baz {args} { my instvar bar return $bar } Foo instproc myFilter {args} { lappend ::r myFilter->[self calledproc] my set r 4 next } Foo instfilter myFilter Foo instfilterguard myFilter { ([self calledproc] == "baz") } Foo instfilterguard myFilter { ([self calledproc] == "baz") } set f [Foo new] $f baz ::errorCheck [$f baz] "hello" \ {[self] -- Filter guard from method call} Foo instfilterguard myFilter {} set ::r "" Foo create f f filter myFilter f filterguard myFilter { ([self calledproc] == "baz") } lappend ::r [f baz] [f set r 1] f filterguard myFilter {} lappend ::r [f baz] [f set r 1] ::errorCheck $::r [list myFilter->configure myFilter->init \ myFilter->set myFilter->filter \ myFilter->filterguard myFilter->baz \ hello 1 myFilter->baz \ myFilter->instvar myFilter->set hello 1] \ {[self] -- Filter guard from method call} f destroy Class Room Room instproc open {} {lappend ::r [self proc]} Room instproc x {} {lappend ::r [self proc]} Room instproc loggingFilter args { lappend ::r [self proc]-[self calledproc] next } Room instproc callsMethod {method calledproc} { return [string match $calledproc $method] } Room instproc callsLevel2 {} { set level [self guardedlevel] lappend ::r $level set calledproc [uplevel $level self calledproc] lappend ::r $calledproc } Room instfilter loggingFilter Room instfilterguard loggingFilter {[my callsMethod open [self calledproc]]} Room r set ::r "" r open r x ::errorCheck $::r "loggingFilter-open open x" \ {[self] -- info guarded scope} } return "PASSED [self]" } TestX mixinGuards @ TestX mixinGuards { description {Regression test object testing mixin guards.} } mixinGuards proc run {{n 20}} { set ::r "" Class Fly Fly instproc fly {} {lappend ::r "[my signature]: yippee, fly like an eagle!"} Class Sing Sing instproc sing {} {lappend ::r "[my signature]: what a difference a day make"} Class Animal -parameter age Animal instproc unknown args { lappend ::r "[my signature]: how should i $args?"} Animal instproc signature {} { return "[self] [my info class] ([my age] years)" } Class Bird -superclass Animal Class Penguine -superclass Bird Class Parrot -superclass Bird Class Duck -superclass Bird Parrot tweedy -age 1 Penguine pingo -age 5 Duck donald -age 4 Parrot lora -age 6 Bird instmixin {{Fly -guard {[my age]>2 && ![my istype Penguine]}} Sing} foreach bird {tweedy pingo donald lora} { $bird fly } ::errorCheck [set ::r] [list \ {::tweedy ::Parrot (1 years): how should i fly?} \ {::pingo ::Penguine (5 years): how should i fly?} \ {::donald ::Duck (4 years): yippee, fly like an eagle!} \ {::lora ::Parrot (6 years): yippee, fly like an eagle!}] \ {[self] -- Simple Instmixin Guard} set ::r "" tweedy age 3 pingo class Duck lora class Penguine foreach bird {tweedy pingo donald lora} { $bird fly } ::errorCheck [set ::r] [list \ {::tweedy ::Parrot (3 years): yippee, fly like an eagle!} \ {::pingo ::Duck (5 years): yippee, fly like an eagle!} \ {::donald ::Duck (4 years): yippee, fly like an eagle!} \ {::lora ::Penguine (6 years): how should i fly?}] \ {[self] -- Simple Instmixin Guard ... Class Change} set ::r "" pingo mixin {{Fly -guard {[my age]>2}} Sing} foreach i { {Bird info instmixin -guards} {pingo info mixin -guards} {pingo info mixin -order -guards}} { lappend ::r "$i [eval $i]" } ::errorCheck [set ::r] [list \ {Bird info instmixin -guards {::Fly -guard {[my age]>2 && ![my istype Penguine]}} ::Sing} \ {pingo info mixin -guards {::Fly -guard {[my age]>2}} ::Sing} \ {pingo info mixin -order -guards {::Fly -guard {[my age]>2}} ::Sing}] \ {[self] -- Simple Instmixin Guard ... Info} set ::r "" Class POM-start Class POM-end Class PCM-start Class PCM-end pingo mixin {POM-start {Fly -guard {[my age]>2}} Sing POM-end} Bird instmixin {PCM-start {Fly -guard {[my age]>2 && ![my istype Penguine]}} Sing PCM-end} pingo class Penguine foreach i { {Bird info instmixin -guards} {pingo info mixin -guards} {pingo info mixin -order -guards}} { lappend ::r "$i [eval $i]" } ::errorCheck [set ::r] [list \ {Bird info instmixin -guards ::PCM-start {::Fly -guard {[my age]>2 && ![my istype Penguine]}} ::Sing ::PCM-end} \ {pingo info mixin -guards ::POM-start {::Fly -guard {[my age]>2}} ::Sing ::POM-end} \ {pingo info mixin -order -guards ::POM-start ::POM-end ::PCM-start {::Fly -guard {[my age]>2}} ::Sing ::PCM-end}] \ {[self] -- Same Mixin Guard ... Info} set ::r "" pingo fly ::errorCheck [set ::r] [list \ {::pingo ::Penguine (5 years): yippee, fly like an eagle!}] \ {[self] -- Same Mixin Guard ... most specific counts} set ::r "" Animal a -set age 20 a mixin Fly a mixinguard ::Fly {[my age] > 3} a fly lappend ::r [a info mixin -guards] lappend ::r [a info mixin -order -guards] a set age 2 a fly a mixinguard ::Fly {[my age] > 4} a fly set info "" lappend info [a info mixinguard Fly] lappend ::r [a info mixin -guards] lappend ::r [a info mixin -order -guards] a mixinguard ::Fly {} a fly lappend ::r [a info mixin -guards] lappend info [a info mixinguard Fly] lappend ::r [a info mixin -order -guards] ::errorCheck [set ::r] [list \ {::a ::Animal (20 years): yippee, fly like an eagle!} \ {{::Fly -guard {[my age] > 3}}} {{::Fly -guard {[my age] > 3}}} \ {::a ::Animal (2 years): how should i fly?} \ {::a ::Animal (2 years): how should i fly?} \ {{::Fly -guard {[my age] > 4}}} {{::Fly -guard {[my age] > 4}}} \ {::a ::Animal (2 years): yippee, fly like an eagle!} \ ::Fly ::Fly] \ {mixinguard method} set ::r "" Class A -superclass Animal A a -set age 20 A instmixin Fly A instmixinguard ::Fly {[my age] > 3} lappend info [A info instmixinguard ::Fly] a fly lappend ::r [A info instmixin -guards] lappend ::r [a info mixin -order -guards] a set age 2 a fly A instmixinguard ::Fly {[my age] > 4} lappend info [A info instmixinguard ::Fly] a fly lappend ::r [A info instmixin -guards] lappend ::r [a info mixin -order -guards] A instmixinguard ::Fly {} lappend info [A info instmixinguard ::Fly] a fly lappend ::r [A info instmixin -guards] lappend ::r [a info mixin -order -guards] ::errorCheck [set ::r] [list \ {::a ::A (20 years): yippee, fly like an eagle!} \ {{::Fly -guard {[my age] > 3}}} {{::Fly -guard {[my age] > 3}}} \ {::a ::A (2 years): how should i fly?} \ {::a ::A (2 years): how should i fly?} \ {{::Fly -guard {[my age] > 4}}} {{::Fly -guard {[my age] > 4}}} \ {::a ::A (2 years): yippee, fly like an eagle!} \ ::Fly ::Fly] \ {instmixinguard method} ::errorCheck [set info] [list {[my age] > 4} {} {[my age] > 3} \ {[my age] > 4} {} ] {info (inst)mixinguard} return "PASSED [self]" } TestX filterSimpleObserver @ TestX filterSimpleObserver { description {Regression test object testing a simple observer using filters.} } filterSimpleObserver proc run {{n 20}} { set ::filterCount 0 for {set i 0} {$i < $n} {incr i} { Class NetAccess$i Class Http$i -superclass NetAccess$i Class TransferDialog$i TransferDialog$i proc addObserver cl { $cl instproc observerFilter args { set calledMethod [self calledproc] set callingClass [my info class] incr ::filterCount set result [next] my set r 34 foreach var {args calledMethod callingClass result} { if {[info vars $var] != $var} { puts stderr "[self] -- Simple Observer - info vars in filter" exit } } return [self]-[self class]-[my info class]-$args-[self calledproc]-[self callingproc]-$result } $cl instfilter observerFilter } TransferDialog$i instproc show {i} { next TransferDialog${i} addObserver NetAccess$i [self class] instvar observingObjects lappend observingObjects(::NetAccess$i) [self] } Http$i parameter {a be bu} Http$i instproc path x { my set path $x } Http$i instproc query x { my set [self proc] $x } Http$i instproc init {args} { my set url abc next my instvar query path bu if {![info exists query] || ![info exists path] || ![info exists bu] || $query != "q"} { puts stderr "FAILED - [self] -- Simple Observer - Variable Init"; exit } } Http$i instproc GET {x} { my instvar query url path if {[info exists query]} { append url ?$query append path ?$query } set ::baseLevel [info level] if {0 != [expr [info level] - $::baseLevel]} { puts stderr "FAILED - [self] -- Simple Observer - info level in filtered proc\n\ expected 0, got [expr [info level] - $::baseLevel]" exit } foreach var {x path query url} { if {[info vars $var] != $var} { puts stderr "FAILED - [self] -- Simple Observer - info vars in filtered proc"; exit } } return $url } TransferDialog$i t($i) t($i) show $i Http$i h($i) -query q -path p -bu b set erg [h($i) GET 1] ::errorCheck $erg "::h($i)-::NetAccess$i-::Http$i-1-GET-run-abc?q" \ "[self] -- Simple Observer - Filter Return" } for {set i 0} {$i < $n} {incr i} { NetAccess$i instfilter {} h($i) destroy t($i) destroy Http$i destroy NetAccess$i destroy TransferDialog$i destroy } ::errorCheck $::filterCount 220 \ "[self] -- Simple Observer - Filter Count" return "PASSED [self]" } TestX stdargs @ TestX stdargs { description { Regression test object testing the ability of the next primitive to pass arguments without naming them. } } stdargs proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { Class C Class D Class A -superclass {C D} Class B -superclass A C instproc t {} { next return } D instproc t args { ::errorCheck $args "" \ "[self] -- --noArgs" next return } A instproc t {a b args} { if {$a != 1 || $b != 2 || $args != {3 4 5 6 7 8 9}} { puts stderr "FAILED - [self] -- StdArgs not computed"; exit } next --noArgs return } B instproc t {a b args} { if {$a != 1 || $b != 2 || $args != {3 4 5 6 7 8 9}} { puts stderr "FAILED -[self] -- StdArgs not computed"; exit } next return } B x x t 1 2 3 4 5 6 7 8 9 } foreach o {x A B C D} {$o destroy} return "PASSED [self]" } TestX filterInfo @ TestX filterInfo { description{ Regression test object testing introspection of filters. } } # Helper Procs proc ::showStack {{m 100}} { set r "" set max [info level] if {$m<$max} {set max $m} for {set i 0} {$i < $max} {incr i} { set r ${r}-$i=[info level [expr -$i]] } return $r } proc ::showCall {} { set n "" for {set level -1} {1} {incr level -1} { set p [info level $level] if {[lindex $p 0] == "next"} {set n "next:"} break } return [showStack] } filterInfo proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { global FInfo set FInfo "" Class FI FI proc addFilter {classname} { $classname instproc infoFilter args { global FInfo lappend FInfo \ [list callingclass [self callingclass] \ filterreg [self filterreg] \ callingobject [self callingobject] \ callingproc [self callingproc] \ calledproc [self calledproc]] set r [next] lappend FInfo \ [list self [self] proc [self proc] class [self class] \ infoclass [my info class] r $r] return $r } $classname instfilter infoFilter } Class C0 FI addFilter C0 C0 instproc m1 {} { my instvar aa bb cc set cc 1 } Class C1 -superclass C0 C1 instproc init args { my set a 1 my set c 22 next } C1 instproc m1 args { set r [next] my instvar a b cc return $r--${a}--[set cc] } set safedObjFilters [Object info filter] Object instfilter "" C1 c1 Object instfilter $safedObjFilters if {$i == 0} { ::errorCheck "$FInfo" \ "{callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc configure} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 0} {callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc init} {callingclass ::C1 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc init calledproc set} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 1} {callingclass ::C1 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc init calledproc set} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 22} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r {}}" \ "Wrong filtering of instproc creation C/C1" } else { ::errorCheck "$FInfo" \ "{callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc cleanup} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r {}} {callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc configure} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 0} {callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc init} {callingclass ::C1 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc init calledproc set} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 1} {callingclass ::C1 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc init calledproc set} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 22} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r {}}" \ "Wrong filtering of instproc creation C/C1 (b)" } set FInfo "" set result [c1 m1] ::errorCheck "$FInfo" \ "{callingclass {} filterreg {::C0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc m1} {callingclass ::C0 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc m1 calledproc instvar} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r {}} {callingclass ::C1 filterreg {::C0 instfilter infoFilter} callingobject ::c1 callingproc m1 calledproc instvar} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r {}} {self ::c1 proc infoFilter class ::C0 infoclass ::C1 r 1--1--1}" \ "Wrong filtering of c1 m1" set FInfo "" ::errorCheck "$result" \ "1--1--1" "Wrong return result of Filter Example 2 'c1 m1' " Class T0 FI addFilter T0 T0 instproc m {} { set e -0=showStack-1=showCall-2=m-3=m-4=m-5=run-6=run if {[string first $e [showCall]] == -1} { puts stderr "FAILED - Wrong calling stack in T0 m: [showCall]" puts stderr "expected = '$e'" puts stderr "got = '[showCall]'" exit } return [self]-[self proc]-[self class]-[my info class] } Class T1 -superclass T0 T1 instproc m {} { set e 0=showStack-1=showCall-2=m-3=m-4=run-5=run if {[string first $e [showCall]] == -1} { puts stderr "FAILED - Wrong calling stack in T1 m: [showCall]" puts stderr "expected = '$e'" puts stderr "got = '[showCall]'" exit } set r1 before-[self]-[self proc]-[self class]-[my info class] set r2 [next] set r after-[self]-[self proc]-[self class]-[my info class]-${r1}-$r2 } T1 t set FInfo "" set result [t m] ::errorCheck "$FInfo" \ "{callingclass {} filterreg {::T0 instfilter infoFilter} callingobject ::filterInfo callingproc run calledproc m} {callingclass ::T1 filterreg {::T0 instfilter infoFilter} callingobject ::t callingproc m calledproc info} {self ::t proc infoFilter class ::T0 infoclass ::T1 r ::T1} {callingclass ::T0 filterreg {::T0 instfilter infoFilter} callingobject ::t callingproc m calledproc info} {self ::t proc infoFilter class ::T0 infoclass ::T1 r ::T1} {callingclass ::T1 filterreg {::T0 instfilter infoFilter} callingobject ::t callingproc m calledproc info} {self ::t proc infoFilter class ::T0 infoclass ::T1 r ::T1} {self ::t proc infoFilter class ::T0 infoclass ::T1 r after-::t-m-::T1-::T1-before-::t-m-::T1-::T1-::t-m-::T0-::T1}" \ "Wrong filtering of t m" set FInfo "" ::errorCheck "$result" \ "after-::t-m-::T1-::T1-before-::t-m-::T1-::T1-::t-m-::T0-::T1" \ "Wrong return result of Filter Example 2 \"t m\" " } c1 destroy for {set i 0} {$i < $n} {incr i} { global InfoTraceResult Object InfoTrace InfoTrace proc createInfoTrace cl { $cl instproc infoTraceFilter args { global InfoTraceResult ::set r [next] ::lappend InfoTraceResult [list \ $r-[self]-[self proc]-[self class] \ [my info class]-[self calledproc] \ [self callingproc]-[self callingobject] \ [self callingclass]-[self filterreg]] return $r } $cl instfilter infoTraceFilter } Class ObjectsClass ObjectsClass anObject Class aClass ObjectsClass instproc aProc {} {aClass create anotherObject} InfoTrace createInfoTrace Object set InfoTraceResult "" set r [anObject aProc] if {$i > 0} { ::errorCheck $InfoTraceResult \ "{-::anotherObject-infoTraceFilter-::xotcl::Object ::aClass-cleanup aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {-::xotcl::Class::Parameter-infoTraceFilter-::xotcl::Object ::xotcl::Class-searchDefaults aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {0-::anotherObject-infoTraceFilter-::xotcl::Object ::aClass-configure aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {-::anotherObject-infoTraceFilter-::xotcl::Object ::aClass-init aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {anotherObject-::aClass-infoTraceFilter-::xotcl::Object ::xotcl::Class-recreate aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {::anotherObject-::aClass-infoTraceFilter-::xotcl::Object ::xotcl::Class-create aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {::anotherObject-::anObject-infoTraceFilter-::xotcl::Object ::ObjectsClass-aProc run-::filterInfo {-::xotcl::Object instfilter infoTraceFilter}}" \ "FilterInfo InfoTrace: Filter information wrong (b)" } else { ::errorCheck $InfoTraceResult \ "{::anotherObject-::aClass-infoTraceFilter-::xotcl::Object ::xotcl::Class-alloc aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {-::xotcl::Class::Parameter-infoTraceFilter-::xotcl::Object ::xotcl::Class-searchDefaults aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {0-::anotherObject-infoTraceFilter-::xotcl::Object ::aClass-configure aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {-::anotherObject-infoTraceFilter-::xotcl::Object ::aClass-init aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {::anotherObject-::aClass-infoTraceFilter-::xotcl::Object ::xotcl::Class-create aProc-::anObject {::ObjectsClass-::xotcl::Object instfilter infoTraceFilter}} {::anotherObject-::anObject-infoTraceFilter-::xotcl::Object ::ObjectsClass-aProc run-::filterInfo {-::xotcl::Object instfilter infoTraceFilter}}" \ "FilterInfo InfoTrace: Filter information wrong" } Object instfilter {} } global fUplevelResult set fUplevelResult "" Class FilterMix FilterMix instproc calls args { global fUplevelResult set calledproc [uplevel 1 {self calledproc}] set calledclass [uplevel 1 {self calledclass}] append fUplevelResult "-[self class]-[self proc]-$calledproc-$calledclass" } Class FilterCL -instmixin FilterMix FilterCL instproc filterA args { global fUplevelResult append fUplevelResult -[self class]-[self proc]-[self calledproc]-[self calledclass] my calls next } FilterCL instproc fclproc args {} FilterCL instfilter filterA FilterCL fcl fcl fclproc # ::errorCheck $fUplevelResult "-::FilterCL-filterA-configure-::xotcl::Object-::FilterMix-calls-configure-::xotcl::Object-::FilterCL-filterA-init-::xotcl::Object-::FilterMix-calls-init-::xotcl::Object-::FilterCL-filterA-fclproc-::FilterCL-::FilterMix-calls-fclproc-::FilterCL" "Filter/Mixin Info Uplevel Test" return "PASSED [self]" } TestX nextTest @ TestX nextTest { description { Regression test object testing the next primitive. } } nextTest proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { global result infoNext set result "" set infoNext "" Class X X instproc n {} { append ::infoNext " [self]+[self class]->[self proc]*<[self next]>" next } Class Y -superclass X Y instproc m {} { append ::infoNext " [self]+[self class]->[self proc]*<[self next]>" next } Y instproc n {} { append ::infoNext " [self]+[self class]->[self proc]*<[self next]>" next } Y y y m y n y proc n {} { append ::infoNext " [self]+[self class]->[self proc]*<[self next]>" next } y n ::errorCheck $infoNext " ::y+::Y->m*<> ::y+::Y->n*<::X instproc n> ::y+::X->n*<> ::y+->n*<::Y instproc n> ::y+::Y->n*<::X instproc n> ::y+::X->n*<>" \ "simple self next test" set infoNext "" set result "" Class A A instproc m arg { global result infoNext set result ${result}-[self]-$arg } Class B -superclass A B instproc m arg { global result infoNext set result ${result}-[self]-$arg append infoNext " 2[self]+[self class]->[self proc]*<[self next]>" next } B b0 -m 1 B b -m "" ::errorCheck $result "-::b0-1-::b0-1-::b--::b-" \ "Next Test A/B -- Wrong result" set result "" Class X X instproc init args { global result infoNext set result ${result}-[self]-$args append infoNext " 1[self]+[self class]->[self proc]*<[self next]>" next } X instproc test {} { global result set result ${result}-[self] } X x -test ::errorCheck $result "-::x-::x-" \ "Next Test X -- Wrong result" ::errorCheck $infoNext " 2::b0+::B->m*<::A instproc m> 2::b+::B->m*<::A instproc m> 1::x+::X->init*<::xotcl::Object instproc init>" \ "self next test 2" X destroy x destroy A destroy B destroy b0 destroy b destroy Class MIX MIX instproc mProc args { global result append result "[self]-[self class]-[self next]" next } Object o -mixin MIX o proc mProc args { global result append result "[self]-[self class]-[self next]" } set result "" o mProc ::errorCheck $result "::o-::MIX-::o proc mProc::o--" \ "Next Test Proc & Mixin" o destroy; MIX destroy } return "PASSED [self]" } TestX init_params @ TestX init_params { description { Regression test object testing the parameter instance method, the init dash '-' and constructor calling. } } init_params proc run {{n 20}} { for {set i 0} {$i < $n} {incr i} { global dashResult set dashResult "" set dashResultEnd "" Class A A instproc t0 {} { global dashResult set dashResult ${dashResult}*[self proc] } A instproc t1 {a} { global dashResult set dashResult ${dashResult}*[self proc]-$a } A instproc t2 {a b} { global dashResult set dashResult ${dashResult}*[self proc]-${a}-$b } A instproc t3 {a b c} { global dashResult set dashResult ${dashResult}*[self proc]-${a}-${b}-$c } A a set dashResultEnd "[A a -t0] $dashResultEnd" A a set dashResultEnd "[A a -t1 1] $dashResultEnd" A a set dashResultEnd "[A a -t2 1 2] $dashResultEnd" A a set dashResultEnd "[A a -t3 1 2 3] $dashResultEnd" A a set dashResultEnd "[A a -t0 -t0 -t3 1 2 3 -t0 -t1 1 -t1 1 -t0] $dashResultEnd" catch {A a t} ::errorCheck $dashResult \ "*t0*t1-1*t2-1-2*t3-1-2-3*t0*t0*t3-1-2-3*t0*t1-1*t1-1*t0" \ "Init Dash Test fails" ::errorCheck $dashResultEnd \ "::a ::a ::a ::a ::a " \ "Init Dash Test fails -- result" } # paramter/defaults test proc ::cmd {a b} { return in-cmd-${a}-${b} } global parameterResult global initResult for {set i 0} {$i < $n} {incr i} { Class O -parameter { {a -default 0} {b -default {[cmd 3 4]}} c d {e -default 3} {Self -default [self]} } O instproc init args { global initResult set initResult ${initResult}-[self]-[self class]-[self proc]--$args next } O instproc show {} { global parameterResult set parameterResult [self] foreach v [lsort [my info vars]] { set parameterResult ${parameterResult}-${v}=<[my set ${v}]> } } Class Meta -superclass Class Meta instproc create args {next; return Meta-create} Meta C -superclass O -parameter {a {b -default ""} {c -default 1}} Class D -parameter {a {c -default 1}} -superclass O # create on class should not be called D instproc create args {next; return D-create} D instproc init args { global initResult set initResult ${initResult}-[self]-[self class]-[self proc]--$args next } D instproc test i { ::errorCheck [my set c]-[my set a] "2-0" "Wrong order of init call" } set parameterResult "" set initResult "" C c0 -show ::errorCheck $parameterResult "::c0-Self=<::c0>-a=<0>-b=<>-c=<1>-e=<3>" \ "C c0 parameter Test failed" if {$i == 0} { ::errorCheck $initResult "-::c0-::O-init--" \ "C c0 parameter init Test failed" } else { ::errorCheck $initResult "-::c0-::O-init--" \ "C c0 parameter init Test failed (b)" } set parameterResult "" set initResult "" set r [C c1 -c 2 -init a b c -a 1 -show] ::errorCheck $parameterResult "::c1-Self=<::c1>-a=<1>-b=<>-c=<2>-e=<3>" \ "C c1 parameter Test failed (b)" ::errorCheck $initResult "-::c1-::O-init--a b c" \ "C c1 parameter init Test failed" set parameterResult "" set initResult "" set r $r-[D d1 -c 2 -init a b c -test $i -a 1 -show] ::errorCheck $parameterResult "::d1-Self=<::d1>-a=<1>-b=-c=<2>-e=<3>" \ "D d1 parameter Test failed" if {$i == 0} { ::errorCheck $initResult "-::d1-::D-init--a b c-::d1-::O-init--a b c" \ "D d1 parameter init Test failed" } else { ::errorCheck $initResult "-::d1-::D-init--a b c-::d1-::O-init--a b c" \ "D d1 parameter init Test failed (b)" } ::errorCheck $r "Meta-create-::d1" \ "User defined object creation failed" } return "PASSED [self]" } TestX mixinTest @ TestX mixinTest { description { Regression test object testing per-object mixins. } } mixinTest proc run {{n 10}} { global mixinResult set mixinResult "" Class Agent Agent instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Agent instproc otherProc {} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Class InteractiveAgent -superclass Agent InteractiveAgent instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Class InteractiveAgent2 -superclass Agent InteractiveAgent2 instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Class InteractiveAgent3 -superclass Agent InteractiveAgent3 instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } # Addition-Classes Class MovementLog MovementLog instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] my otherProc next } MovementLog instproc otherProc {} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Class MovementTest MovementTest instproc moveAgent {x y} { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } InteractiveAgent i1; InteractiveAgent i2 i1 mixin MovementLog i2 mixin MovementTest InteractiveAgent2 instmixin {MovementLog MovementTest} InteractiveAgent3 instmixin MovementTest InteractiveAgent2 i3; InteractiveAgent3 i4; ::errorCheck [InteractiveAgent2 info instmixin] "::MovementLog ::MovementTest" "Mixin: info instmixin" i2 moveAgent 1 2 ::errorCheck "$mixinResult" \ "-::i2-moveAgent-::MovementTest-::i2-moveAgent-::InteractiveAgent-::i2-moveAgent-::Agent" \ "Mixin: 'i2 moveAgent 1 2' failed" set mixinResult "" i1 moveAgent 3 4 ::errorCheck "$mixinResult" \ "-::i1-moveAgent-::MovementLog-::i1-otherProc-::MovementLog-::i1-otherProc-::Agent-::i1-moveAgent-::InteractiveAgent-::i1-moveAgent-::Agent" \ "Mixin: 'i1 moveAgent 3 4' failed" set mixinResult "" i3 moveAgent 3 4 ::errorCheck "$mixinResult" \ "-::i3-moveAgent-::MovementLog-::i3-otherProc-::MovementLog-::i3-otherProc-::Agent-::i3-moveAgent-::MovementTest-::i3-moveAgent-::InteractiveAgent2-::i3-moveAgent-::Agent" \ "Instmixin: 'i3 moveAgent 3 4' failed" set mixinResult "" i4 moveAgent 3 4 ::errorCheck "$mixinResult" \ "-::i4-moveAgent-::MovementTest-::i4-moveAgent-::InteractiveAgent3-::i4-moveAgent-::Agent" \ "Instmixin: 'i4 moveAgent 3 4' failed" i4 mixin {MovementTest MovementLog} i4 proc aaa args {puts TEST} ::errorCheck [i4 procsearch moveAgent]-[i4 procsearch aaa]-[i4 procsearch set] "::MovementLog instproc moveAgent-::i4 proc aaa-::xotcl::Object instproc set" "[self]: procsearch" set mixinResult "" i4 moveAgent 5 6 ::errorCheck "$mixinResult" \ -::i4-moveAgent-::MovementLog-::i4-otherProc-::MovementLog-::i4-otherProc-::Agent-::i4-moveAgent-::MovementTest-::i4-moveAgent-::InteractiveAgent3-::i4-moveAgent-::Agent \ "Instmixin: 'i4 moveAgent 5 6' failed" Class A A instproc test {} { global mixinResult set mixinResult "test" i1 moveAgent 3 4 } A a a test ::errorCheck "$mixinResult" \ "test-::i1-moveAgent-::MovementLog-::i1-otherProc-::MovementLog-::i1-otherProc-::Agent-::i1-moveAgent-::InteractiveAgent-::i1-moveAgent-::Agent" \ "Mixin: 'a test' failed" i2 mixin {MovementLog MovementTest} set mixinResult "" i2 moveAgent a b ::errorCheck "$mixinResult" \ "-::i2-moveAgent-::MovementLog-::i2-otherProc-::MovementLog-::i2-otherProc-::Agent-::i2-moveAgent-::MovementTest-::i2-moveAgent-::InteractiveAgent-::i2-moveAgent-::Agent" \ "Mixin: 'i2 moveAgent a b' failed" ::errorCheck "[i2 info mixin]-[i1 info mixin]-[a info mixin]" \ "::MovementLog ::MovementTest-::MovementLog-" \ "Mixin: Info failed" ::errorCheck "[i2 ismixin MovementTest]-[i4 ismixin MovementTest]-[a ismixin MovementTest]-[i3 ismixin MovementTest]-[i4 ismixin MovementTest]-[i4 ismixin MovementLog]-[i3 ismixin YXZ]-[i3 ismixin InteractiveAgent]" \ "1-1-0-1-1-1-0-0" \ "'ismixin test' failed" ::errorCheck "[i2 hasclass MovementTest]-[i4 hasclass MovementTest]-[a hasclass MovementTest]-[i3 hasclass MovementTest]-[i4 hasclass MovementTest]-[i4 hasclass MovementLog]-[i3 hasclass YXZ]-[i3 hasclass InteractiveAgent]-[a hasclass A]-[i3 hasclass Agent]" \ "1-1-0-1-1-1-0-0-1-1" \ "'hasclass test' failed" set mixinResult "" i2 mixin "" i2 moveAgent a b ::errorCheck "$mixinResult" \ "-::i2-moveAgent-::InteractiveAgent-::i2-moveAgent-::Agent" \ "Mixin: remove failed" set mixinResult "" Class A A instproc destroy args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } A instproc y args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } Class B B instproc destroy args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] next } B instproc y args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] my mixin "" next } B instproc x args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] my destroy } A a -mixin B a destroy A a -mixin B a x A a -mixin B a y ::errorCheck "$mixinResult" \ "-::a-destroy-::B-::a-destroy-::A-::a-x-::B-::a-destroy-::B-::a-destroy-::A-::a-y-::B-::a-y-::A" \ "Mixin: destroy failed" A instmixin B set mixinResult "" A a2 a2 destroy A a2 a2 x A a2 a2 y ::errorCheck "$mixinResult" \ "-::a2-destroy-::B-::a2-destroy-::A-::a2-x-::B-::a2-destroy-::B-::a2-destroy-::A-::a2-y-::B-::a2-y-::A" \ "Instmixin: destroy failed" # mixin Test: calls the mixins and a proc of the object set ::mixinResult "" Class A Class B A instproc a {} {set ::mixinResult ${::mixinResult}-[self]-[self class]-[self proc];next} B instproc a {} {set ::mixinResult ${::mixinResult}-[self]-[self class]-[self proc]; next} A d -mixin B d proc a {} {set ::mixinResult ${::mixinResult}-[self]-[self class]-[self proc]; next} d a ::errorCheck $::mixinResult \ "-::d-::B-a-::d--a-::d-::A-a" \ "Mixin: calling of object's proc" set mixinResult "" d mixin {} A instmixin B d a ::errorCheck $::mixinResult \ "-::d-::B-a-::d--a-::d-::A-a" \ "Instmixin: calling of object's proc" # # combining filters with mixins # set ::traceResults "" Class M1 M1 instproc test args { global traceResults lappend traceResults "[self] [self proc] [self class]" next } Class M2 M2 instproc test args { global traceResults lappend traceResults "[self] [self proc] [self class]" next } Class A A instproc test args { global traceResults lappend traceResults "[self] [self proc] [self class]" next } A instproc f1 args { global traceResults lappend traceResults "[self] [self proc] [self class]" next } A instproc f2 args { global traceResults lappend traceResults "[self] [self proc] [self class]" next } A a A instmixin {M1 M2} A instfilter {f1 f2} a test ::errorCheck $::traceResults \ "{::a f1 ::A} {::a f2 ::A} {::a test ::M1} {::a test ::M2} {::a test ::A}" \ "Combining mixins and filters" # mixin recursion test set mixinResult "" Class Computation Computation instproc compute args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] # abstract interface for computations } Class ComputationOutput -superclass Computation Computation instproc compute args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] return $args } Class RecFacultyMixin RecFacultyMixin instproc compute args { global mixinResult set mixinResult ${mixinResult}-[self]-[self proc]-[self class] set n [lindex $args 0] set callingClass - #puts stderr [self class]=[uplevel 1 self class]-[self callingclass] #catch {set callingClass [uplevel 1 self class]} set callingClass [self callingclass] if {$n == 0} { set result 1 } else { set f [my compute [expr $n - 1] x] set result [expr $n * $f] } if {$callingClass != [self class]} { next $result return $result } else { return $result } } ComputationOutput faculty faculty mixin RecFacultyMixin ::errorCheck [faculty compute 3] 6 \ "Mixin: faculty wrong result" ::errorCheck "$mixinResult" \ "-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::Computation" \ "Mixin: faculty failed" set mixinResult "" ComputationOutput faculty ComputationOutput instmixin RecFacultyMixin ::errorCheck [faculty compute 3] 6 \ "Mixin: faculty wrong result" ::errorCheck "$mixinResult" \ "-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::RecFacultyMixin-::faculty-compute-::Computation" \ "Mixin: faculty failed" set ::mixinResult "" set ::calling "" Class GrObject GrObject instproc draw args { lappend ::mixinResult [list grObject [self] [self proc] [self class]] lappend ::calling [list grObject [self proc]: [self callingobject] [self callingclass] [self callingproc] [self next]] } Class Image -superclass GrObject Image instproc draw args { lappend ::mixinResult [list image [self] [self proc] [self class]] lappend ::calling [list image [self proc]: [self callingobject] [self callingclass] [self callingproc] [self next]] next } Class MenuDecorator MenuDecorator instproc draw args { lappend ::mixinResult [list m1 [self] [self proc] [self class]] lappend ::calling [list m1 [self proc]: [self callingobject] [self callingclass] [self callingproc] [self next]] next } Class ScrollBarDecorator ScrollBarDecorator instproc draw args { lappend ::mixinResult [list m2 [self] [self proc] [self class]] lappend ::calling [list m2 [self proc]: [self callingobject] [self callingclass] [self callingproc] [self next]] next } Image mainImage -mixin {MenuDecorator ScrollBarDecorator} Image zoom -mixin {ScrollBarDecorator} Object instproc f args { if {[self calledproc] != "filter"} { lappend ::mixinResult [list filter [self] [self proc] [self class]] lappend ::calling [list filter [self proc]: [self callingobject] [self callingclass] [self callingproc] [self calledproc] [self next]] } return [next] } Object instfilter f mainImage draw zoom draw Object instfilter "" ::errorCheck $::calling \ "{filter f: ::mixinTest {} run draw {::MenuDecorator instproc draw}} {m1 draw: ::mixinTest {} run {::ScrollBarDecorator instproc draw}} {m2 draw: ::mixinTest {} run {::Image instproc draw}} {image draw: ::mixinTest {} run {::GrObject instproc draw}} {grObject draw: ::mixinTest {} run {}} {filter f: ::mixinTest {} run draw {::ScrollBarDecorator instproc draw}} {m2 draw: ::mixinTest {} run {::Image instproc draw}} {image draw: ::mixinTest {} run {::GrObject instproc draw}} {grObject draw: ::mixinTest {} run {}} {filter f: ::mixinTest {} run instfilter {::xotcl::Class instproc instfilter}}" \ "Mixin: Calling-Obj/Cl/Proc failed" ::errorCheck "$::mixinResult" \ "{filter ::mainImage f ::xotcl::Object} {m1 ::mainImage draw ::MenuDecorator} {m2 ::mainImage draw ::ScrollBarDecorator} {image ::mainImage draw ::Image} {grObject ::mainImage draw ::GrObject} {filter ::zoom f ::xotcl::Object} {m2 ::zoom draw ::ScrollBarDecorator} {image ::zoom draw ::Image} {grObject ::zoom draw ::GrObject} {filter ::xotcl::Object f ::xotcl::Object}" \ "Mixin: Filter failed" set ::mixinResult "" set ::calling "" Class InfoTrace2 InfoTrace2 instproc infoTraceFilter2 args { lappend ::calling \ self [self] \ "self proc" [self proc] \ "self class" [self class] \ "self calledproc" [self calledproc] \ "self callingproc" [self callingproc] \ "self callingobject" [self callingobject] \ "self callingclass" [self callingclass] \ "self filterreg" [self filterreg] \ "self next" [self next] next } Class CallingObjectsClass CallingObjectsClass create callingObject Class FilterRegClass -superclass InfoTrace2 Class FilteredObjectsClass -superclass FilterRegClass FilteredObjectsClass filteredObject CallingObjectsClass instproc callingProc args { filteredObject set someVar 0 } FilterRegClass instfilter infoTraceFilter2 callingObject callingProc ::errorCheck $::calling \ {self ::filteredObject {self proc} infoTraceFilter2 {self class} ::InfoTrace2 {self calledproc} set {self callingproc} callingProc {self callingobject} ::callingObject {self callingclass} ::CallingObjectsClass {self filterreg} {::FilterRegClass instfilter infoTraceFilter2} {self next} {::xotcl::Object instproc set}} \ "call stack info" Class M1; Class M2; Class M3; Class M4 Class A; Class B -superclass A; B b A instmixin {M1 M2} B instmixin {M3 M1 M1 M4} b mixin {M1 M1 M4} ::errorCheck [b info mixin -order] "::M3 ::M4 ::M1 ::M2" "Mixin Info: -order option" ::errorCheck [B info instmixin]-[b info mixin] "::M3 ::M1 ::M4-::M1 ::M4" "Mixin Info: no duplicates" B instmixin {} ::errorCheck [b info mixin -order] "::M4 ::M1 ::M2" "Mixin Info: -order option" set ::r "" Class X11 -instproc test {args} { lappend ::r [self class] next } Class X12 -instproc test {args} { lappend ::r [self class] next } Class X -instmixin {X11 X12} -instproc test {args} { lappend ::r [self class] next } Class Y -instmixin X Y create y -test X create x -test ::errorCheck $::r [list ::X11 ::X12 ::X ::X11 ::X12 ::X] \ {transitive mixin} unset ::r # test for MixinRemoveFromMixinStack, MixinRemoveFromCmdPtr, # MixinRemoveOnObjFromCmdPtr Class A A instproc x {} {B destroy; next} Class B B instproc x {} {next} Class C C instproc x {} {next} Object o -mixin {A B C} o proc x {} {return x} ::errorCheck [o x] {x} {mixin destroy on stack} return "PASSED [self]" } TestX mixinInheritanceTest @ TestX mixinInheritanceTest { description { Regression test object testing per-object mixin inheritance. } } mixinInheritanceTest proc run {{n 10}} { for {set i 0} {$i < $n} {incr i} { global mixinResult set mixinResult "" Class A Class B Class C -superclass {A B} Class GeneralMixin Class RefinedMixin1 -superclass GeneralMixin Class RefinedMixin2 -superclass GeneralMixin Class AppMixin1 -superclass {RefinedMixin1 RefinedMixin2} Class AppMixin2 -superclass {RefinedMixin2 RefinedMixin1} Class AppMixin3 -superclass {RefinedMixin1} A instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return $args } B instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return $args } C instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next "$args [self class]"] } GeneralMixin instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next "$args [self class]"] } RefinedMixin1 instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next "$args [self class]"] } RefinedMixin2 instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next "$args [self class]"] } AppMixin1 instproc aProc args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next "$args [self class]"] } AppMixin1 mixinInstance set r [mixinInstance aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::AppMixin1 ::RefinedMixin1 ::RefinedMixin2 ::GeneralMixin" \ "Mixin inheritance: mixinInstance aProc" set mixinResult "" AppMixin3 mixinInstance2 set r [mixinInstance2 aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::RefinedMixin1 ::GeneralMixin" \ "Mixin inheritance: mixinInstance2 aProc" set mixinResult "" A a a mixin AppMixin1 set r [a aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::AppMixin1 ::RefinedMixin1 ::RefinedMixin2 ::GeneralMixin ::A" \ "Mixin inheritance: a aProc" ::errorCheck $r \ "{{{{ARGS1 ARGS2 ::AppMixin1} ::RefinedMixin1} ::RefinedMixin2} ::GeneralMixin}" \ "Mixin inheritance result: a aProc" A a A instmixin AppMixin1 set mixinResult "" set r [a aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::AppMixin1 ::RefinedMixin1 ::RefinedMixin2 ::GeneralMixin ::A" \ "Instmixin inheritance: a aProc" ::errorCheck $r \ "{{{{ARGS1 ARGS2 ::AppMixin1} ::RefinedMixin1} ::RefinedMixin2} ::GeneralMixin}" \ "Instmixin inheritance: a aProc" set mixinResult "" C c c mixin {AppMixin3 AppMixin2} set r [c aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::AppMixin1 ::RefinedMixin1 ::RefinedMixin2 ::GeneralMixin ::C ::A" \ "Mixin/Instmixin inheritance: c aProc" set mixinResult "" A instmixin {} set r [c aProc ARGS1 ARGS2] ::errorCheck $mixinResult \ " ::RefinedMixin2 ::RefinedMixin1 ::GeneralMixin ::C ::A" \ "Mixin/Instmixin inheritance: c aProc" GeneralMixin instproc set args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next] } RefinedMixin1 instproc set args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next] } AppMixin1 instproc set args { global mixinResult; ::set mixinResult "$mixinResult [self class]" return [next] } global setFilterResult set setFilterResult "" Object instproc setFilter args { global setFilterResult ::append setFilterResult \ -[self]-[self calledproc]-[self calledclass] next } Object instfilter setFilter set mixinResult "" set r [c set setVar 111] ::errorCheck $mixinResult \ " ::RefinedMixin1 ::GeneralMixin" \ "Mixin inheritance: c set" # UNKNOWN PROBLEM 2 # ::errorCheck [c setsetVar] 111 "Mixin inheritance: c set - value" ::errorCheck [c set setVar] 111 "Mixin inheritance: c set - value" set mixinResult "" mixinInstance set setVar 222 ::errorCheck $mixinResult \ " ::AppMixin1 ::RefinedMixin1 ::GeneralMixin" \ "Mixin inheritance: mixinInstance set" ::errorCheck [mixinInstance set setVar] 222\ "Mixin inheritance: mixinInstance set - value" ::errorCheck $setFilterResult \ "-::c-set-::xotcl::Object-::c-set-::xotcl::Object-::mixinInstance-set-::AppMixin1-::mixinInstance-set-::AppMixin1" \ "Mixin inheritance: Wrong classes in mixin set test" Object instfilter "" } # Mixin init test global initResult set initResult "" Class A A instproc init args { my mixin B global initResult append initResult [self class]- next } Class C C instproc init args { global initResult append initResult [self class]- next } Class B -superclass C B instproc init args { global initResult append initResult [self class]- next } Class D D instproc init args { global initResult append initResult [self class]- next } A a ::errorCheck $initResult \ "::A-" \ "Mixin init 1 failed" set initResult "" # in A mixin changes to B - before D's constructor must # be called A b -mixin D ::errorCheck $initResult \ "::D-::A-" \ "Mixin init 2 failed" Class Mix Mix instproc init args { global initResult append initResult [self class]- next } Class Mix1 Mix1 instproc init args { global initResult append initResult [self class]- next } Class Mix2 Mix2 instproc init args { global initResult append initResult [self class]- next } Class A A instproc init args { global initResult append initResult [self class]- next } Class B B instproc init args { my mixin {Mix Mix1} global initResult append initResult [self class]- next } set initResult "" A a a mixin {Mix Mix1} ::errorCheck $initResult \ "::A-" \ "Mixin init 3 failed" set initResult "" B b ::errorCheck $initResult \ "::B-" \ "Mixin init 4 failed" set initResult "" B mixinappend Mix2 ::errorCheck $initResult \ "" \ "Mixin init 5 failed" set initResult "" A mixin {}; A mixin {Mix Mix1} ::errorCheck $initResult \ "" \ "Mixin init 6 failed" set initResult "" A a -mixin {Mix} ::errorCheck $initResult \ "::Mix-::A-" \ "Mixin init 7 failed" Class Strategy Strategy instproc init args { global initResult append initResult [self class]- next } Class A A instproc strategy {n} { set a [my info mixin] my mixin [concat $n $a] } A instproc init args { global initResult append initResult [self class]- next } Class Mix1 Mix1 instproc init args { global initResult append initResult [self class]- my strategy Strategy next } set initResult "" A a -mixin Mix1 ::errorCheck $initResult \ "::Mix1-::A-" \ "Mixin init 8 failed" set initResult "" Class X X instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } Class Y -superclass X Y instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } Class U -superclass X U instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } Class V V instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } Class A A instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } Class B -superclass A B instproc init args { append ::initResult " [self]: [self class]->[self proc]" next } A a a mixin X B b b mixin Y A a2 -mixin Y B b2 -mixin X A a3 -mixin {U V} B b3 b3 mixin {U V} A a3 A instmixin X A instmixin {} B instmixin Y B b3 b3 mixin Y ::errorCheck $initResult \ " ::a: ::A->init ::b: ::B->init ::b: ::A->init ::a2: ::Y->init ::a2: ::X->init ::a2: ::A->init ::b2: ::X->init ::b2: ::B->init ::b2: ::A->init ::a3: ::U->init ::a3: ::X->init ::a3: ::V->init ::a3: ::A->init ::b3: ::B->init ::b3: ::A->init ::a3: ::A->init ::b3: ::Y->init ::b3: ::X->init ::b3: ::B->init ::b3: ::A->init" \ "Mixin init 9 failed" return "PASSED [self]" } TestX copymove @ TestX copymove { description { Regression test for copy/move methods } } copymove proc run {{n 10}} { # Composite Class Composite -superclass Class Composite instproc addop {op} { my instvar ops set ops($op) $op } Composite instproc compositeFilter args { set m [self calledproc] set c [lindex [self filterreg] 0] set r [next] if {[$c exists ops($m)]} { foreach child [my info children] { eval [self]::$child $m $args } } return $r } Composite AbstractNode AbstractNode abstract instproc iterate v AbstractNode addop iterate for {set i 0} {$i < $n} {incr i} { # # class copy # Class X Class X::Y Class X::Y::Z -parameter { {param1 1} {param2 2} } #X::Y::Z metadata add {Version Author Nothing} #X::Y::Z metadata Version {0.0.9} #X::Y::Z metadata Author {Uwe} X::Y::Z instproc defaultValueIP {{a defA} {b defB} v} { return } X::Y::Z proc defaultValueP {{c defC} {d defD} v} { return } X::Y::Z instinvar {{7 > 6} { #a comment } } X::Y::Z instproc assProc {} {puts x} {{5 > 4} { #pre }} {{5 > 4} { #post } } X::Y::Z check {pre post instinvar} foreach C {X X::Y X::Y::Z} { $C instproc q {a b c} { return [self]--[self class]--[self proc]--[next]-- } } X::Y::Z z X::Y::Z copy V V v ::errorCheck "[z q 1 2 3]--[X::Y::Z info class]--[X::Y::Z info classparent]" \ "::z--::X::Y::Z--q------::xotcl::Class--::X::Y"\ "class copy z" ::errorCheck "[v q 1 2 3]--[V info class]--[V info classparent]" "::v--::V--q------::xotcl::Class--::"\ "class copy v" ::errorCheck "[::cutSpaces [V info parameter]--[v set param1]--[v set param2]]" \ " {param1 1} {param2 2} --1--2" \ "parameter test" ::errorCheck "[::cutSpaces [V info instinvar]--[V info instpre assProc]--[V info instpost assProc]]"\ "{7 > 6} { #a comment }--{5 > 4} { #pre }--{5 > 4} { #post }"\ "Copy Class Assertions" #::errorCheck "[V info metadata]--[V metadata Author]--[V metadata Version]--[V metadata Nothing]"\ "Version Author Nothing--Uwe--0.0.9--"\ "Copy Metadata" set df1 [V info default defaultValueP v dfv1] set df2 [V info default defaultValueP c dfv2] set df3 [V info instdefault defaultValueIP v dfv3] set df4 [V info instdefault defaultValueIP a dfv4] ::errorCheck "$df1 $dfv1 $df2 $dfv2 $df3 $dfv3 $df4 $dfv4"\ "0 1 defC 0 1 defA"\ "Copy Default Values" # class hierarchy copy Class O X copy O::X O::X x1; O::X::Y y1; O::X::Y::Z z1 ::errorCheck "[x1 q 1 2 3]--[y1 q 1 2 3]--[z1 q 1 2 3]" \ "::x1--::O::X--q------::y1--::O::X::Y--q------::z1--::O::X::Y::Z--q----"\ "class hierarchy copy" # # object copy # X x -set var1 12 -requireNamespace proc ::x::tclProc args {return tclProc} x proc q {a b c} {return [self]--[self class]--[self proc]--[next]--} x copy y ::errorCheck "[::y::tclProc]--[x q 1 2 3]--[y q 1 2 3]" \ "tclProc--::x----q--::x--::X--q--------::y----q--::y--::X--q------"\ "object copy" # object hierarchy copy x copy x::a x copy x::a::z ::errorCheck "[::x::a::tclProc]--[::x::a::z::a::tclProc]" \ "tclProc--tclProc"\ "object hierarchy copy" Class O O x x invar {{7 > 5} { #a comment }} x proc assProc {} {return} {{5 > 3} { #pre }} {{5 > 4} {#post }} x set var1 12 x proc p1 {} {return [self]-p1} x copy y ::errorCheck "[x p1]--[x set var1]--[::x info class]" "::x-p1--12--::O"\ "Simple Copy - Origin" ::errorCheck "[y p1]--[y set var1]--[::y info class]" "::y-p1--12--::O"\ "Simple Copy - Duplicate" ::errorCheck "[::cutSpaces [y info invar]--[y info pre assProc]--[y info post assProc]]"\ "{7 > 5} { #a comment }--{5 > 3} { #pre }--{5 > 4} {#post }"\ "Copy Obj Assertions" # # move test # V destroy X::Y::Z move V V v ::errorCheck "[v q 1 2 3]--[V info class]--[V info classparent]" "::v--::V--q------::xotcl::Class--::"\ "class move v" ::errorCheck "[::cutSpaces [V info parameter]--[v set param1]--[v set param2]]" \ " {param1 1} {param2 2} --1--2" \ "parameter move test" ::errorCheck "[::cutSpaces [V info instinvar]--[V info instpre assProc]--[V info instpost assProc]]"\ "{7 > 6} { #a comment }--{5 > 4} { #pre }--{5 > 4} { #post }"\ "Move Class Assertions" #::errorCheck "[V info metadata]--[V metadata Author]--[V metadata Version]--[V metadata Nothing]"\ "Version Author Nothing--Uwe--0.0.9--"\ "Move Metadata" set df1 [V info default defaultValueP v dfv1] set df2 [V info default defaultValueP c dfv2] set df3 [V info instdefault defaultValueIP v dfv3] set df4 [V info instdefault defaultValueIP a dfv4] ::errorCheck "$df1 $dfv1 $df2 $dfv2 $df3 $dfv3 $df4 $dfv4"\ "0 1 defC 0 1 defA"\ "Move Default Values" ::errorCheck "[::info commands X::Y::Z]"\ ""\ "Moved command still exists" # # copy with filters test # foreach filters {{} compositeFilter} { Composite instfilter $filters AbstractNode instfilter $filters Object commands Class Commands -superclass AbstractNode Class Command -superclass Commands Command instproc init args { my instvar label set label [self] next } Command instproc setlabel {{arg ""}} { my instvar label if {$arg == ""} { set label } else { set label $arg } } Command instproc setproc {value} { my instvar src set src $value } # prototypes Command commands::cellcmd commands::cellcmd setlabel cell commands::cellcmd setproc {return "coucou" } commands::cellcmd proc x args {return xxx} commands::cellcmd copy toto ::errorCheck [::toto info class] ::Command\ "Copy with Filter: info class" ::errorCheck [toto set label] cell\ "Copy with Filter: set var" ::errorCheck [toto x] xxx\ "Copy with Filter: call proc" ::errorCheck [commands::cellcmd set label] cell\ "Copy with Filter: set var" } Class A Class V Class Z Class B -superclass A Class B1 -superclass {V A Z} A move X ::errorCheck [B info superclass]-[B1 info superclass]-[X info subclass] \ "::X-::V ::X ::Z-::B ::B1" \ "Move of subclass relationship" } return "PASSED [self]" } TestX recreation @ TestX recreation { description { Regression test for object recreation/cleanup. } } recreation proc run {{n 10}} { for {set i 0} {$i < $n} {incr i} { set ::recreateResult "" Class R R instproc recreate args { global recreateResult append recreateResult "*recreate [self] $args* " set r [next] append recreateResult "*recreate [self] <[lindex $args 0]> $r * " return $r } Object instmixin R catch { C destroy c1 destroy } Class C -parameter {a b} C instproc cProc {} {return cProc} C set r 4 C set v 5 C c1 -a 1 c1 proc x {} {return p} c1 set x 3 C c1 -b 2 append ::recreateResult "+[c1 info vars]," append ::recreateResult "[c1 info procs] +" Class C C set w 3 append ::recreateResult "+[C info vars]," append ::recreateResult "[C info instprocs] +" if {$i > 0} { errorCheck [set ::recreateResult] \ "*recreate ::xotcl::Class R* *recreate ::xotcl::Class R * *recreate ::C c1 -b 2* *recreate ::C c1 * +b, +*recreate ::xotcl::Class C* *recreate ::xotcl::Class C * +w, +" \ "Var/proc recreate delete failed (n)" } else { errorCheck [set ::recreateResult] \ "*recreate ::C c1 -b 2* *recreate ::C c1 * +b, +*recreate ::xotcl::Class C* *recreate ::xotcl::Class C * +w, +" \ "Var/proc recreate delete failed (0)" } global recreateMixinResult global recreateFilterResult set recreateMixinResult "" set recreateFilterResult "" Class RecreateObserve foreach ip {create destroy instdestroy init configure recreate cleanup alloc class} { RecreateObserve instproc $ip args { append ::recreateMixinResult " [self]+[self class]->[self proc]" next } } Class Recreated Recreated instproc recreationFilter args { append ::recreateFilterResult " [self]+[self calledclass]->[self calledproc]" next } Recreated instfilter recreationFilter Recreated mixin RecreateObserve Recreated instmixin RecreateObserve Recreated recreateObj Recreated recreateObj recreateObj destroy errorCheck [set ::recreateFilterResult] \ " ::recreateObj+::xotcl::Object->configure ::recreateObj+::xotcl::Object->init ::recreateObj+::xotcl::Object->cleanup ::recreateObj+::xotcl::Object->configure ::recreateObj+::xotcl::Object->init ::recreateObj+::xotcl::Object->destroy" \ "recreateObj - recreateFilterResult" if {$i == 0} { errorCheck [set ::recreateMixinResult] \ " ::Recreated+::RecreateObserve->create ::Recreated+::RecreateObserve->alloc ::recreateObj+::RecreateObserve->configure ::recreateObj+::RecreateObserve->init ::Recreated+::RecreateObserve->create ::Recreated+::RecreateObserve->recreate ::recreateObj+::RecreateObserve->cleanup ::recreateObj+::RecreateObserve->configure ::recreateObj+::RecreateObserve->init ::recreateObj+::RecreateObserve->destroy ::Recreated+::RecreateObserve->instdestroy" \ "recreateObj - recreateMixinResult (0)" } else { errorCheck [set ::recreateMixinResult] \ " ::Recreated+::RecreateObserve->cleanup ::Recreated+::RecreateObserve->create ::Recreated+::RecreateObserve->alloc ::recreateObj+::RecreateObserve->configure ::recreateObj+::RecreateObserve->init ::Recreated+::RecreateObserve->create ::Recreated+::RecreateObserve->recreate ::recreateObj+::RecreateObserve->cleanup ::recreateObj+::RecreateObserve->configure ::recreateObj+::RecreateObserve->init ::recreateObj+::RecreateObserve->destroy ::Recreated+::RecreateObserve->instdestroy" \ "recreateObj - recreateMixinResult (n)" } } set ::cleanupResult "" catch {a destroy} catch {A destroy} catch {X destroy} catch {META destroy} Class A A proc instdestroy args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} A proc recreate args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} A instproc destroy args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} A instproc cleanup args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} A a A a::b errorCheck [set ::cleanupResult] \ "" \ "Cleanup Create Failed" A a errorCheck [a info children] \ "" \ "Cleanup Object Children Destroy Failed" A a::b errorCheck [set ::cleanupResult] \ " ::A+->recreate ::a+::A->cleanup ::a::b+::A->destroy ::A+->instdestroy" \ "Cleanup a/a::b Failed (n)" a destroy; set ::cleanupResult "" A instproc cleanup args {append ::cleanupResult " [self]+[self class]->[self proc]"} A a A a::b errorCheck [set ::cleanupResult] \ "" \ "Cleanup Redefine Create Failed" A a errorCheck [a info children] \ "::a::b" \ "Cleanup Redefine Object Children Survive Failed" A a::b errorCheck [set ::cleanupResult] \ " ::A+->recreate ::a+::A->cleanup ::A+->recreate ::a::b+::A->cleanup" \ "Cleanup Redefine a/a::b Failed" a destroy set ::cleanupResult "" Class META -superclass Class META proc instdestroy args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} META proc recreate args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} META instproc destroy args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} META instproc cleanup args {append ::cleanupResult " [self]+[self class]->[self proc]"; next} META X META X::Y errorCheck [set ::cleanupResult] \ "" \ "Class Cleanup Create Failed" META X errorCheck [X info classchildren] \ "" \ "Class Cleanup Class Children Destroy Failed" META X::Y errorCheck [set ::cleanupResult] \ " ::META+->recreate ::X+::META->cleanup ::X::Y+::META->destroy ::META+->instdestroy" \ "Class Cleanup X/X::Y Failed" X destroy; set ::cleanupResult "" META instproc cleanup args {append ::cleanupResult " [self]+[self class]->[self proc]"} META X META X::Y errorCheck [set ::cleanupResult] \ "" \ "Class Cleanup Redefine Create Failed" META X errorCheck [X info classchildren] \ "::X::Y" \ "Class Cleanup Redefine Class Children Survive Failed" META X::Y errorCheck [set ::cleanupResult] \ " ::META+->recreate ::X+::META->cleanup ::META+->recreate ::X::Y+::META->cleanup" \ "Class Cleanup Redefine X/X::Y Failed" X destroy A destroy META destroy unset ::cleanupResult return "PASSED [self]" } TestX smallScripts @ TestX smallScripts { description { Regression test object testing arbitrary features. } } proc ::up1 {} { return [uplevel 1 self] } proc ::up3 {} { return [uplevel 3 self] } proc ::up2 {} { return [up3] } smallScripts proc run {{n 20}} { catch {Object o; o r} errMsg ::errorCheck $errMsg "::o: unable to dispatch method 'r'" "Unknown Test" # uplevel test for {set i 0} {$i < $n} {incr i} { Object o o proc u2 {} {return [::up2]} o proc u1 {} {return [::up1]} Class SM SM instproc init args { ::errorCheck [o u1] "::o" "FAILED - UpLevel Test 1" ::errorCheck [o u2] "::s" "FAILED - UpLevel Test 2" } SM s } for {set i 0} {$i < $n} {incr i} { Class A A a set oname1 [Object autoname ooo] set oname2 [Object autoname -instance OOO] A autoname -reset AAA set names [A autoname AAA] a autoname -reset aaa lappend names [a autoname aaa] lappend names [a autoname aaa] ::errorCheck $names "AAA0 aaa0 aaa1" \ "Autoname creation" ::errorCheck $oname1 "ooo$i" \ "Autoname Object 1" ::errorCheck $oname2 "oOO$i" \ "Autoname Object 2" ::errorCheck [xotcl::Object set __autonames(ooo)] $i \ "Autoname Object Count" } Class P; P p P instproc x {} { my instvar "x(1) t" return $t } p set x(1) rrr ::errorCheck [p x] "rrr" "Array member alias, no ns" Object o o proc x {} { my instvar "x(1) t" return $t } o set x(1) rrr ::errorCheck [o x] "rrr" "Array member alias, with ns" Object o o proc x args {puts r} ::errorCheck [o info body x] "puts r" "Info Body" ::errorCheck [info body o::x] "puts r" "Info Body" Object o o proc a {} { my lappend table(i) xxx } ::errorCheck [o a]-[o set table(i)] "xxx-xxx" "Array instvar create" Class A A instproc myProc args {} Class Mix1 Mix1 instproc myProcMix1 args {} Class Mix2 Mix2 instproc myProcMix2 args {} Class B -superclass A -instmixin Mix1 B instproc myProc2 args {} B b -mixin Mix2 b proc objproc args {} ::errorCheck [b info procs] "objproc" "[self]: info procs" ::errorCheck [B info instprocs] "myProc2" "[self]: info instprocs" ::errorCheck [lsort [b info methods]] "__next abstract append array autoname check class cleanup configure copy defaultmethod destroy eval exists extractConfigureArg f filter filterappend filterguard filtersearch forward hasclass incr info infoTraceFilter init instvar invar isclass ismetaclass ismixin isobject istype lappend mixin mixinappend mixinguard move myProc myProc2 myProcMix1 myProcMix2 noinit objproc parametercmd proc procsearch recreate requireNamespace self set setFilter tclcmd trace unset uplevel upvar volatile vwait" "[self]: b info methods" ::errorCheck [lsort [b info methods -nocmds]] "abstract copy defaultmethod extractConfigureArg f filterappend hasclass infoTraceFilter init mixinappend move myProc myProc2 myProcMix1 myProcMix2 objproc recreate self setFilter tclcmd" "[self]: b info methods -nocmds" ::errorCheck [lsort [b info methods -noprocs]] "__next append array autoname check class cleanup configure destroy eval exists filter filterguard filtersearch forward incr info instvar invar isclass ismetaclass ismixin isobject istype lappend mixin mixinguard noinit parametercmd proc procsearch requireNamespace set trace unset uplevel upvar volatile vwait" "[self]: b info methods -noprocs" ::errorCheck [lsort [b info methods -nocmds -nomixins]] "abstract copy defaultmethod extractConfigureArg f filterappend hasclass infoTraceFilter init mixinappend move myProc myProc2 objproc self setFilter tclcmd" "[self]: b info methods -nocmds -nomixins" ::errorCheck [b info methods -nocmds -noprocs] "" "[self]: b info methods -nocmds -noprocs" ::errorCheck [lsort [B info methods -nocmds]] "abstract copy defaultmethod extractConfigureArg f filterappend hasclass infoTraceFilter init instfilterappend instmixinappend insttclcmd mixinappend move recreate self setFilter tclcmd" "[self]: B info methods -nocmds" namespace eval a { proc o args {return o} } namespace eval a::b { proc b args {return b} } Object a a requireNamespace set r [a::b::b] Object a::b a::b proc x args { return x } set r "$r-[a::b x]-[a o]" ::errorCheck $r "b-x-o" "[self]: Tcl Namespace should survive requireNamespace" xotcl::interp create in set ::r [in eval { namespace import -force xotcl::* Object o}] xotcl::interp delete in ::errorCheck $::r "::o" "[self]: XOTcl slave interpreter " Object o -requireNamespace o set r 1 after 100 {o set r 3} o vwait r ::errorCheck [o set r] "3" "[self]: Vwait test" return "PASSED [self]" } TestX objectReferences @ TestX objectReferences { description { Regression test for object and class references in tcl_objs } } objectReferences proc run {{n 20}} { my proc ok01 {} { Class AAA AAA destroy Class AAA } my proc ok02 {} { Class ::AAA AAA destroy Class AAA } my proc ok03 {} { Class ::AAA ::AAA destroy Class AAA } my proc ok04 {} { Class ::AAA ::AAA destroy Class ::AAA } my proc ok05 {} { set c [Class AAA] $c destroy Class AAA } my proc ok06 {} { set c [Class ::AAA] $c destroy Class AAA } my proc ok07 {} { set c [Class ::AAA] $c destroy Class ::AAA } my proc ok08 {} { set c [Class ::AAA] $c destroy Class $c } my proc ok09 {} { [Class AAA] destroy Class AAA } my proc ok10 {} { [Class ::AAA] destroy Class AAA } my proc ok11 {} { [Class ::AAA] destroy Class ::AAA } for {set i 1} {$i < 20} {incr i} { # "reference to xotcl object in instvar" Class LexxTreeMounter Class LexxTree LexxTreeMounter proc new {args} { if {[LexxTree exists LexxTreeMounter]} { set o [LexxTree set LexxTreeMounter] } else { set o [my create [my autoname [self]]] } $o incr C(refcnt) return $o } LexxTreeMounter instproc init {args} { my instvar C set C(refcnt) 0 if {[LexxTree exists LexxTreeMounter] == 0} { LexxTree set LexxTreeMounter [self] } next } set x [LexxTreeMounter new] set x [LexxTreeMounter new] ::errorCheck [llength [LexxTreeMounter info instances]] 1 "[self]: singleton" # "Global reference to xotcl object" set ::v [Object ::a] set ::w [Object ::b] set ::z(1) [Object ::c] unset ::v # "Class creation and Class destroys, after 2nd round procs contain xotcl-object references" foreach m [lsort [my info procs ok*]] {my $m} ::errorCheck [my isobject AAA] 1 "[self]: classdestroys" } catch {UnknownClass destroy} set ::utest "" Class proc __unknown args { lappend ::utest $args set x [Class $args] set r [$x] #puts r=$r return $r } Class O -superclass UnknownClass ::errorCheck $::utest ::UnknownClass "[self]: __unknown" ::errorCheck [lsort [UnknownClass info info]] {args body children class classchildren classparent commands default filter filterguard forward heritage info instances instbody instcommands instdefault instfilter instfilterguard instforward instinvar instmixin instpost instpre instprocs invar methods mixin parameter parent post pre procs subclass superclass vars} "[self]: info info" ::errorCheck [Class info instances *Unk*] ::UnknownClass "match in info instances" ::errorCheck [Class info instances Unk*] "" "no match in info instances" ::errorCheck [Class info instances Unk] "" "no match in info instances (no metachars)" ::errorCheck [Class info class] "::xotcl::Class" "info class of Class" ::errorCheck [Class info class Object] 1 "info class of Class Object" Class C Class D -superclass C Class E -superclass D -parameter {{x 1}} E instproc t {a b {c 1}} {return ok} E proc p {a b {c 1}} {return ok} E instproc q {} {return [self proc]} ::errorCheck [C info subclass E] 1 "transitive subclass 1" ::errorCheck [Object info subclass E] 1 "transitive subclass 2" ::errorCheck [D info subclass C] 0 "transitive subclass 3" ::errorCheck [E info heritage] "::D ::C ::xotcl::Object" "heritage" ::errorCheck [E info instargs t] "a b c" "instargs" ::errorCheck [E info instdefault t c x] 1 "instdefault" ::errorCheck [E info args p] "a b c" "args" ::errorCheck [E info default p c x] 1 "default" ::errorCheck [E configure [list -p -x -y]] 0 "list params 1" ::errorCheck [E e1 [list -t -1 -e -3]] ::e1 "list params 2" ::errorCheck [e1 x] 1 "instparameter cmd 1" ::errorCheck [e1 x 2] 2 "instparameter cmd 2" ::errorCheck [e1 x] 2 "instparameter cmd 3" ::errorCheck [e1 parametercmd y] "" "parametercmd 1" ::errorCheck [e1 y 3] 3 "parametercmd 2" ::errorCheck [e1 y] 3 "parametercmd 3" ::errorCheck [e1 forward regexp -objscope] "" "forward 1" ::errorCheck [e1 regexp (y) xyz _ X] "1" "forward 2" ::errorCheck [e1 exists X] "1" "forward 3" ::errorCheck [e1 q] q "self proc" ::errorCheck [E info commands] p "class commands" ::errorCheck [E info instcommands] "t x q" "class instcommands" ::errorCheck [E info instbody t] "return ok" "class info instbody" Object o Object o::abc Object o::bcd Object o::cde ::errorCheck [o info children] "::o::cde ::o::bcd ::o::abc" "info children 1" ::errorCheck [o info children *cd*] "::o::cde ::o::bcd" "info children 2" ::errorCheck [o info children ::o::cde] ::o::cde "info children 3" ::errorCheck [o info children ::o::def] "" "info children 4" Object new -childof o ::errorCheck [llength [o info children]] 4 "info children 5" ::errorCheck [Object isobject o] 1 "is object 1" ::errorCheck [Object isobject ox] 0 "is object 2" Class M -superclass Class ::errorCheck [Object ismetaclass M] 1 "is metaclass 1" ::errorCheck [Object ismetaclass C] 0 "is metaclass 0" return "PASSED [self]" } TestX create condMixins @ TestX condMixins { description { Regression test for conditional mixins } } condMixins proc show {c obj} { set ::context $c set r [list] foreach x [list \ [list $obj info methods salary] \ [list $obj info methods -incontext salary] \ [list $obj info methods driv*] \ [list $obj info methods -incontext driv*] \ ] { lappend r "$::context: $x => [lsort [eval $x]]" } return $r } condMixins proc run {{n 20}} { Object instproc signature {} {return "[self] [my info class] ([my age] years)"} Class Person -parameter {id name age} Class Payroll-aspect -parameter salary Payroll-aspect instproc print {} {puts "[my signature]: [my salary]"} Class Driver-aspect -parameter driving-license Payroll-aspect instproc print {} {puts "[my signature]: [my driving-license]"} Person instmixin {{Payroll-aspect -guard {[string equal $::context payrollApp]}}} Person jim -mixin {{Driver-aspect -guard {[string equal $::context shipmentApp]}}} set ::context payrollApp ::errorCheck [lsort [jim info methods]] "__next abstract age append array autoname check class cleanup configure copy defaultmethod destroy driving-license eval exists extractConfigureArg f filter filterappend filterguard filtersearch forward hasclass id incr info infoTraceFilter init instvar invar isclass ismetaclass ismixin isobject istype lappend mixin mixinappend mixinguard move name noinit parametercmd print proc procsearch recreate requireNamespace salary self set setFilter signature tclcmd trace unset uplevel upvar volatile vwait" "condmixin all methods" ::errorCheck "[lsort [jim info methods -incontext]]" "__next abstract age append array autoname check class cleanup configure copy defaultmethod destroy eval exists extractConfigureArg f filter filterappend filterguard filtersearch forward hasclass id incr info infoTraceFilter init instvar invar isclass ismetaclass ismixin isobject istype lappend mixin mixinappend mixinguard move name noinit parametercmd print proc procsearch recreate requireNamespace salary self set setFilter signature tclcmd trace unset uplevel upvar volatile vwait" "all methods in context" ::errorCheck [my show payrollApp jim] "{payrollApp: jim info methods salary => salary} {payrollApp: jim info methods -incontext salary => salary} {payrollApp: jim info methods driv* => driving-license} {payrollApp: jim info methods -incontext driv* => }" "payrollApp jim" ::errorCheck [my show shipmentApp jim] "{shipmentApp: jim info methods salary => salary} {shipmentApp: jim info methods -incontext salary => } {shipmentApp: jim info methods driv* => driving-license} {shipmentApp: jim info methods -incontext driv* => driving-license}" "shipmentApp jim" return "PASSED [self]" } TestX create volatileObjects @ TestX volatileObjects { description { Regression test for volatile objects } } volatileObjects proc inscope {} { set r 0 set y 0 set z 0 set c [C new -volatile] catch {incr r [$c test]} catch {set y [$c y]} catch {set z [$c z]} if {[catch {set u [$c u]} err]} {puts stderr $err} return $r-[llength [C info instances]]-$y-$z-$u } volatileObjects proc run {{n 20}} { Class create ::xotcl::_creator -instproc create {args} { set result [next] return $result } Class instproc f args { #puts stderr "*****F [self calledproc]" return [next] } Class C -parameter {{x 0}} C instproc f args { #puts stderr "*****C [self calledproc]" return [next] } C instproc test {} { my incr x } C instproc y {} { my instvar x; incr x } C instproc z {} { my set x 10 } C instproc u {} { upvar [self callinglevel] z b; info exists b } Class create ::xotcl::I -instproc instvar args { #puts [self proc] next } -instproc set args { #puts [self proc] next } -instproc u args { #puts [self proc] next } ::errorCheck [llength [C info instances]] 0 "[self]: foreign instances" ::errorCheck [my inscope] 1-1-2-10-1 "[self]: volatile objects in scope" ::errorCheck [llength [C info instances]] 0 "[self]: instances survived scope" Class instmixin ::xotcl::_creator ::errorCheck [my inscope] 1-1-2-10-1 \ "[self]: volatile objects in scope through mixin" ::errorCheck [llength [C info instances]] 0 \ "[self]: instances survived scope through mixin" Class instfilter f ::errorCheck [my inscope] 1-1-2-10-1 \ "[self]: volatile objects in scope through mixin + filter" ::errorCheck [llength [C info instances]] 0 \ "[self]: instances survived scope through mixin + filter" Class instmixin {} Class instfilter f ::errorCheck [my inscope] 1-1-2-10-1 \ "[self]: volatile objects in scope through filter" ::errorCheck [llength [C info instances]] 0 \ "[self]: instances survived scope through filter" Class instfilter {} C instmixin ::xotcl::I ::errorCheck [my inscope] 1-1-2-10-1 \ "[self]: instvar overload in scope through mixin" C instfilter f ::errorCheck [my inscope] 1-1-2-10-1 \ "[self]: instvar overload in scope through mixin and filter" C instfilter {} Class instproc f {} {} return "PASSED [self]" } TestX create uplevelCmds uplevelCmds proc upproc {} { lappend ::result [list \ self=[self] \ up1=[uplevel 1 self] \ up2=[uplevel 2 self] \ up3=[uplevel 3 self] ] } uplevelCmds proc run {{n 20}} { Object o1 -proc m {} { set ::result [list] lappend ::result [list \ self=[self] \ up1=[uplevel 1 self] \ up2=[uplevel 2 self] \ up3=[uplevel 3 self] ] uplevelCmds::upproc return $::result } Object o2 -proc m {} { o1 m } Object o3 -proc m {} { o2 m } Object o4 -proc m {} { o3 m } ::errorCheck [o4 m] \ "{self=::o1 up1=::o2 up2=::o3 up3=::o4} {self=::o1 up1=::o2 up2=::o2 up3=::o3}" \ "[self]: uplevel self" o4 m proc showstack {} { set l [info level] for {set i $l} {$i>0} {incr i -1} { set vars [uplevel \#$i info vars] upvar \#$i what w if {![info exists w]} {set w ""} puts "$i: $w[info level $i] vars=$vars" } } Class C C instproc u0 {} { upvar [self callinglevel] x y; incr y return [uplevel [self callinglevel] {incr x 1}] } C instproc u1 {} { upvar [self callinglevel] x y; incr y set r [uplevel [self callinglevel] {incr x 1}] set z [uplevel [self activelevel] incr z] return $z-$r } C instproc p0 {y} { set x $y set r [my u0] return $r-$x } C instproc p1 {y} { set z 0 set x $y set r [my u1] return $r-$x } Class D -superclass C D instproc u0 {} { upvar [self callinglevel] x y; incr y return [uplevel [self callinglevel] {incr x 1}] } D instproc u1 {} { set z [uplevel [self activelevel] incr z] set r [next] return $z-$r } Class M M instproc u1 {} { set z [uplevel [self activelevel] incr z] set r [next] return $z-$r } Object instproc f args { next } D create d1 errorCheck [d1 p0 1] 3-3 "simple uplevel" errorCheck [d1 p1 1] 2-2-3-3 "uplevel through next in class hierarchy + activelevel" D instmixin M errorCheck [d1 p1 1] 1-3-3-3-3 "uplevel through mixin and class hierarchy + activelevel" Object instfilter f errorCheck [d1 p1 1] 1-3-3-3-3 "uplevel through filter, mixin and class hierarchy + activelevel" Object instfilter "" D instmixin {} # now again the same tests with upvar and uplevel methods C instproc u0 {} { my upvar [self callinglevel] x y; incr y return [my uplevel {incr x 1}] } C instproc u1 {} { my upvar [self callinglevel] x y; incr y set r [my uplevel {incr x 1}] set z [my uplevel [self activelevel] incr z] return $z-$r } D instproc u0 {} { my upvar [self callinglevel] x y; incr y return [my uplevel {incr x 1}] } Class M M instproc u1 {} { set z [my uplevel [self activelevel] incr z] set r [next] return $z-$r } errorCheck [d1 p0 1] 3-3 "upvar method: simple uplevel" errorCheck [d1 p1 1] 2-2-3-3 \ "upvar method: uplevel through next in class hierarchy + activelevel" D instmixin M errorCheck [d1 p1 1] 1-3-3-3-3 \ "upvar method: uplevel through mixin and class hierarchy + activelevel" Object instfilter f errorCheck [d1 p1 1] 1-3-3-3-3 \ "upvar method: uplevel through filter, mixin and class hierarchy + activelevel" Object instfilter "" D instmixin {} # now again the same tests with upvar and uplevel methods with default levels C instproc u0 {} { my upvar x y; incr y return [my uplevel {incr x 1}] } C instproc u1 {} { my upvar x y; incr y set r [my uplevel {incr x 1}] set z [my uplevel [self activelevel] incr z] return $z-$r } D instproc u0 {} { my upvar x y; incr y return [my uplevel {incr x 1}] } Class M M instproc u1 {} { set z [my uplevel [self activelevel] incr z] set r [next] return $z-$r } errorCheck [d1 p0 1] 3-3 "upvar method: simple uplevel (dl)" errorCheck [d1 p1 1] 2-2-3-3 \ "upvar method: uplevel through next in class hierarchy + activelevel (dl)" D instmixin M errorCheck [d1 p1 1] 1-3-3-3-3 \ "upvar method: uplevel through mixin and class hierarchy + activelevel (dl)" Object instfilter f errorCheck [d1 p1 1] 1-3-3-3-3 \ "upvar method: uplevel through filter, mixin and class hierarchy + activelevel (dl)" Object instfilter "" D instmixin {} return "PASSED [self]" } TestX proc run {} { puts [nestingClasses run] puts [nestingObjects run] puts [assertions run] puts [stdargs run] puts [filterAddRemove run] puts [filterClassChange run] puts [filterSimpleObserver run] puts [filterInfo run] puts [filterGuards run] puts [nextTest run] puts [init_params run] puts [mixinTest run] puts [mixinInheritanceTest run] puts [mixinGuards run] puts [copymove run] puts [recreation run] puts [smallScripts run] puts [objectReferences run] puts [condMixins run] puts [volatileObjects run] puts [uplevelCmds run] } puts "XOTcl - Test" puts "Time used: [time {TestX run} 1]" # toplevel tests ################################################# Class instmixin {} C instmixin {} set o [C new -volatile];errorCheck [Object isobject $o] 1 "topLevel, check object 1 - $o" Class instmixin ::xotcl::_creator set o [C new -volatile];errorCheck [Object isobject $o] 1 "topLevel, check object 2 - $o" C instmixin ::xotcl::I set o [C new -volatile];errorCheck [Object isobject $o] 1 "topLevel, check object 3 - $o" foreach i [C info instances] {$i destroy} proc x {} { Class instmixin {} C instmixin {} set c0 [llength [C info instances]] set o [C new -volatile]; errorCheck [Object isobject $o] 1 "x, check object" Class instmixin ::xotcl::_creator set o [C new -volatile]; errorCheck [Object isobject $o] 1 "x, check object" C instmixin ::xotcl::I set o [C new -volatile]; errorCheck [Object isobject $o] 1 "x, check object" set c1 [llength [C info instances]] errorCheck [expr {$c1 - $c0 != 3}] 0 "exit x, three more objects" } x errorCheck [expr {[llength [C info instances]] > 0}] 0 "top, all volatile object gone" proc x1 {} { set c0 [llength [C info instances]] set o [C new -volatile]; errorCheck [Object isobject $o] 1 "x1, check object" x set o [C new -volatile]; errorCheck [Object isobject $o] 1 "x1, check object" set c1 [llength [C info instances]] errorCheck [expr {$c1 - $c0 != 2}] 0 "exit x1, two more objects" } x1 errorCheck [expr {[llength [C info instances]] > 0}] 0 "top, volatile objects gone" Object o o proc test {} { x1; errorCheck [expr {[llength [C info instances]] > 0}] 0 "x1 from o" } o test puts "PASSED ::topLevelCommands"