OpenFPGA/libs/EXTERNAL/tcl8.6.12/tests/ooNext2.test

1066 lines
25 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# This file contains a collection of tests for Tcl's built-in object system.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2006-2011 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require TclOO 1.0.3
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
proc getbytes {} {
set lines [split [memory info] \n]
return [lindex $lines 3 3]
}
proc leaktest {script {iterations 3}} {
set end [getbytes]
for {set i 0} {$i < $iterations} {incr i} {
uplevel 1 $script
set tmp $end
set end [getbytes]
}
return [expr {$end - $tmp}]
}
}
test oo-nextto-1.1 {basic nextto functionality} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x args {
lappend ::result ==A== $args
}
}
oo::class create B {
superclass A
method x args {
lappend ::result ==B== $args
nextto A B -> A {*}$args
}
}
oo::class create C {
superclass A
method x args {
lappend ::result ==C== $args
nextto A C -> A {*}$args
}
}
oo::class create D {
superclass B C
method x args {
lappend ::result ==D== $args
next foo
nextto C bar
}
}
set ::result {}
[D new] x
return $::result
} -cleanup {
root destroy
} -result {==D== {} ==B== foo ==A== {B -> A foo} ==C== bar ==A== {C -> A bar}}
test oo-nextto-1.2 {basic nextto functionality} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x args {
lappend ::result ==A== $args
}
}
oo::class create B {
superclass A
method x args {
lappend ::result ==B== $args
nextto A B -> A {*}$args
}
}
oo::class create C {
superclass A
method x args {
lappend ::result ==C== $args
nextto A C -> A {*}$args
}
}
oo::class create D {
superclass B C
method x args {
lappend ::result ==D== $args
nextto B foo {*}$args
nextto C bar {*}$args
}
}
set ::result {}
[D new] x 123
return $::result
} -cleanup {
root destroy
} -result {==D== 123 ==B== {foo 123} ==A== {B -> A foo 123} ==C== {bar 123} ==A== {C -> A bar 123}}
test oo-nextto-1.3 {basic nextto functionality: constructors} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
variable result
constructor {a c} {
lappend result ==A== a=$a,c=$c
}
}
oo::class create B {
superclass root
variable result
constructor {b} {
lappend result ==B== b=$b
}
}
oo::class create C {
superclass A B
variable result
constructor {p q r} {
lappend result ==C== p=$p,q=$q,r=$r
# Route arguments to superclasses, in non-trival pattern
nextto B $q
nextto A $p $r
}
method result {} {return $result}
}
[C new x y z] result
} -cleanup {
root destroy
} -result {==C== p=x,q=y,r=z ==B== b=y ==A== a=x,c=z}
test oo-nextto-1.4 {basic nextto functionality: destructors} -setup {
oo::class create root {destructor return}
} -body {
oo::class create A {
superclass root
destructor {
lappend ::result ==A==
next
}
}
oo::class create B {
superclass root
destructor {
lappend ::result ==B==
next
}
}
oo::class create C {
superclass A B
destructor {
lappend ::result ==C==
lappend ::result |
nextto B
lappend ::result |
nextto A
lappend ::result |
next
}
}
set ::result ""
[C new] destroy
return $::result
} -cleanup {
root destroy
} -result {==C== | ==B== | ==A== ==B== | ==A== ==B==}
test oo-nextto-2.1 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {error $y}
}
oo::class create B {
superclass A
method x y {nextto A $y}
}
[B new] x boom
} -cleanup {
root destroy
} -result boom -returnCodes error
test oo-nextto-2.2 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {error $y}
}
oo::class create B {
superclass root
method x y {nextto A $y}
}
[B new] x boom
} -returnCodes error -cleanup {
root destroy
} -result {method has no non-filter implementation by "A"}
test oo-nextto-2.3 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {nextto $y}
}
oo::class create B {
superclass A
method x y {nextto A $y}
}
[B new] x B
} -returnCodes error -cleanup {
root destroy
} -result {method implementation by "B" not reachable from here}
test oo-nextto-2.4 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {nextto $y}
}
oo::class create B {
superclass A
method x y {nextto}
}
[B new] x B
} -returnCodes error -cleanup {
root destroy
} -result {wrong # args: should be "nextto class ?arg...?"}
test oo-nextto-2.5 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {nextto $y}
}
oo::class create B {
superclass A
method x y {nextto $y $y $y}
}
[B new] x A
} -cleanup {
root destroy
} -result {wrong # args: should be "nextto A y"} -returnCodes error
test oo-nextto-2.6 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {nextto $y}
}
oo::class create B {
superclass A
method x y {nextto $y $y $y}
}
[B new] x [root create notAClass]
} -cleanup {
root destroy
} -result {"::notAClass" is not a class} -returnCodes error
test oo-nextto-2.7 {errors in nextto} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x y {nextto $y}
}
oo::class create B {
superclass A
filter Y
method Y args {next {*}$args}
}
oo::class create C {
superclass B
method x y {nextto $y $y $y}
}
[C new] x B
} -returnCodes error -cleanup {
root destroy
} -result {method has no non-filter implementation by "B"}
test oo-call-1.1 {object call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
A create y
info object call y x
} -cleanup {
root destroy
} -result {{method x ::A method}}
test oo-call-1.2 {object call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
}
B create y
info object call y x
} -cleanup {
root destroy
} -result {{method x ::B method} {method x ::A method}}
test oo-call-1.3 {object call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
A create y
oo::objdefine y method x {} {}
info object call y x
} -cleanup {
root destroy
} -result {{method x object method} {method x ::A method}}
test oo-call-1.4 {object object call introspection - unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
A create y
info object call y z
} -cleanup {
root destroy
} -result {{unknown unknown ::oo::object {core method: "unknown"}}}
test oo-call-1.5 {object call introspection - filters} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method y {} {}
filter y
}
A create y
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::A method} {method x ::A method}}
test oo-call-1.6 {object call introspection - filters} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method x {} {}
}
B create y
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::A method} {method x ::B method} {method x ::A method}}
test oo-call-1.7 {object call introspection - filters} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method x {} {}
method y {} {}
}
B create y
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::B method} {filter y ::A method} {method x ::B method} {method x ::A method}}
test oo-call-1.8 {object call introspection - filters} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method x {} {}
method y {} {}
method z {} {}
filter z
}
B create y
info object call y x
} -cleanup {
root destroy
} -result {{filter z ::B method} {filter y ::B method} {filter y ::A method} {method x ::B method} {method x ::A method}}
test oo-call-1.9 {object call introspection - filters} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method x {} {}
method y {} {}
method z {} {}
filter z
}
B create y
info object call y y
} -cleanup {
root destroy
} -result {{filter z ::B method} {filter y ::B method} {filter y ::A method} {method y ::B method} {method y ::A method}}
test oo-call-1.10 {object call introspection - filters + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method y {} {}
method unknown {} {}
}
B create y
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::B method} {filter y ::A method} {unknown unknown ::B method} {unknown unknown ::oo::object {core method: "unknown"}}}
test oo-call-1.11 {object call introspection - filters + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method y {} {}
filter y
}
A create y
oo::objdefine y method unknown {} {}
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::A method} {unknown unknown object method} {unknown unknown ::oo::object {core method: "unknown"}}}
test oo-call-1.12 {object call introspection - filters + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method y {} {}
}
A create y
oo::objdefine y {
method unknown {} {}
filter y
}
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::A method} {unknown unknown object method} {unknown unknown ::oo::object {core method: "unknown"}}}
test oo-call-1.13 {object call introspection - filters + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method y {} {}
}
A create y
oo::objdefine y {
method unknown {} {}
method x {} {}
filter y
}
info object call y x
} -cleanup {
root destroy
} -result {{filter y ::A method} {method x object method}}
test oo-call-1.14 {object call introspection - errors} -body {
info object call
} -returnCodes error -result {wrong # args: should be "info object call objName methodName"}
test oo-call-1.15 {object call introspection - errors} -body {
info object call a
} -returnCodes error -result {wrong # args: should be "info object call objName methodName"}
test oo-call-1.16 {object call introspection - errors} -body {
info object call a b c
} -returnCodes error -result {wrong # args: should be "info object call objName methodName"}
test oo-call-1.17 {object call introspection - errors} -body {
info object call notanobject x
} -returnCodes error -result {notanobject does not refer to an object}
test oo-call-1.18 {object call introspection - memory leaks} -body {
leaktest {
info object call oo::object destroy
}
} -constraints memory -result 0
test oo-call-1.19 {object call introspection - memory leaks} -setup {
oo::class create leaktester { method foo {} {dummy} }
} -body {
leaktest {
set lt [leaktester new]
oo::objdefine $lt method foobar {} {dummy}
list [info object call $lt destroy] \
[info object call $lt foo] \
[info object call $lt bar] \
[info object call $lt foobar] \
[$lt destroy]
}
} -cleanup {
leaktester destroy
} -constraints memory -result 0
test oo-call-1.20 {object call introspection - complex case} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
}
oo::class create ::C {
superclass root
method x {} {}
mixin B
}
oo::class create ::D {
superclass C
method x {} {}
}
oo::class create ::E {
superclass root
method x {} {}
}
oo::class create ::F {
superclass E
method x {} {}
}
oo::class create ::G {
superclass root
method x {} {}
}
oo::class create ::H {
superclass G
method x {} {}
}
oo::define F mixin H
F create y
oo::objdefine y {
method x {} {}
mixin D
}
info object call y x
} -cleanup {
root destroy
} -result {{method x ::D method} {method x ::B method} {method x ::A method} {method x ::C method} {method x ::H method} {method x ::G method} {method x object method} {method x ::F method} {method x ::E method}}
test oo-call-1.21 {object call introspection - complex case} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method y {} {}
filter y
}
oo::class create ::B {
superclass A
method y {} {}
}
oo::class create ::C {
superclass root
method x {} {}
mixin B
}
oo::class create ::D {
superclass C
filter x
}
oo::class create ::E {
superclass root
method y {} {}
method x {} {}
}
oo::class create ::F {
superclass E
method z {} {}
method q {} {}
}
F create y
oo::objdefine y {
method unknown {} {}
mixin D
filter q
}
info object call y z
} -cleanup {
root destroy
} -result {{filter x ::C method} {filter x ::E method} {filter y ::B method} {filter y ::A method} {filter y ::E method} {filter q ::F method} {method z ::F method}}
test oo-call-2.1 {class call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
info class call A x
} -cleanup {
root destroy
} -result {{method x ::A method}}
test oo-call-2.2 {class call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
}
list [info class call A x] [info class call B x]
} -cleanup {
root destroy
} -result {{{method x ::A method}} {{method x ::B method} {method x ::A method}}}
test oo-call-2.3 {class call introspection} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
}
oo::class create ::C {
superclass A
method x {} {}
}
oo::class create ::D {
superclass C B
method x {} {}
}
info class call D x
} -cleanup {
root destroy
} -result {{method x ::D method} {method x ::C method} {method x ::B method} {method x ::A method}}
test oo-call-2.4 {class call introspection - mixin} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
}
oo::class create ::C {
superclass A
method x {} {}
}
oo::class create ::D {
superclass C
mixin B
method x {} {}
}
info class call D x
} -cleanup {
root destroy
} -result {{method x ::B method} {method x ::D method} {method x ::C method} {method x ::A method}}
test oo-call-2.5 {class call introspection - mixin + filter} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
method y {} {}
filter y
}
oo::class create ::C {
superclass A
method x {} {}
method y {} {}
}
oo::class create ::D {
superclass C
mixin B
method x {} {}
}
info class call D x
} -cleanup {
root destroy
} -result {{filter y ::B method} {filter y ::C method} {method x ::B method} {method x ::D method} {method x ::C method} {method x ::A method}}
test oo-call-2.6 {class call introspection - mixin + filter + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
method unknown {} {}
}
oo::class create ::B {
superclass A
method x {} {}
method y {} {}
filter y
}
oo::class create ::C {
superclass A
method x {} {}
method y {} {}
}
oo::class create ::D {
superclass C
mixin B
method x {} {}
method unknown {} {}
}
info class call D z
} -cleanup {
root destroy
} -result {{filter y ::B method} {filter y ::C method} {unknown unknown ::D method} {unknown unknown ::A method} {unknown unknown ::oo::object {core method: "unknown"}}}
test oo-call-2.7 {class call introspection - mixin + filter + unknown} -setup {
oo::class create root
} -body {
oo::class create ::A {
superclass root
method x {} {}
}
oo::class create ::B {
superclass A
method x {} {}
filter x
}
info class call B x
} -cleanup {
root destroy
} -result {{filter x ::B method} {filter x ::A method} {method x ::B method} {method x ::A method}}
test oo-call-2.8 {class call introspection - errors} -body {
info class call
} -returnCodes error -result {wrong # args: should be "info class call className methodName"}
test oo-call-2.9 {class call introspection - errors} -body {
info class call a
} -returnCodes error -result {wrong # args: should be "info class call className methodName"}
test oo-call-2.10 {class call introspection - errors} -body {
info class call a b c
} -returnCodes error -result {wrong # args: should be "info class call className methodName"}
test oo-call-2.11 {class call introspection - errors} -body {
info class call notaclass x
} -returnCodes error -result {notaclass does not refer to an object}
test oo-call-2.12 {class call introspection - errors} -setup {
oo::class create root
} -body {
root create notaclass
info class call notaclass x
} -returnCodes error -cleanup {
root destroy
} -result {"notaclass" is not a class}
test oo-call-2.13 {class call introspection - memory leaks} -body {
leaktest {
info class call oo::class destroy
}
} -constraints memory -result 0
test oo-call-2.14 {class call introspection - memory leaks} -body {
leaktest {
oo::class create leaktester { method foo {} {dummy} }
[leaktester new] destroy
list [info class call leaktester destroy] \
[info class call leaktester foo] \
[info class call leaktester bar] \
[leaktester destroy]
}
} -constraints memory -result 0
test oo-call-3.1 {current call introspection} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
method x {} {lappend ::result [self call]}
}
oo::class create B {
superclass A
method x {} {lappend ::result [self call];next}
}
B create y
oo::objdefine y method x {} {lappend ::result [self call];next}
set ::result {}
y x
} -cleanup {
root destroy
} -result {{{{method x object method} {method x ::B method} {method x ::A method}} 0} {{{method x object method} {method x ::B method} {method x ::A method}} 1} {{{method x object method} {method x ::B method} {method x ::A method}} 2}}
test oo-call-3.2 {current call introspection} -setup {
oo::class create root
} -constraints memory -body {
oo::class create A {
superclass root
method x {} {self call}
}
oo::class create B {
superclass A
method x {} {self call;next}
}
B create y
oo::objdefine y method x {} {self call;next}
leaktest {
y x
}
} -cleanup {
root destroy
} -result 0
test oo-call-3.3 {current call introspection: in constructors} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
constructor {} {lappend ::result [self call]}
}
oo::class create B {
superclass A
constructor {} {lappend ::result [self call]; next}
}
set ::result {}
[B new] destroy
return $::result
} -cleanup {
root destroy
} -result {{{{method <constructor> ::B method} {method <constructor> ::A method}} 0} {{{method <constructor> ::B method} {method <constructor> ::A method}} 1}}
test oo-call-3.4 {current call introspection: in destructors} -setup {
oo::class create root
} -body {
oo::class create A {
superclass root
destructor {lappend ::result [self call]}
}
oo::class create B {
superclass A
destructor {lappend ::result [self call]; next}
}
set ::result {}
[B new] destroy
return $::result
} -cleanup {
root destroy
} -result {{{{method <destructor> ::B method} {method <destructor> ::A method}} 0} {{{method <destructor> ::B method} {method <destructor> ::A method}} 1}}
# Contributed tests from aspect, related to [0f42ff7871]
#
# dkf's "Principles Leading to a Fix"
#
# A method ought to work "the same" whether or not it has been overridden by
# a subclass. A tailcalled command ought to have as parent stack the same
# thing you'd get with uplevel 1. A subclass will often expect the
# superclass's result to be the result that would be returned if the
# subclass was not there.
# Common setup:
# any invocation of bar should emit "abc\nhi\n" then return to its
# caller
set testopts {
-setup {
oo::class create Parent
oo::class create Foo {
superclass Parent
method bar {} {
puts abc
tailcall puts hi
puts xyz
}
}
oo::class create Foo2 {
superclass Parent
}
}
-cleanup {
Parent destroy
}
}
# these succeed, showing that without [next] the bug doesn't fire
test next-tailcall-simple-1 "trivial case with one method" {*}$testopts -body {
[Foo create foo] bar
} -output [join {abc hi} \n]\n
test next-tailcall-simple-2 "my bar" {*}$testopts -body {
oo::define Foo method baz {} {
puts a
my bar
puts b
}
[Foo create foo] baz
} -output [join {a abc hi b} \n]\n
test next-tailcall-simple-3 "\[self\] bar" {*}$testopts -body {
oo::define Foo method baz {} {
puts a
[self] bar
puts b
}
[Foo create foo] baz
} -output [join {a abc hi b} \n]\n
test next-tailcall-simple-4 "foo bar" {*}$testopts -body {
oo::define Foo method baz {} {
puts a
foo bar
puts b
}
[Foo create foo] baz
} -output [join {a abc hi b} \n]\n
# everything from here on uses [next], and fails on 8.6.4 with compilation
test next-tailcall-superclass-1 "next superclass" {*}$testopts -body {
oo::define Foo2 {
superclass Foo
method bar {} {
puts a
next
puts b
}
}
[Foo2 create foo] bar
} -output [join {a abc hi b} \n]\n
test next-tailcall-superclass-2 "nextto superclass" {*}$testopts -body {
oo::define Foo2 {
superclass Foo
method bar {} {
puts a
nextto Foo
puts b
}
}
[Foo2 create foo] bar
} -output [join {a abc hi b} \n]\n
test next-tailcall-mixin-1 "class mixin" {*}$testopts -body {
oo::define Foo2 {
method Bar {} {
puts a
next
puts b
}
filter Bar
}
oo::define Foo mixin Foo2
Foo create foo
foo bar
} -output [join {a abc hi b} \n]\n
test next-tailcall-objmixin-1 "object mixin" {*}$testopts -body {
oo::define Foo2 {
method Bar {} {
puts a
next
puts b
}
filter Bar
}
Foo create foo
oo::objdefine foo mixin Foo2
foo bar
} -output [join {a abc hi b} \n]\n
test next-tailcall-filter-1 "filter method" {*}$testopts -body {
oo::define Foo method Filter {} {
puts a
next
puts b
}
oo::define Foo filter Filter
[Foo new] bar
} -output [join {a abc hi b} \n]\n
test next-tailcall-forward-1 "forward method" {*}$testopts -body {
proc foobar {} {
puts "abc"
tailcall puts "hi"
puts "xyz"
}
oo::define Foo forward foobar foobar
oo::define Foo2 {
superclass Foo
method foobar {} {
puts a
next
puts b
}
}
[Foo2 new] foobar
} -output [join {a abc hi b} \n]\n
test next-tailcall-constructor-1 "next in constructor" -body {
oo::class create Foo {
constructor {} {
puts abc
tailcall puts hi
puts xyz
}
}
oo::class create Foo2 {
superclass Foo
constructor {} {
puts a
next
puts b
}
}
list [Foo new] [Foo2 new]
return ""
} -cleanup {
Foo destroy
} -output [join {abc hi a abc hi b} \n]\n
test next-tailcall-destructor-1 "next in destructor" -body {
oo::class create Foo {
destructor {
puts abc
tailcall puts hi
puts xyz
}
}
oo::class create Foo2 {
superclass Foo
destructor {
puts a
next
puts b
}
}
Foo create foo
Foo2 create foo2
foo destroy
foo2 destroy
} -output [join {abc hi a abc hi b} \n]\n -cleanup {
Foo destroy
}
unset testopts
cleanupTests
return
# Local Variables:
# mode: tcl
# End: