#!../tsh

# Test Script for Object Tcl

# Test Procedure used by all tests
# id is the test identifier
# code is the test scenario
# optional -dontclean argument will stop the test classes being cleaned out
proc Test {id code args} {
   puts "Test ($id) begin \{"
   set result [catch {eval $code} msg]
   if {$result == 0} {
      if {$msg != ""} {
         puts $msg
      }
   } else {
      global errorInfo
      puts "Completed with error ($result):\n$errorInfo"
   }
   puts "\} Test ($id) end\n"

   if {[llength $args] == 0 || [lindex $args 0] != "-dontclean"} {
      # An un-documented command to clear out the Otcl classes,
      # only used here to making thinking of class names easier in testing
      # not recommended
      otcl clear
   }
}

Test 1.1 {
   # Not enough args for otclInterface command
   otclInterface AClass
}

Test 1.2 {
   # Too many args for otclInterface command
   otclInterface AClass -isA AnotherClass {body} tooMany
}

Test 1.3 {
   # Illegal args for otclInterface
   otclInterface AClass blah {body}
}

Test 1.4 {
   # Illegal args for otclInterface
   otclInterface AClass -isA {}
}

Test 1.5 {
   # Illegal args for otclInterface as AClass doesn't exist
   otclInterface BClass -isA AClass {}
}

Test 1.6 {
   # Illegal args for otclInterface
   otclInterface BClass -isA {} {}
}

Test 1.7 {
   # Illegal args for otclInterface
   otclInterface AClass {}
   otclInterface BClass -isA AClass {}
}

Test 1.8 {
   # Illegal args for otclInterface
   otclInterface AClass {}
   otclInterface AClass {}
}

Test 1.9 {
   # Illegal arsg for otclInterface
   otclInterface AClass {}
   otclImplementation AClass {}
   otclInterface BClass -isA {AClass AClass} {}
}


Test 1.10 {
   # Too many superclasses
   otclInterface AClass {}
   otclImplementation AClass {}
   otclInterface BClass {}
   otclImplementation BClass {}
   otclInterface CClass {}
   otclImplementation CClass {}
   otclInterface DClass {}
   otclImplementation DClass {}
   otclInterface EClass -isA {AClass BClass CClass DClass} {}
}

Test 1.11 {
   # Not enough args for constructor
   otclInterface AClass {
      constructor
   }
}

Test 1.12 {
   # Too many args for constructor
   otclInterface AClass {
      constructor {} extra
   }
}

Test 1.13 {
   # Formal arguemnt error in constructor
   otclInterface AClass {
      constructor {arg {}}
   }
}

Test 1.14 {
   # Formal argument error in constructor
   otclInterface AClass {
      constructor {arg1 {arg2 value extra}}
   }
}

Test 1.15 {
   # Duplicated arguments in constructor
   otclInterface AClass {
      constructor {arg1 arg1}
   }
}

Test 1.16 {
   # Not enough args for method
   otclInterface AClass {
      method
   }
}

Test 1.17 {
   # Too many args for method
   otclInterface AClass {
      method name args extra
   }
}

Test 1.18 {
   # Invalid name for method
   otclInterface AClass {
      method constructor {}
   }
}

Test 1.19 {
   # Invalid name for method
   otclInterface AClass {
      method destructor {}
   }
}

Test 1.20 {
   # Method duplicated in interface
   otclInterface AClass {
      method methodOne {}
      method methodOne {}
   }
}

Test 1.21 {
   # Method duplicated in interface
   otclInterface AClass {
      classMethod methodOne {}
      method methodOne {}
   }
}

Test 1.22 {
   # Not enough args for classMethod
   otclInterface AClass {
      classMethod 
   }
}

Test 1.23 {
   # Too many args for classMethod
   otclInterface AClass {
      classMethod name arg extra
   }
}

Test 1.24 {
   # Invalid name for classMethod
   otclInterface AClasss {
      classMethod constructor {}
   }
}

Test 1.25 {
   # Invalid name for classMethod
   otclInterface AClass {
      classMethod destructor {}
   }
}

Test 1.26 {
   # Duplicate method in interface
   otclInterface AClass {
     classMethod methodOne {}
     classMethod methodOne {}
   }
}

Test 1.27 {
   # Duplicate method in interface
   otclInterface AClass {
      method methodOne {}
      classMethod methodOne {}
   }
}

Test 1.28 {
   # Invalid argument in method
   otclInterface AClass {
      method methodOne {{}}
   }
}

Test 2.1 {
   # Not enough args for otclImplementation
   otclImplementation 
}

Test 2.2 {
   # Too many arguments for otclImplementation
   # Max args only check after name has been checked
   otclInterface name {}
   otclImplementation name body extra
}

Test 2.3 {
   # Illegal class name for otclImplementation
   otclImplementation AClass {}
}

Test 2.4 {
   # Duplicate implementation
   otclInterface AClass {}
   otclImplementation AClass {}
   otclImplementation AClass {}
}

Test 2.5 {
   # Not enough args for constructor implementation
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor
   }
}

Test 2.6 {
   # Too many args for constructor implementation
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor args parentList body extra
   }
}

Test 2.7 {
   # Diff # args from int to imp for constructor
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {arg1} {} {}
   }
}

Test 2.8 {
   # Diff # args from int to imp for constructor
   otclInterface AClass {
      constructor {arg1}
   }
   otclImplementation AClass {
      constructor {} {} {}
   }
}

Test 2.9 {
   # Default value for constructor specified in implementation
   otclInterface AClass {
      constructor {arg1}
   }
   otclImplementation AClass {
      constructor {{arg1 0}} {} {}
   }
}

Test 2.10 {
   # Parent constructor bad syntax
   otclInterface AClass {  
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {{}} {}
   }
}

Test 2.11 {
   # Parent constructor bad syntax
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {{bad}} {}
   }
}

Test 2.12 {
   # Unknown class in parent construcopr
   otclInterface AClass {
     constructor {}
   }
   otclImplementation AClass {
      constructor {} {{BClass arg arg}} {}
   }
}

Test 2.13 {
   # Known but not inherited class in parent constructor
   otclInterface AClass {}
   otclImplementation AClass {}
   otclInterface BClass {
      constructor {}
   }
   otclImplementation BClass {
      constructor {} {{AClass asd asd asd}} {}
   }
}

Test 2.14 {
   # Duplication of parent constructor calls
   otclInterface AClass {}
   otclImplementation AClass {}
   otclInterface BClass -isA AClass {
      constructor {}
   }
   otclImplementation BClass {
      constructor {} {{AClass arg} {AClass arg}} {}
   }
}

Test 2.15 {
   # Private constructor?
   otclInterface AClass {}
   otclImplementation AClass {
      constructor {} {} {}
   }
}

Test 2.16 {
   # Not enough args for method in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      method
   }
}

Test 2.17 {
   # Too many args for method in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      method name args body extra
   }
}

Test 2.18 {
   # Implemented as method but interfaced as classMethod
   otclInterface AClass {
      classMethod methodOne {}
   }
   otclImplementation AClass {
      method methodOne {} {}
   }
}

Test 2.19 {
   # Too few args for classMethod in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      classMethod
   }
}

Test 2.20 {
   # Too many args to classMethod in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      classMethod name args body extra
   }
}

Test 2.21 {
   # Interfaced as instance and implemented as class method
   otclInterface AClass {
      method methodOne {}
   }
   otclImplementation AClass {
      classMethod methodOne {} {}
   }
}

Test 2.22 {
   # Not enough args for attribute
   otclInterface AClass {}
   otclImplementation AClass {
      attribute
   }
}

Test 2.21 {
   # Too many args for attribute
   otclInterface AClass {}
   otclImplementation AClass {
      attribute name initial extra
   }
}

Test 2.22 {
   # Bad name for attribute
   otclInterface AClass {}
   otclImplementation AClass {
      attribute this
   }
}

Test 2.23 {
   # Duplicated instance attributes
   otclInterface AClass {}
   otclImplementation AClass {
      attribute attOne
      attribute attOne
   }
}

Test 2.24 {
   # Duplicated instance with class attribute
   otclInterface AClass {}
   otclImplementation AClass {
      classAttribute attOne 0
      attribute attOne
   }
}

Test 2.25 {
   # Not enough args for classAttribute
   otclInterface AClass {}
   otclImplementation AClass {
      classAttribute
   }
}

Test 2.26 {
   # Too many args for classAttribute
   otclInterface AClass {}
   otclImplementation AClass {
      classAttribute name initial extra
   }
}

Test 2.27 {
   # Bad name for classAttribute
   otclInterface AClass {}
   otclImplementation AClass {
      classAttribute this 0
   }
}

Test 2.28 {
   # Duplicated class attribute
   otclInterface AClass {}
   otclImplementation AClass {
      classAttribute attOne 0
      classAttribute attOne 1
   }
}

Test 2.29 {
   # Class attribute classes with instance attribute
   otclInterface AClass {}
   otclImplementation AClass {
      attribute attOne
      classAttribute attOne 0
   }
}

Test 2.30 {
   # Not enough args for destructor
   otclInterface AClass {}
   otclImplementation AClass {
      destructor
   }
}

Test 2.31 {
   # Too many args for destructor
   otclInterface AClass {}
   otclImplementation AClass {
      destructor {body} extra
   }
}

Test 2.32 {
  # Body duplicated in implementation
  otclInterface AClass {}
  otclImplementation AClass {
     method a {} {}
     method a {} {}
  }
}

Test 2.33 {
   # Body duplicated in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      method a {} {}
      classMethod a {} {}
   }
}

Test 2.34 {
   # Body duplicated in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      classMethod a {} {}
      classMethod a {} {}
   }
}

Test 2.35 {
   # Body duplicated in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      classMethod a {} {}
      method a {} {}
   }
}

Test 2.36 {
  # Class not completed
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
   }
}

Test 2.37 {
   # Class not complete
   otclInterface AClass {
      method A {}
   }
   otclImplementation AClass {
   }
}

Test 2.38 {
   # Class not complete
   otclInterface AClass {
      classMethod A {}
   }
   otclImplementation AClass {
   }
}

Test 3.1 {
   # Class attributes initialisation, read test
   otclInterface AClass {
      classMethod printValues {}
      classMethod modifyValues {}
   }
   otclImplementation AClass {

      classMethod printValues {} {
         puts "att1 = $att1"
         puts "att2 = $att2"
         puts "att3 = $att3"
         puts "att4 = {"
         foreach a $att4 {
            puts $a
         }
         puts "}"
      }

      classMethod modifyValues {} {
         set att1 1
         set att2 Goodbye
         set att3 "Goodbye Tester"
         set att4 {words of list a}
      }

      classAttribute att1 0
      classAttribute att2 Hello
      classAttribute att3 "Hello Tester"
      classAttribute att4 {a list of words}
    # classAttribute att5() {{key1 value1} {key2 value2}}
   }

   AClass printValues

} -dontclean

Test 3.2 {
   # Class attribute write test
   AClass modifyValues
   AClass printValues
} -dontclean

Test 4.1 {
   # Unknown class in class method invocation
   blah doMethod
}

Test 4.2 {
   # Unknown class in class method invocation
   otclInterface AClass {
   }
   AClass doMethod
}

Test 4.3 {
   # Unknown method in class method invocation
   otclInterface AClass {
   }
   otclImplementation AClass {
   }
   AClass unknownMethod
} -dontclean

Test 4.4 {
   # Not enough args for class method invocation
   AClass
}
   

Test 5.1 {
   # Not enough argument for method
   otclInterface AClass {
     classMethod m1 {a}
   }
   otclImplementation AClass {
      classMethod m1 {a} {
         puts "AClass::m1 called with a = $a"
      }
   }
   AClass m1
} -dontclean

Test 5.2 {
   # Too many arguments for method
   AClass m1 a b
} -dontclean

Test 5.3 {
   # Correct number of arguments
   AClass m1 Hello
   AClass m1 5
   AClass m1 [expr 5 * 66]
}

Test 5.4 {
   # Test default parameters
   otclInterface AClass {
      classMethod m1 {a {b 15}}
   }
   otclImplementation AClass {
      classMethod m1 {a b} {
         puts "AClass::m1 called with a = $a, b = $b"
      }
   }
   AClass m1 10
} -dontclean

Test 5.5 {
   # Test default override
   AClass m1 10 12
}

Test 5.6 {
   # Test trailing 'args' empty
   otclInterface AClass {
      classMethod m1 {a args}
   }
   otclImplementation AClass {
      classMethod m1 {a args} {
         puts "AClass::m1 called with a = $a, args = \["
         foreach v $args {
            puts $v
         }
         puts "\]"
      }
   }
   AClass m1 5
} -dontclean

Test 5.7 {
   # Test trailing 'args' with 1 value
   AClass m1 5 6
} -dontclean

Test 5.8 {
   # Test trailing 'args' with a list of values
   AClass m1 5 6 7 8 {Hello People} My Name Is Fred
}

Test 6.1 {
   # Test initialisation and reading of instance attributes
   otclInterface AClass {
      constructor {}
      method printValues {}
      method modifyValues {}
   }
   otclImplementation AClass {

      constructor {} {} {
         # Would like to do $this printValues but see later bug with $this
         # in constructor :-( Will fix, honest :-)
         puts "att0 = $att0"
         puts "att1 = $att1"
         puts "att2 = $att2"
         puts "att3 = $att3"
         puts "att4 = {"
         foreach a $att4 {
            puts $a
         }
         puts "}"
      }

      method printValues {} {
         puts "att0 = $att0"
         puts "att1 = $att1"
         puts "att2 = $att2"
         puts "att3 = $att3"
         puts "att4 = {"
         foreach a $att4 {
            puts $a
         }
         puts "}"
      }

      method modifyValues {} {
         set att0 0
         set att1 1
         set att2 Goodbye
         set att3 "Goodbye Tester"
         set att4 {words of list a}
      }

      attribute att0
      attribute att1 0
      attribute att2 Hello
      attribute att3 "Hello Tester"
      attribute att4 {a list of words}
    # attribute att5() {{key1 value1} {key2 value2}}
   }

   set a [otclNew AClass]
   otclDelete $a

} -dontclean

Test 6.2 {
   # Test writing of instance attributes
   set a [otclNew AClass]
   $a modifyValues
   $a printValues
   otclDelete $a
} -dontclean

Test 6.3 {
   # Test independence of instance attributes
   set a [otclNew AClass]
   $a modifyValues
   set b [otclNew AClass]
   puts "About to print values of a and then b"
   $a printValues
   $b printValues
   otclDelete $a
   otclDelete $b
}

Test 7.1 {
   # Test constructor execution
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {} {
         puts "AClass::constructor called"
      }
   }
   otclDelete [otclNew AClass]
}

Test 7.2 {
   # Test constructor ordering for multiple inheritance
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {} {
         puts "AClass::constructor called"
      }
   }
   otclInterface BClass {
      constructor {}
   }
   otclImplementation BClass {
      constructor {} {} {
         puts "BClass::constructor called"
      }
   }
   otclInterface CClass -isA {AClass BClass} {
      constructor {}
   }
   otclImplementation CClass {
      constructor {} {} {
         puts "CClass::constructor called"
      }
   }
   otclDelete [otclNew CClass]
}

Test 7.3 {
   # Test passing arguments to parent constructor
   otclInterface AClass {
      constructor {a {b 0}}
   }
   otclImplementation AClass {
      constructor {a b} {} {
        puts "AClass::constructor called with a = $a, b = $b"
      }
   }
   otclInterface BClass {
      constructor {{a 5}} 
   }
   otclImplementation BClass {
      constructor {a} {} {
         puts "BClass::constructor called with a = $a"
      }
   }
   otclInterface CClass -isA {AClass BClass} {
      constructor {a b}
   }
   otclImplementation CClass {
      constructor {a b} {{AClass [expr $a * $b]}} {
         puts "CClass::constructor called with a = $a, b = $b"
      }
   }
   otclDelete [otclNew CClass 10 20]
}

Test 8.1 {
   # Test destructor calling
   otclInterface AClass {}
   otclImplementation AClass {
      destructor {
         puts "AClass::destructor called"
      }
   }
   set a [otclNew AClass]
   puts "About to destroy AClass instance"
   otclDelete $a
}

Test 8.2 {
   # Test destructor ordering in multiple inheritance
   otclInterface AClass {}
   otclImplementation AClass {
      destructor {
         puts "AClass::destructor called"
      }
   }
   otclInterface BClass {}
   otclImplementation BClass {
      destructor {
         puts "BClass::destructor called"
      }
   }
   otclInterface CClass -isA {AClass BClass} {}
   otclImplementation CClass {
      destructor {
         puts "CClass::destructor called"
      }
   }
   set a [otclNew CClass]
   puts "About to destroy CClass instance"
   otclDelete $a
}

Test 9.1 {
   # Test instance method invocation
   otclInterface AClass {
      method m1 {}
   }
   otclImplementation AClass {
      method m1 {} {
         puts "AClass::m1 called"
      }
   }
   set a [otclNew AClass]
   $a m1
   otclDelete $a
} -dontclean

Test 9.3 {
   # Test instance method not known
   set a [otclNew AClass]
   $a m2
   otclDelete $a
}

Test 10.1 {
   # Test private instance method access
   otclInterface AClass {
      method m1 {}
   }
   otclImplementation AClass {
      method m1 {} {
         $this m2
      }
      method m2 {} {
         puts "AClass::m2 called"
      }
   }
   set a [otclNew AClass]
   $a m2
   otclDelete $a
} -dontclean

Test 10.2 {
   # Test private instance access
   set a [otclNew AClass]
   $a m1
   otclDelete $a
}

Test 11.1 {
   # Test private class method access
   otclInterface AClass {
      classMethod m1 {}
   }
   otclImplementation AClass {
      classMethod m1 {} {
         AClass m2
      }
      classMethod m2 {} { 
         puts "AClass::m2 called"
      }
   }
   AClass m2
} -dontclean

Test 11.2 {
   # Test private class method access
   AClass m1
}

Test 12.1 {
   # Test invocation of inherit method from outside
   otclInterface AClass {
      method m1 {}
   }
   otclImplementation AClass {
     method m1 {} {
        puts "AClass::m1 called"
     }
   }
   otclInterface BClass -isA AClass {
      method m2 {}
   }
   otclImplementation BClass {
      method m2 {} {
         $this m1
      }
   }
   set a [otclNew BClass]
   $a m1
   otclDelete $a
} -dontclean

Test 12.2 {
   # Test invocation of inherited method from insidde
   set a [otclNew BClass]
   $a m2
   otclDelete $a
} -dontclean

Test 12.3 {
   # Tes invocation of method inherited in both parent from outside
   otclInterface CClass {
      method m1 {}
   }
   otclImplementation CClass {
      method m1 {} {
         puts "CClass::m1 called"
      }
   }
   otclInterface DClass -isA {AClass CClass} {
      method m3 {}
      method m4 {}
   }
   otclImplementation DClass {
      method m3 {} {
         $this m1
      }
      method m4 {} {
         # Force it to take the CClass version
         $this -CClass m1
      }
   }
   set a [otclNew DClass]
   $a m1
   otclDelete $a
} -dontclean

Test 12.4 {
   # Test invocation of method inherited in both parents from inside
   set a [otclNew DClass]
   $a m3
   $a m4
   otclDelete $a
}

Test 13.1 {
   # Test dynamic binding of method with single inheritance
   otclInterface AClass {
      method m1 {}
   }
   otclImplementation AClass {
      method m1 {} {
         puts "AClass::m1 called"
      }
   }
   otclInterface BClass -isA AClass {
      method m1 {}
   }
   otclImplementation BClass {
      method m1 {} {
         puts "BClass::m1 called"
      }
   }
   set a [otclNew BClass]
   $a m1
   otclDelete $a
} -dontclean

Test 13.2 {
   # Test dynamic binding of method with multiple inheritance
   otclInterface CClass {
     method m1 {}
   }
   otclImplementation CClass {
      method m1 {} {
         puts "CClass::m1 called"
      }
   }
   otclInterface DClass -isA {BClass CClass} {
     method m1 {}
     method m2 {}
   }
   otclImplementation DClass {
      method m1 {} {
         puts "DClass::m1 called"
      }
      method m2 {} {
         $this -CClass m1
      }
   }
   
   set a [otclNew DClass]
   $a m1
   otclDelete $a
} -dontclean

Test 13.3 {
   # Test dynamic binding override
   set a [otclNew DClass]
   $a m2
   otclDelete $a
} -dontclean

Test 13.4 {
   # Test dynamic bind override for a not base class
   otclInterface EClass -isA DClass {
      method m1 {}
   }
   otclImplementation EClass {
      method m1 {} {
         $this -FClass m1
      }
   }

   set a [otclNew EClass]
   $a m1
   otclDelete $a
}

Test 14.1 {
   # Test Unknwon Instance Method
   otclInterface AClass {}
   otclImplementation AClass {}
   set a [otclNew AClass]
   $a m1
   otclDelete $a
}

Test 15.1 {
   # Not enough args for otclNew
   otclNew
}

Test 15.2 {
   # Unknown class for otclNew
   otclNew AClass
}

Test 16.1 {
   # Not enough arguments for otclDelete
   otclDelete
}

Test 16.2 {
   # Bad object for otclDelete
   otclDelete 123bE
}

Test 17.1 {
   # Syntax error in constructor body no inheritance
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {} {
         some rubbish
      }
   }

   set a [otclNew AClass]
   otclDelete $a
} -dontclean

Test 17.2 {
   # Syntax error in constructor body with inheritance
   otclInterface BClass -isA AClass {
   }
   otclImplementation BClass {
   }
   
   set a [otclNew BClass]
   otclDelete $a
}

Test 17.3 {
   # Syntax error in class method
   otclInterface AClass {
      classMethod m1 {}
   }
   otclImplementation AClass {
      classMethod m1 {} {
         some rubbish
      }
   }
   AClass m1
}

Test 17.4 {
   # Syntax error in instance method
   otclInterface AClass {
      method m1 {}
   }
   otclImplementation AClass {
      method m1 {} {
         some rubbish
      }
   }
   set a [otclNew AClass]
   $a m1
   otclDelete $a
}

Test 17.5 {
   # Syntax error in destructor, no inheritance
   otclInterface AClass {
   }
   otclImplementation AClass {
      destructor {
         some rubbish
      }
   }
   set a [otclNew AClass]
   otclDelete $a
} -dontclean

Test 17.6 {
   # Syntax error in destructor, inheritance
   otclInterface BClass -isA AClass {
   }
   otclImplementation BClass {
   }
   set a [otclNew AClass]
   otclDelete $a
} -dontclean

Test 17.7 {
   # Syntax error in parent constructor
   otclInterface CClass -isA BClass {
      constructor {a}
   }
   otclImplementation CClass {
      constructor {a} {{BClass [expr $a + $b]}} {
      }
   }
   set a [otclNew CClass 55]
}

Test 18.1 {
   # constructor duplicate in interface
   otclInterface AClass {
      constructor {}
      constructor {}
   }
}

Test 18.2 {
   # constructor duplicate in implementation
   otclInterface AClass {
      constructor {}
   }
   otclImplementation AClass {
      constructor {} {} {}
      constructor {} {} {}
   }
}

Test 18.3 {
   # destructor duplicated in implementation
   otclInterface AClass {}
   otclImplementation AClass {
      destructor {}
      destructor {}
   }
}

Test 19.1 {
   # Constructor arg same as inst attribute
   otclInterface AClass {
      constructor {a}
   }
   otclImplementation AClass {
      constructor {a} {} {}
      attribute a
   }
}

Test 19.2 {
   # Constructor arg same as class attribute
   otclInterface AClass {
      constructor {a}
   }
   otclImplementation AClass {
      constructor {a} {} {}
      classAttribute a 0
   }
}

Test 19.3 {
   # Instance method arg same as inst attribute
   otclInterface AClass {
      method a {b}
   }
   otclImplementation AClass {
      method a {b} {}
      attribute b
   }
}

Test 19.4 {
   # Instance method arg same as class attribute
   otclInterface AClass {
      method a {b}
   }
   otclImplementation AClass {
      method a {b} {}
      classAttribute b 0
   }
}

Test 19.5 {
   # Class method arg saem as instance attribute
   otclInterface AClass {
      classMethod a {b}
   }
   otclImplementation AClass {
      classMethod a {b} {}
      attribute b
   }
}

Test 19.6 {
   # Class method arg same as class attribute
   otclInterface AClass {
      classMethod a {b}
   }
   otclImplementation AClass {
      classMethod a {b} {}
      classAttribute b 0
   }
}

Test 20.1 {
   # Test unknown method
   otclInterface AClass {
      method unknown {args}
   }
   otclImplementation AClass {
      method unknown {args} {
         puts "You have called [lindex $args 0] which is not a method of AClass or"
         puts "any of its superclasses"
      }
   }

   set o [otclNew AClass]
   $o notARealMethod 55 66 77
   otclDelete $o
} -dontclean

Test 20.2 {
   # Test unknown method is inherited
   otclInterface BClass -isA AClass {
   }
   otclImplementation BClass {}

   set o [otclNew BClass]
   $o notARealMethod 77 66 55
   otclDelete $o
}

Test 21.1 {
   # Test manipulation of a C++ class, object
   puts "There are [SimpleCppClass getNoOfObjects] instance of SimpleCppClass"
   set a [otclNew SimpleCppClass "Hello" 55]
   puts "There are [SimpleCppClass getNoOfObjects] instance of SimpleCppClass"
   puts "getValue on a returns [$a getValue]"
   puts "getStr on a returns [$a getStr]"
   $a setValue 12
   $a setStr "Goodbye"
   puts "getValue on a returns [$a getValue]"
   puts "getStr on a returns [$a getStr]"
   set b [otclNew SimpleCppClass "Bob" 99]
   otclDelete $a
   otclDelete $b
}

Test 21.2 {
   # Test inheritance from C++ class
   otclInterface AClass -isA SimpleCppClass {
      constructor {str val}
   }
   otclImplementation AClass {
      constructor {str val} {{SimpleCppClass $str $val}} {
         puts "AClass constructed"
      }
      destructor {
         puts "AClass destructed"
      }
   }
   puts "There are [SimpleCppClass getNoOfObjects] instance of SimpleCppClass"
   set a [otclNew AClass "Hello" 55]
   puts "There are [SimpleCppClass getNoOfObjects] instance of SimpleCppClass"
   puts "getValue on a returns [$a getValue]"
   puts "getStr on a returns [$a getStr]"
   $a setValue 12
   $a setStr "Goodbye"
   puts "getValue on a returns [$a getValue]"
   puts "getStr on a returns [$a getStr]"
   otclDelete $a
}

Test 21.3 {
   # Test dynamic binding of methods from C++.
   otclInterface AClass -isA TestCppClass {
      constructor {{val 0}}
      method methodTwo {}
   }
   otclImplementation AClass {
      constructor {v} {} {
         set val $v
      }
      method methodTwo {} {
         puts "AClass::methodTwo called, val = $val"
      }
      attribute val
   }
   set a [otclNew AClass]
   $a methodOne
   otclDelete $a
} -dontclean

Test 21.4 {
   # Test C++ manipulation of Object Tcl object
   set a [otclNew AClass]
   set b [otclNew AClass 99]
   $a setOtherObject $b
   $a doMethodTwoOnOtherObject
   otclDelete $a
   otclDelete $b
}

Test 22.1 {
   # Test this available from constructor
   otclInterface AClass {
      constructor {}
      method methodOne {}
   }
   otclImplementation AClass {
      constructor {} {} {
         $this methodOne
      }
      method methodOne {} {
         puts "AClass::methodOne called"
      }
   }
   # otclNew AClass
   puts "Test 22.1 fails with a core dump"
}
