home *** CD-ROM | disk | FTP | other *** search
- #
- # Tests for inheritance and scope handling
- # ----------------------------------------------------------------------
- # AUTHOR: Michael J. McLennan Phone: (610)712-2842
- # AT&T Bell Laboratories E-mail: michael.mclennan@att.com
- #
- # RCS: inherit.test,v 1.3 1994/04/08 13:40:20 mmc Exp
- # ----------------------------------------------------------------------
- # Copyright (c) 1993 AT&T Bell Laboratories
- # ======================================================================
- # Permission to use, copy, modify, and distribute this software and its
- # documentation for any purpose and without fee is hereby granted,
- # provided that the above copyright notice appear in all copies and that
- # both that the copyright notice and warranty disclaimer appear in
- # supporting documentation, and that the names of AT&T Bell Laboratories
- # any of their entities not be used in advertising or publicity
- # pertaining to distribution of the software without specific, written
- # prior permission.
- #
- # AT&T disclaims all warranties with regard to this software, including
- # all implied warranties of merchantability and fitness. In no event
- # shall AT&T be liable for any special, indirect or consequential
- # damages or any damages whatsoever resulting from loss of use, data or
- # profits, whether in an action of contract, negligence or other
- # tortuous action, arising out of or in connection with the use or
- # performance of this software.
- # ======================================================================
-
- # ----------------------------------------------------------------------
- # MULTIPLE BASE-CLASS ERROR DETECTION
- # ----------------------------------------------------------------------
- test {Cannot inherit from the same base class more than once} {
- catch "VirtualErr" errmsg
- set errmsg
- } {
- $result == {error while autoloading "VirtualErr": class "VirtualErr" inherits base class "Foo" more than once:
- VirtualErr->Mongrel->FooBar->Foo
- VirtualErr->Foo
- VirtualErr->BarFoo->Foo}
- }
-
- # ----------------------------------------------------------------------
- # CONSTRUCTION
- # ----------------------------------------------------------------------
- test {Constructors should be invoked implicitly} {
- set WATCH ""
- concat [Mongrel m] / $WATCH
- } {
- $result == "m / Mongrel FooBar Foo Bar Geek"
- }
-
- test {Initialization of shadowed variables works properly} {
- concat [m info public blit -value] / [m info public Foo::blit -value]
- } {
- $result == "nonnull / <undefined>"
- }
-
- # ----------------------------------------------------------------------
- # PUBLIC VARIABLES
- # ----------------------------------------------------------------------
- test {Inherited "config" method works on derived classes} {
- m config -blit xyz -Foo::blit pdq
- } {
- $result == "Mongrel::blit Foo::blit"
- }
-
- test {Inherited "config" method works on derived classes} {
- m config -blit xyz -Foo::blit pdq
- concat [m info public blit -value] / [m info public Foo::blit -value]
- } {
- $result == "xyz / pdq"
- }
-
- test {Inherited "config" method works on derived classes} {
- m config -tag #0000
- } {
- $result == "Mongrel::tag"
- }
-
- # ----------------------------------------------------------------------
- # INHERITANCE INFO
- # ----------------------------------------------------------------------
- test {Info: class} {
- m info class
- } {
- $result == "Mongrel"
- }
-
- test {Info: inherit} {
- m info inherit
- } {
- $result == "FooBar Geek"
- }
-
- test {Info: heritage} {
- m info heritage
- } {
- $result == "Mongrel FooBar Foo Bar Geek"
- }
-
- test {Built-in "isa" method} {
- set status 1
- foreach c [m info heritage] {
- set status [expr {$status && [m isa $c]}]
- }
- set status
- } {
- $result == 1
- }
-
- test {Built-in "isa" method} {
- m isa Watermelon
- } {
- $result == 0
- }
-
- # ----------------------------------------------------------------------
- # SCOPE MANIPULATION
- # ----------------------------------------------------------------------
- test {commands normally execute in the scope of their class} {
- m Foo::do {info class}
- } {
- $result == "Foo says 'Foo'"
- }
-
- test {"virtual" command moves scope to most specific class} {
- m Foo::do {virtual info class}
- } {
- $result == "Foo says 'Mongrel'"
- }
-
- test {"previous" command moves scope upward in hierarchy} {
- m do {virtual previous info class}
- } {
- $result == "Foo says 'FooBar'"
- }
-
- test {"previous" command can be chained} {
- m do {virtual previous previous info class}
- } {
- $result == "Foo says 'Foo'"
- }
-
- # ----------------------------------------------------------------------
- # METHOD INVOCATION
- # ----------------------------------------------------------------------
- test {Simple method names are assigned based on heritage} {
- m do {concat "$this ([virtual info class]) at scope [info class]::"}
- } {
- $result == "Foo says 'm (Mongrel) at scope Foo::'"
- }
-
- test {Explicit scoping can be used to reach shadowed members} {
- m Geek::do {concat "$this ([virtual info class]) at scope [info class]::"}
- } {
- $result == "Geek says 'm (Mongrel) at scope Geek::'"
- }
-
- test {Methods execute in local scope of class, e.g., Foo::do} {
- m config -blit abc -Foo::blit def
- m Foo::do {set blit xyz}
- concat [m info public blit -value] / [m info public Foo::blit -value]
- } {
- $result == "abc / xyz"
- }
-
- # ----------------------------------------------------------------------
- # DESTRUCTION
- # ----------------------------------------------------------------------
- test {Destructors should be invoked implicitly} {
- set WATCH ""
- concat [m delete] / $WATCH
- } {
- $result == "/ Mongrel Geek Bar Foo FooBar"
- }
-
- # ----------------------------------------------------------------------
- # OBJECT INFO
- # ----------------------------------------------------------------------
- foreach obj [itcl_info objects] {
- $obj delete
- }
- Mongrel m
- FooBar fb
- Foo f
- Geek g
-
- test {Object queries can be restricted by object name} {
- itcl_info objects f*
- } {
- [test_cmp_lists $result {f fb}]
- }
-
- test {Object queries can be restricted to specific classes} {
- itcl_info objects -class Foo
- } {
- $result == "f"
- }
-
- test {Object queries can be restricted by object heritage} {
- itcl_info objects -isa Foo
- } {
- [test_cmp_lists $result {m f fb}]
- }
-
- test {Object queries can be restricted by object name / specific classes} {
- itcl_info objects f* -class Foo
- } {
- $result == "f"
- }
-
- test {Object queries can be restricted by object name / object heritage} {
- itcl_info objects f* -isa Foo
- } {
- [test_cmp_lists $result {f fb}]
- }
-
- # ----------------------------------------------------------------------
- # ERROR HANDLING ACROSS CLASS BOUNDARIES
- # ----------------------------------------------------------------------
- Mongrel m1
- FooBar fb2
-
- test {Errors and detected and reported across class boundaries} {
- set status [catch {m1 do {fb2 do {error "test"}}} mesg]
- format "$mesg $status"
- } {
- $result == "test 1"
- }
-
- test {Stack trace unwinds properly across class boundaries} {
- catch {m1 do {fb2 do {error "test"}}} mesg
- format "$errorInfo"
- } {
- $result == {test
- while executing
- "error "test""
- ("eval" body line 1)
- invoked from within
- "eval $cmds"
- invoked from within
- "return "Foo says '[eval $cmds]..."
- (object "fb2" method "FooBar::do" body line 2)
- invoked from within
- "fb2 do {error "test"}"
- invoked from within
- "fb2 do {error "test"}"
- ("eval" body line 1)
- invoked from within
- "eval $cmds"
- invoked from within
- "return "Foo says '[eval $cmds]..."
- (object "m1" method "Mongrel::do" body line 2)
- invoked from within
- "m1 do {fb2 do {error "test"}}"}
- }
-
- test {Stack trace unwinds properly across class boundaries} {
- catch {m1 do {fb2 do {error "test" "some error"}}} mesg
- format "$errorInfo"
- } {
- $result == {some error
- ("eval" body line 2)
- invoked from within
- "eval $cmds"
- invoked from within
- "return "Foo says '[eval $cmds]..."
- (object "fb2" method "FooBar::do" body line 2)
- invoked from within
- "fb2 do {error "test" "some error"}"
- invoked from within
- "fb2 do {error "test" "some error"}"
- ("eval" body line 1)
- invoked from within
- "eval $cmds"
- invoked from within
- "return "Foo says '[eval $cmds]..."
- (object "m1" method "Mongrel::do" body line 2)
- invoked from within
- "m1 do {fb2 do {error "test" "some error"}}"}
- }
-
- test {Error codes are preserved across class boundaries} {
- catch {m1 do {fb2 do {error "test" "some error" CODE-BLUE}}} mesg
- format "$errorCode"
- } {
- $result == "CODE-BLUE"
- }
-