home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / ObjectTcl-1.1 / tests / tscript
Encoding:
Text File  |  1995-06-30  |  39.4 KB  |  1,643 lines

  1. #!../otcltest
  2.  
  3. # Test Script for Object Tcl
  4.  
  5. #
  6. # Support routines for Test procedure
  7. #
  8. proc ResultCode code {
  9.     switch $code {
  10.         0 {return TCL_OK}
  11.         1 {return TCL_ERROR}
  12.         2 {return TCL_RETURN}
  13.         3 {return TCL_BREAK}
  14.         4 {return TCL_CONTINUE}
  15.     }
  16.     return "Invalid result code $code"
  17. }
  18.  
  19. proc OutputTestError {id command expectCode expectResult resultCode result} {
  20.     puts stderr "======== Test $id failed ========"
  21.     puts stderr $command
  22.     puts stderr "==== Result was: [ResultCode $resultCode]:"
  23.     puts stderr $result
  24.     puts stderr "==== Expected : [ResultCode $expectCode]:"
  25.     puts stderr $expectResult
  26.     puts stderr "===="
  27. }
  28.  
  29. # Test Procedure used by all tests
  30. # id is the test identifier
  31. # code is the test scenario
  32. # optional -dontclean argument will stop the test classes being cleaned out
  33.  
  34. proc Test {id command expectCode expectResult args} {
  35.     set resultCode [catch {uplevel $command} result]
  36.  
  37.     if {($resultCode != $expectCode) ||
  38.         ([string compare $result $expectResult] != 0)} {
  39.         OutputTestError $id $command $expectCode $expectResult $resultCode \
  40.                 $result
  41.     }
  42.  
  43.    if {[llength $args] == 0 || [lindex $args 0] != "-dontclean"} {
  44.       # An un-documented command to clear out the Otcl classes,
  45.       # only used here to making thinking of class names easier in testing
  46.       # not recommended
  47.       otcl clear
  48.    }
  49. }
  50.  
  51. global results
  52.  
  53. Test 1.1 {
  54.    # Not enough args for otclInterface command
  55.    otclInterface AClass
  56. } 1 {wrong # args: should be "otclInterface className ?-isA classList? body"}
  57.  
  58. Test 1.2 {
  59.    # Too many args for otclInterface command
  60.    otclInterface AClass -isA AnotherClass {body} tooMany
  61. } 1 {wrong # args: should be "otclInterface className ?-isA classList? body"}
  62.  
  63. Test 1.3 {
  64.    # Illegal args for otclInterface
  65.    otclInterface AClass blah {body}
  66. } 1 {wrong # args: should be "otclInterface className ?-isA classList? body"}
  67.  
  68. Test 1.4 {
  69.    # Illegal args for otclInterface
  70.    otclInterface AClass -isA {}
  71. } 1 {wrong # args: should be "otclInterface className ?-isA classList? body"}
  72.  
  73. Test 1.5 {
  74.    # Illegal args for otclInterface as AClass doesn't exist
  75.    otclInterface BClass -isA AClass {}
  76. } 1 {Class "BClass" interface specified an unknown class, "AClass", as one of its superclasses.}
  77.  
  78. Test 1.6 {
  79.    # Illegal args for otclInterface
  80.    otclInterface BClass -isA {} {}
  81. } 1 {Class "BClass" does not specify any classes in its -isA class list. Must specify at least one class with the -isA option.}
  82.  
  83. Test 1.7 {
  84.    # Illegal args for otclInterface
  85.    otclInterface AClass {}
  86.    otclInterface BClass -isA AClass {}
  87. } 1 {Class "BClass" interface specified an unknown class, "AClass", as one of its superclasses.}
  88.  
  89. Test 1.8 {
  90.    # Illegal args for otclInterface
  91.    otclInterface AClass {}
  92.    otclInterface AClass {}
  93. } 1 {Class "AClass" already declared.}
  94.  
  95. Test 1.9 {
  96.    # Illegal arsg for otclInterface
  97.    otclInterface AClass {}
  98.    otclImplementation AClass {}
  99.    otclInterface BClass -isA {AClass AClass} {}
  100. } 1 {Class "AClass" is specified as a superclass of class "BClass" twice.}
  101.  
  102.  
  103. Test 1.10 {
  104.    # Too many superclasses
  105.    otclInterface AClass {}
  106.    otclImplementation AClass {}
  107.    otclInterface BClass {}
  108.    otclImplementation BClass {}
  109.    otclInterface CClass {}
  110.    otclImplementation CClass {}
  111.    otclInterface DClass {}
  112.    otclImplementation DClass {}
  113.    otclInterface EClass -isA {AClass BClass CClass DClass} {}
  114. } 1 {Too many superclasses specified in interface for class "EClass". Maximum is 3.}
  115.  
  116. Test 1.11 {
  117.    # Not enough args for constructor
  118.    otclInterface AClass {
  119.       constructor
  120.    }
  121. } 1 {wrong # args: should be "constructor args"}
  122.  
  123. Test 1.12 {
  124.    # Too many args for constructor
  125.    otclInterface AClass {
  126.       constructor {} extra
  127.    }
  128. } 1 {wrong # args: should be "constructor args"}
  129.  
  130. Test 1.13 {
  131.    # Formal arguemnt error in constructor
  132.    otclInterface AClass {
  133.       constructor {arg {}}
  134.    }
  135. } 1 {Syntax error in formal argument 2 for method "AClass::constructor". Formal argument specification is "".}
  136.  
  137. Test 1.14 {
  138.    # Formal argument error in constructor
  139.    otclInterface AClass {
  140.       constructor {arg1 {arg2 value extra}}
  141.    }
  142. } 1 {Syntax error in formal argument 2 for method "AClass::constructor". Formal argument specification is "arg2 value extra".}
  143.  
  144. Test 1.15 {
  145.    # Duplicated arguments in constructor
  146.    otclInterface AClass {
  147.       constructor {arg1 arg1}
  148.    }
  149. } 1 {Duplicated formal argument "arg1" in method "AClass::constructor".}
  150.  
  151. Test 1.16 {
  152.    # Not enough args for method
  153.    otclInterface AClass {
  154.       method
  155.    }
  156. } 1 {wrong # args: should be "method name args"}
  157.  
  158. Test 1.17 {
  159.    # Too many args for method
  160.    otclInterface AClass {
  161.       method name args extra
  162.    }
  163. } 1 {wrong # args: should be "method name args"}
  164.  
  165. Test 1.18 {
  166.    # Invalid name for method
  167.    otclInterface AClass {
  168.       method constructor {}
  169.    }
  170. } 1 {Cannot name an instance method "constructor".}
  171.  
  172. Test 1.19 {
  173.    # Invalid name for method
  174.    otclInterface AClass {
  175.       method destructor {}
  176.    }
  177. } 1 {Cannot name an instance method "destructor".}
  178.  
  179. Test 1.20 {
  180.    # Method duplicated in interface
  181.    otclInterface AClass {
  182.       method methodOne {}
  183.       method methodOne {}
  184.    }
  185. } 1 {Method "methodOne" duplicated in interface for class "AClass".}
  186.  
  187. Test 1.21 {
  188.    # Method duplicated in interface
  189.    otclInterface AClass {
  190.       classMethod methodOne {}
  191.       method methodOne {}
  192.    }
  193. } 1 {Method "methodOne" duplicated in interface for class "AClass".}
  194.  
  195. Test 1.22 {
  196.    # Not enough args for classMethod
  197.    otclInterface AClass {
  198.       classMethod 
  199.    }
  200. } 1 {wrong # args: should be "classMethod name args"}
  201.  
  202. Test 1.23 {
  203.    # Too many args for classMethod
  204.    otclInterface AClass {
  205.       classMethod name arg extra
  206.    }
  207. } 1 {wrong # args: should be "classMethod name args"}
  208.  
  209. Test 1.24 {
  210.    # Invalid name for classMethod
  211.    otclInterface AClasss {
  212.       classMethod constructor {}
  213.    }
  214. } 1 {Cannot name a class method "constructor".}
  215.  
  216. Test 1.25 {
  217.    # Invalid name for classMethod
  218.    otclInterface AClass {
  219.       classMethod destructor {}
  220.    }
  221. } 1 {Cannot name a class method "destructor".}
  222.  
  223. Test 1.26 {
  224.    # Duplicate method in interface
  225.    otclInterface AClass {
  226.      classMethod methodOne {}
  227.      classMethod methodOne {}
  228.    }
  229. } 1 {Method "methodOne" duplicated in interface for class "AClass".}
  230.  
  231. Test 1.27 {
  232.    # Duplicate method in interface
  233.    otclInterface AClass {
  234.       method methodOne {}
  235.       classMethod methodOne {}
  236.    }
  237. } 1 {Method "methodOne" duplicated in interface for class "AClass".}
  238.  
  239. Test 1.28 {
  240.    # Invalid argument in method
  241.    otclInterface AClass {
  242.       method methodOne {{}}
  243.    }
  244. } 1 {Syntax error in formal argument 1 for method "AClass::methodOne". Formal argument specification is "".}
  245.  
  246. Test 2.1 {
  247.    # Not enough args for otclImplementation
  248.    otclImplementation 
  249. } 1 {wrong # args: should be "otclImplementation className body"}
  250.  
  251. Test 2.2 {
  252.    # Too many arguments for otclImplementation
  253.    # Max args only check after name has been checked
  254.    otclInterface name {}
  255.    otclImplementation name body extra
  256. } 1 {wrong # args: should be "otclImplementation className body"}
  257.  
  258. Test 2.3 {
  259.    # Illegal class name for otclImplementation
  260.    otclImplementation AClass {}
  261. } 1 {Class "AClass" interface has not been declared.}
  262.  
  263. Test 2.4 {
  264.    # Duplicate implementation
  265.    otclInterface AClass {}
  266.    otclImplementation AClass {}
  267.    otclImplementation AClass {}
  268. } 1 {Class "AClass" has already been completely specified.}
  269.  
  270. Test 2.5 {
  271.    # Not enough args for constructor implementation
  272.    otclInterface AClass {
  273.       constructor {}
  274.    }
  275.    otclImplementation AClass {
  276.       constructor
  277.    }
  278. } 1 {wrong # args: should be "constructor args parentConstructors body"}
  279.  
  280. Test 2.6 {
  281.    # Too many args for constructor implementation
  282.    otclInterface AClass {
  283.       constructor {}
  284.    }
  285.    otclImplementation AClass {
  286.       constructor args parentList body extra
  287.    }
  288. } 1 {wrong # args: should be "constructor args parentConstructors body"}
  289.  
  290. Test 2.7 {
  291.    # Diff # args from int to imp for constructor
  292.    otclInterface AClass {
  293.       constructor {}
  294.    }
  295.    otclImplementation AClass {
  296.       constructor {arg1} {} {}
  297.    }
  298. } 1 {Method "AClass::constructor" has different number of arguments specified in its interface and implementation.}
  299.  
  300. Test 2.8 {
  301.    # Diff # args from int to imp for constructor
  302.    otclInterface AClass {
  303.       constructor {arg1}
  304.    }
  305.    otclImplementation AClass {
  306.       constructor {} {} {}
  307.    }
  308. } 1 {Method "AClass::constructor" has different number of arguments specified in its interface and implementation.}
  309.  
  310. Test 2.9 {
  311.    # Default value for constructor specified in implementation
  312.    otclInterface AClass {
  313.       constructor {arg1}
  314.    }
  315.    otclImplementation AClass {
  316.       constructor {{arg1 0}} {} {}
  317.    }
  318. } 1 {Method "AClass::constructor" has default values specified for formal arguments in its implementation. Can only specify defaults in interface if method is public.}
  319.  
  320. Test 2.10 {
  321.    # Parent constructor bad syntax
  322.    otclInterface AClass {  
  323.       constructor {}
  324.    }
  325.    otclImplementation AClass {
  326.       constructor {} {{}} {}
  327.    }
  328. } 1 {Syntax error in parent constructor "" in constructor of class "AClass".}
  329.  
  330. Test 2.11 {
  331.    # Parent constructor bad syntax
  332.    otclInterface AClass {
  333.       constructor {}
  334.    }
  335.    otclImplementation AClass {
  336.       constructor {} {{bad}} {}
  337.    }
  338. } 1 {Syntax error in parent constructor "bad" in constructor of class "AClass".}
  339.  
  340. Test 2.12 {
  341.    # Unknown class in parent construcopr
  342.    otclInterface AClass {
  343.      constructor {}
  344.    }
  345.    otclImplementation AClass {
  346.       constructor {} {{BClass arg arg}} {}
  347.    }
  348. } 1 {Constructor of class "AClass" has specified an unknown class, "BClass", in its parent construction specifier.}
  349.  
  350. Test 2.13 {
  351.    # Known but not inherited class in parent constructor
  352.    otclInterface AClass {}
  353.    otclImplementation AClass {}
  354.    otclInterface BClass {
  355.       constructor {}
  356.    }
  357.    otclImplementation BClass {
  358.       constructor {} {{AClass asd asd asd}} {}
  359.    }
  360. } 1 {Constructor of class "BClass" has specified an unknown class, "AClass", in its parent construction specifier.}
  361.  
  362. Test 2.14 {
  363.    # Duplication of parent constructor calls
  364.    otclInterface AClass {}
  365.    otclImplementation AClass {}
  366.    otclInterface BClass -isA AClass {
  367.       constructor {}
  368.    }
  369.    otclImplementation BClass {
  370.       constructor {} {{AClass arg} {AClass arg}} {}
  371.    }
  372. } 1 {Duplication of parent construction parameters for class "AClass" from constructor of class "BClass".}
  373.  
  374. Test 2.15 {
  375.    # Private constructor?
  376.    otclInterface AClass {}
  377.    otclImplementation AClass {
  378.       constructor {} {} {}
  379.    }
  380. } 1 {Constructor for class "AClass" must be specified in interface.}
  381.  
  382. Test 2.16 {
  383.    # Not enough args for method in implementation
  384.    otclInterface AClass {}
  385.    otclImplementation AClass {
  386.       method
  387.    }
  388. } 1 {wrong # args: should be "method name args body"}
  389.  
  390. Test 2.17 {
  391.    # Too many args for method in implementation
  392.    otclInterface AClass {}
  393.    otclImplementation AClass {
  394.       method name args body extra
  395.    }
  396. } 1 {wrong # args: should be "method name args body"}
  397.  
  398. Test 2.18 {
  399.    # Implemented as method but interfaced as classMethod
  400.    otclInterface AClass {
  401.       classMethod methodOne {}
  402.    }
  403.    otclImplementation AClass {
  404.       method methodOne {} {}
  405.    }
  406. } 1 {Method "methodOne" specified as a class method in the interfaced but implemented as an instance method.}
  407.  
  408. Test 2.19 {
  409.    # Too few args for classMethod in implementation
  410.    otclInterface AClass {}
  411.    otclImplementation AClass {
  412.       classMethod
  413.    }
  414. } 1 {wrong # args: should be "classMethod name args body"}
  415.  
  416. Test 2.20 {
  417.    # Too many args to classMethod in implementation
  418.    otclInterface AClass {}
  419.    otclImplementation AClass {
  420.       classMethod name args body extra
  421.    }
  422. } 1 {wrong # args: should be "classMethod name args body"}
  423.  
  424. Test 2.21 {
  425.    # Interfaced as instance and implemented as class method
  426.    otclInterface AClass {
  427.       method methodOne {}
  428.    }
  429.    otclImplementation AClass {
  430.       classMethod methodOne {} {}
  431.    }
  432. } 1 {Method "methodOne" specified as an instance method in the interface but implemented as a class method.}
  433.  
  434. Test 2.22 {
  435.    # Not enough args for attribute
  436.    otclInterface AClass {}
  437.    otclImplementation AClass {
  438.       attribute
  439.    }
  440. } 1 {wrong # args: should be "attribute name ?initial?"}
  441.  
  442. Test 2.22.1 {
  443.    # Too many args for attribute
  444.    otclInterface AClass {}
  445.    otclImplementation AClass {
  446.       attribute name initial extra
  447.    }
  448. } 1 {wrong # args: should be "attribute name ?initial?"}
  449.  
  450. Test 2.22.2 {
  451.    # Bad name for attribute
  452.    otclInterface AClass {}
  453.    otclImplementation AClass {
  454.       attribute this
  455.    }
  456. } 1 {Attribute's cannot be called "this".}
  457.  
  458. Test 2.23 {
  459.    # Duplicated instance attributes
  460.    otclInterface AClass {}
  461.    otclImplementation AClass {
  462.       attribute attOne
  463.       attribute attOne
  464.    }
  465. } 1 {Instance attribute "attOne" in class "AClass" clashes with another instance attribute of the same name.}
  466.  
  467. Test 2.24 {
  468.    # Duplicated instance with class attribute
  469.    otclInterface AClass {}
  470.    otclImplementation AClass {
  471.       classAttribute attOne 0
  472.       attribute attOne
  473.    }
  474. } 1 {Instance attribute "attOne" in class "AClass" clashes with a class attribute of the same name.}
  475.  
  476. Test 2.25 {
  477.    # Not enough args for classAttribute
  478.    otclInterface AClass {}
  479.    otclImplementation AClass {
  480.       classAttribute
  481.    }
  482. } 1 {wrong # args: should be "classAttribute name initial"}
  483.  
  484. Test 2.26 {
  485.    # Too many args for classAttribute
  486.    otclInterface AClass {}
  487.    otclImplementation AClass {
  488.       classAttribute name initial extra
  489.    }
  490. } 1 {wrong # args: should be "classAttribute name initial"}
  491.  
  492. Test 2.27 {
  493.    # Bad name for classAttribute
  494.    otclInterface AClass {}
  495.    otclImplementation AClass {
  496.       classAttribute this 0
  497.    }
  498. } 1 {Attribute's cannot be called "this".}
  499.  
  500. Test 2.28 {
  501.    # Duplicated class attribute
  502.    otclInterface AClass {}
  503.    otclImplementation AClass {
  504.       classAttribute attOne 0
  505.       classAttribute attOne 1
  506.    }
  507. } 1 {Class attribute "attOne" in class "AClass" clashes with another class attribute of the same name.}
  508.  
  509. Test 2.29 {
  510.    # Class attribute classes with instance attribute
  511.    otclInterface AClass {}
  512.    otclImplementation AClass {
  513.       attribute attOne
  514.       classAttribute attOne 0
  515.    }
  516. } 1 {Class attribute "attOne" in class "AClass" clashes with an instance attribute of the same name.}
  517.  
  518. Test 2.30 {
  519.    # Not enough args for destructor
  520.    otclInterface AClass {}
  521.    otclImplementation AClass {
  522.       destructor
  523.    }
  524. } 1 {wrong # args: should be "destructor body"}
  525.  
  526. Test 2.31 {
  527.    # Too many args for destructor
  528.    otclInterface AClass {}
  529.    otclImplementation AClass {
  530.       destructor {body} extra
  531.    }
  532. } 1 {wrong # args: should be "destructor body"}
  533.  
  534. Test 2.32 {
  535.   # Body duplicated in implementation
  536.   otclInterface AClass {}
  537.   otclImplementation AClass {
  538.      method a {} {}
  539.      method a {} {}
  540.   }
  541. } 1 {Method "AClass::a" implementated twice.}
  542.  
  543. Test 2.33 {
  544.    # Body duplicated in implementation
  545.    otclInterface AClass {}
  546.    otclImplementation AClass {
  547.       method a {} {}
  548.       classMethod a {} {}
  549.    }
  550. } 1 {Method "a" implementated twice.}
  551.  
  552. Test 2.34 {
  553.    # Body duplicated in implementation
  554.    otclInterface AClass {}
  555.    otclImplementation AClass {
  556.       classMethod a {} {}
  557.       classMethod a {} {}
  558.    }
  559. } 1 {Method "AClass::a" implementated twice.}
  560.  
  561. Test 2.35 {
  562.    # Body duplicated in implementation
  563.    otclInterface AClass {}
  564.    otclImplementation AClass {
  565.       classMethod a {} {}
  566.       method a {} {}
  567.    }
  568. } 1 {Method "a" implementated twice.}
  569.  
  570. Test 2.36 {
  571.   # Class not completed
  572.    otclInterface AClass {
  573.       constructor {}
  574.    }
  575.    otclImplementation AClass {
  576.    }
  577. } 1 {Instance method "constructor" of class "AClass" has not been completed. An interfaced method must be implemented.}
  578.  
  579. Test 2.37 {
  580.    # Class not complete
  581.    otclInterface AClass {
  582.       method A {}
  583.    }
  584.    otclImplementation AClass {
  585.    }
  586. } 1 {Instance method "A" of class "AClass" has not been completed. An interfaced method must be implemented.}
  587.  
  588. Test 2.38 {
  589.    # Class not complete
  590.    otclInterface AClass {
  591.       classMethod A {}
  592.    }
  593.    otclImplementation AClass {
  594.    }
  595. } 1 {Class method "A" of class "AClass" has not been completed. An interfaced method must be implemented.}
  596.  
  597. Test 3.1 {
  598.    # Class attributes initialisation, read test
  599.  
  600.    otclInterface AClass {
  601.       classMethod getValues {}
  602.       classMethod modifyValues {}
  603.    }
  604.    otclImplementation AClass {
  605.  
  606.       classMethod getValues {} {
  607.          list $att1 $att2 $att3 $att4 $att5(key1) $att5(key2)
  608.       }
  609.  
  610.       classMethod modifyValues {} {
  611.          set att1 1
  612.          set att2 Goodbye
  613.          set att3 "Goodbye Tester"
  614.          set att4 {words of list a}
  615.          set att5(key1) 5
  616.          set att5(key2) 6
  617.       }
  618.  
  619.       classAttribute att1 0
  620.       classAttribute att2 Hello
  621.       classAttribute att3 "Hello Tester"
  622.       classAttribute att4 {a list of words}
  623.       classAttribute att5() {{key1 value1} {key2 value2}}
  624.    }
  625.  
  626.    AClass getValues
  627. } 0 {0 Hello {Hello Tester} {a list of words} value1 value2} -dontclean
  628.  
  629. Test 3.2 {
  630.    # Class attribute write test
  631.    AClass modifyValues
  632.    AClass getValues
  633. } 0 {1 Goodbye {Goodbye Tester} {words of list a} 5 6} -dontclean
  634.  
  635. Test 4.1 {
  636.    # Unknown class in class method invocation
  637.    blah doMethod
  638. } 1 {invalid command name "blah"}
  639.  
  640. Test 4.2 {
  641.    # Unknown class in class method invocation
  642.    otclInterface AClass {
  643.    }
  644.    AClass doMethod
  645. } 1 {invalid command name "AClass"}
  646.  
  647. Test 4.3 {
  648.    # Unknown method in class method invocation
  649.    otclInterface AClass {
  650.    }
  651.    otclImplementation AClass {
  652.    }
  653.    AClass unknownMethod
  654. } 1 {Class method "unknownMethod" not found for class "AClass".} -dontclean
  655.  
  656. Test 4.4 {
  657.    # Not enough args for class method invocation
  658.    AClass
  659. } 1 {wrong # args: should be "class method ?arg...?"}
  660.    
  661.  
  662. Test 5.1 {
  663.    # Not enough argument for method
  664.    otclInterface AClass {
  665.      classMethod m1 {a}
  666.    }
  667.    otclImplementation AClass {
  668.       classMethod m1 {a} {
  669.          return "AClass::m1 called with a = $a"
  670.       }
  671.    }
  672.    AClass m1
  673. } 1 {Formal argument "a" has no default value but not enough actual aguments.} -dontclean
  674.  
  675. Test 5.2 {
  676.    # Too many arguments for method
  677.    AClass m1 a b
  678. } 1 {Too many arguments have been supplied to "AClass::m1".} -dontclean
  679.  
  680. Test 5.3 {
  681.    # Correct number of arguments
  682.    list [AClass m1 Hello] [AClass m1 5] [AClass m1 [expr 5 * 66]]
  683. } 0 {{AClass::m1 called with a = Hello} {AClass::m1 called with a = 5} {AClass::m1 called with a = 330}}
  684.  
  685. Test 5.4 {
  686.    # Test default parameters
  687.    otclInterface AClass {
  688.       classMethod m1 {a {b 15}}
  689.    }
  690.    otclImplementation AClass {
  691.       classMethod m1 {a b} {
  692.          return "AClass::m1 called with a = $a, b = $b"
  693.       }
  694.    }
  695.    AClass m1 10
  696. } 0 {AClass::m1 called with a = 10, b = 15} -dontclean
  697.  
  698. Test 5.5 {
  699.    # Test default override
  700.    AClass m1 10 12
  701. } 0 {AClass::m1 called with a = 10, b = 12}
  702.  
  703. Test 5.6 {
  704.    # Test trailing 'args' empty
  705.    otclInterface AClass {
  706.       classMethod m1 {a args}
  707.    }
  708.    otclImplementation AClass {
  709.       classMethod m1 {a args} {
  710.          list $a $args
  711.       }
  712.    }
  713.    AClass m1 5
  714. } 0 {5 {}} -dontclean
  715.  
  716. Test 5.7 {
  717.    # Test trailing 'args' with 1 value
  718.    AClass m1 5 6
  719. } 0 {5 6} -dontclean
  720.  
  721. Test 5.8 {
  722.    # Test trailing 'args' with a list of values
  723.    AClass m1 5 6 7 8 {Hello People} My Name Is Fred
  724. } 0 {5 {6 7 8 {Hello People} My Name Is Fred}}
  725.  
  726. Test 6.1 {
  727.    # Test initialisation and reading of instance attributes
  728.    set results {}
  729.  
  730.    otclInterface AClass {
  731.       constructor {}
  732.       method getValues {}
  733.       method modifyValues {}
  734.    }
  735.    otclImplementation AClass {
  736.  
  737.       constructor {} {} {
  738.          global results
  739.          lappend results [$this getValues]
  740.       }
  741.  
  742.       method getValues {} {
  743.          list $att0 $att1 $att2 $att3 $att4 $att5(key1) $att5(key2)
  744.       }
  745.  
  746.       method modifyValues {} {
  747.          set att0 0
  748.          set att1 1
  749.          set att2 Goodbye
  750.          set att3 "Goodbye Tester"
  751.          set att4 {words of list a}
  752.          set att5(key1) 5
  753.          set att5(key2) 6
  754.       }
  755.  
  756.       attribute att0
  757.       attribute att1 0
  758.       attribute att2 Hello
  759.       attribute att3 "Hello Tester"
  760.       attribute att4 {a list of words}
  761.       attribute att5() {{key1 value1} {key2 value2}}
  762.    }
  763.  
  764.    set a [otclNew AClass]
  765.    otclDelete $a
  766.  
  767.    set results
  768. } 0 {{{} 0 Hello {Hello Tester} {a list of words} value1 value2}} -dontclean
  769.  
  770. Test 6.2 {
  771.    # Test writing of instance attributes
  772.    set results {}
  773.  
  774.    set a [otclNew AClass]
  775.    $a modifyValues
  776.    lappend results [$a getValues]
  777.    otclDelete $a
  778.  
  779.    set results
  780. } 0 {{{} 0 Hello {Hello Tester} {a list of words} value1 value2} {0 1 Goodbye {Goodbye Tester} {words of list a} 5 6}}  -dontclean
  781.  
  782. Test 6.3 {
  783.    # Test independence of instance attributes
  784.    set results {}
  785.  
  786.    set a [otclNew AClass]
  787.    $a modifyValues
  788.  
  789.    set b [otclNew AClass]
  790.    lappend results [$a getValues]
  791.    lappend results [$b getValues]
  792.    otclDelete $a
  793.    otclDelete $b
  794.  
  795.    set results
  796. } 0 {{{} 0 Hello {Hello Tester} {a list of words} value1 value2} {{} 0 Hello {Hello Tester} {a list of words} value1 value2} {0 1 Goodbye {Goodbye Tester} {words of list a} 5 6} {{} 0 Hello {Hello Tester} {a list of words} value1 value2}}
  797.  
  798. Test 7.1 {
  799.    # Test constructor execution
  800.    set results {}
  801.  
  802.    otclInterface AClass {
  803.       constructor {}
  804.    }
  805.    otclImplementation AClass {
  806.       constructor {} {} {
  807.           global results
  808.           set results {AClass::constructor called}
  809.       }
  810.    }
  811.    otclDelete [otclNew AClass]
  812.    set results
  813. } 0 {AClass::constructor called}
  814.  
  815. Test 7.2 {
  816.    # Test constructor ordering for multiple inheritance
  817.    set results {}
  818.  
  819.    otclInterface AClass {
  820.       constructor {}
  821.    }
  822.    otclImplementation AClass {
  823.       constructor {} {} {
  824.           global results
  825.           lappend results "AClass::constructor called"
  826.       }
  827.    }
  828.    otclInterface BClass {
  829.       constructor {}
  830.    }
  831.    otclImplementation BClass {
  832.       constructor {} {} {
  833.          global results
  834.          lappend results "BClass::constructor called"
  835.       }
  836.    }
  837.    otclInterface CClass -isA {AClass BClass} {
  838.       constructor {}
  839.    }
  840.    otclImplementation CClass {
  841.       constructor {} {} {
  842.          global results
  843.          lappend results "CClass::constructor called"
  844.       }
  845.    }
  846.    otclDelete [otclNew CClass]
  847.    set results
  848. } 0 {{AClass::constructor called} {BClass::constructor called} {CClass::constructor called}}
  849.  
  850. Test 7.3 {
  851.    # Test passing arguments to parent constructor
  852.    set results {}
  853.  
  854.    otclInterface AClass {
  855.       constructor {a {b 0}}
  856.    }
  857.    otclImplementation AClass {
  858.       constructor {a b} {} {
  859.         global results
  860.         lappend results "AClass::constructor called with a = $a, b = $b"
  861.       }
  862.    }
  863.    otclInterface BClass {
  864.       constructor {{a 5}} 
  865.    }
  866.    otclImplementation BClass {
  867.       constructor {a} {} {
  868.          lappend results "BClass::constructor called with a = $a"
  869.       }
  870.    }
  871.    otclInterface CClass -isA {AClass BClass} {
  872.       constructor {a b}
  873.    }
  874.    otclImplementation CClass {
  875.       constructor {a b} {{AClass [expr $a * $b]}} {
  876.          lappend results "CClass::constructor called with a = $a, b = $b"
  877.       }
  878.    }
  879.    otclDelete [otclNew CClass 10 20]
  880.    set results
  881. } 0 {{AClass::constructor called with a = 200, b = 0}}
  882.  
  883. Test 8.1 {
  884.    # Test destructor calling
  885.    set results {}
  886.  
  887.    otclInterface AClass {}
  888.    otclImplementation AClass {
  889.       destructor {
  890.           global results
  891.           lappend results "AClass::destructor called"
  892.       }
  893.    }
  894.    set a [otclNew AClass]
  895.    lappend results "About to destroy AClass instance"
  896.    otclDelete $a
  897.    set results
  898. } 0 {{About to destroy AClass instance} {AClass::destructor called}}
  899.  
  900. Test 8.2 {
  901.    # Test destructor ordering in multiple inheritance
  902.    set results {}
  903.  
  904.    otclInterface AClass {}
  905.    otclImplementation AClass {
  906.       destructor {
  907.          global results
  908.          lappend results "AClass::destructor called"
  909.       }
  910.    }
  911.    otclInterface BClass {}
  912.    otclImplementation BClass {
  913.       destructor {
  914.          global results
  915.          lappend results "BClass::destructor called"
  916.       }
  917.    }
  918.    otclInterface CClass -isA {AClass BClass} {}
  919.    otclImplementation CClass {
  920.       destructor {
  921.          global results
  922.          lappend results "CClass::destructor called"
  923.       }
  924.    }
  925.    set a [otclNew CClass]
  926.    otclDelete $a
  927.  
  928.    set results
  929. } 0 {{CClass::destructor called} {BClass::destructor called} {AClass::destructor called}}
  930.  
  931. Test 9.1 {
  932.    # Test instance method invocation
  933.    set results {}
  934.  
  935.    otclInterface AClass {
  936.       method m1 {}
  937.    }
  938.    otclImplementation AClass {
  939.       method m1 {} {
  940.          global results
  941.          lappend results "AClass::m1 called"
  942.       }
  943.    }
  944.    set a [otclNew AClass]
  945.    $a m1
  946.    otclDelete $a
  947.  
  948.    set results
  949. } 0 {{AClass::m1 called}} -dontclean
  950.  
  951. Test 9.3 {
  952.    # Test instance method not known
  953.  
  954.    set a [otclNew AClass]
  955.    $a m2
  956. } 1 {Instance method "m2" not found for object of class "AClass".}
  957.  
  958. catch {otclDelete $a}
  959.  
  960. Test 10.1 {
  961.    # Test private instance method access
  962.    otclInterface AClass {
  963.       method m1 {}
  964.    }
  965.    otclImplementation AClass {
  966.       method m1 {} {
  967.          $this m2
  968.       }
  969.       method m2 {} {
  970.          return "AClass::m2 called"
  971.       }
  972.    }
  973.    set a [otclNew AClass]
  974.    $a m2
  975. } 1 {Method "m2" of class "AClass" is private and cannot be accessed from outside class scope.} -dontclean
  976. catch {otclDelete $a}
  977.  
  978. Test 10.2 {
  979.    # Test private instance access
  980.    set a [otclNew AClass]
  981.    set results [$a m1]
  982.    otclDelete $a
  983.  
  984.    set results
  985. } 0 {AClass::m2 called}
  986.  
  987. Test 11.1 {
  988.    # Test private class method access
  989.    otclInterface AClass {
  990.       classMethod m1 {}
  991.    }
  992.    otclImplementation AClass {
  993.       classMethod m1 {} {
  994.          AClass m2
  995.       }
  996.       classMethod m2 {} { 
  997.          return "AClass::m2 called"
  998.       }
  999.    }
  1000.    AClass m2
  1001. } 1 {Method "m2" of class "AClass" is private and cannot be accessed from outside class scope.} -dontclean
  1002.  
  1003. Test 11.2 {
  1004.    # Test private class method access
  1005.    AClass m1
  1006. } 0 {AClass::m2 called}
  1007.  
  1008. Test 12.1 {
  1009.    # Test invocation of inherit method from outside
  1010.    otclInterface AClass {
  1011.       method m1 {}
  1012.    }
  1013.    otclImplementation AClass {
  1014.      method m1 {} {
  1015.          return "AClass::m1 called"
  1016.      }
  1017.    }
  1018.    otclInterface BClass -isA AClass {
  1019.       method m2 {}
  1020.    }
  1021.    otclImplementation BClass {
  1022.       method m2 {} {
  1023.          $this m1
  1024.       }
  1025.    }
  1026.    set a [otclNew BClass]
  1027.    set results [$a m1]
  1028.    otclDelete $a
  1029.    set results
  1030. } 0 {AClass::m1 called} -dontclean
  1031.  
  1032. Test 12.2 {
  1033.    # Test invocation of inherited method from insidde
  1034.    set a [otclNew BClass]
  1035.    set results [$a m2]
  1036.    otclDelete $a
  1037.  
  1038.    set results
  1039. } 0 {AClass::m1 called} -dontclean
  1040.  
  1041. Test 12.3 {
  1042.    # Tes invocation of method inherited in both parent from outside
  1043.    otclInterface CClass {
  1044.       method m1 {}
  1045.    }
  1046.    otclImplementation CClass {
  1047.       method m1 {} {
  1048.          return "CClass::m1 called"
  1049.       }
  1050.    }
  1051.    otclInterface DClass -isA {AClass CClass} {
  1052.       method m3 {}
  1053.       method m4 {}
  1054.    }
  1055.    otclImplementation DClass {
  1056.       method m3 {} {
  1057.          $this m1
  1058.       }
  1059.       method m4 {} {
  1060.          # Force it to take the CClass version
  1061.          $this -CClass m1
  1062.       }
  1063.    }
  1064.    set a [otclNew DClass]
  1065.    set results [$a m1]
  1066.    otclDelete $a
  1067.  
  1068.    set results
  1069. } 0 {AClass::m1 called} -dontclean
  1070.  
  1071. Test 12.4 {
  1072.    # Test invocation of method inherited in both parents from inside
  1073.    set results {}
  1074.  
  1075.    set a [otclNew DClass]
  1076.    lappend results [$a m3]
  1077.    lappend results [$a m4]
  1078.    otclDelete $a
  1079.  
  1080.    set results
  1081. } 0 {{AClass::m1 called} {CClass::m1 called}}
  1082.  
  1083. Test 13.1 {
  1084.    # Test dynamic binding of method with single inheritance
  1085.    set results {}
  1086.  
  1087.    otclInterface AClass {
  1088.       method m1 {}
  1089.    }
  1090.    otclImplementation AClass {
  1091.       method m1 {} {
  1092.          global results
  1093.          lappend results "AClass::m1 called"
  1094.       }
  1095.    }
  1096.    otclInterface BClass -isA AClass {
  1097.       method m1 {}
  1098.    }
  1099.    otclImplementation BClass {
  1100.       method m1 {} {
  1101.          return "BClass::m1 called"
  1102.       }
  1103.    }
  1104.    set a [otclNew BClass]
  1105.    set results [$a m1]
  1106.    otclDelete $a
  1107.  
  1108.    set results
  1109. } 0 {BClass::m1 called} -dontclean
  1110.  
  1111. Test 13.2 {
  1112.    # Test dynamic binding of method with multiple inheritance
  1113.    set results {}
  1114.  
  1115.  
  1116.    otclInterface CClass {
  1117.      method m1 {}
  1118.    }
  1119.    otclImplementation CClass {
  1120.       method m1 {} {
  1121.          global results
  1122.          lappend results "CClass::m1 called"
  1123.       }
  1124.    }
  1125.    otclInterface DClass -isA {BClass CClass} {
  1126.      method m1 {}
  1127.      method m2 {}
  1128.    }
  1129.    otclImplementation DClass {
  1130.       method m1 {} {
  1131.          global results
  1132.          lappend results "DClass::m1 called"
  1133.       }
  1134.       method m2 {} {
  1135.          $this -CClass m1
  1136.       }
  1137.    }
  1138.    
  1139.    set a [otclNew DClass]
  1140.    $a m1
  1141.    otclDelete $a
  1142.  
  1143.    set results
  1144. } 0 {{DClass::m1 called}} -dontclean
  1145.  
  1146. Test 13.3 {
  1147.    # Test dynamic binding override
  1148.    set results {}
  1149.  
  1150.    set a [otclNew DClass]
  1151.    $a m2
  1152.    otclDelete $a
  1153.  
  1154.    set results
  1155. } 0 {{CClass::m1 called}} -dontclean
  1156.  
  1157. Test 13.4 {
  1158.    # Test dynamic bind override for a not base class
  1159.    otclInterface EClass -isA DClass {
  1160.       method m1 {}
  1161.    }
  1162.    otclImplementation EClass {
  1163.       method m1 {} {
  1164.          $this -FClass m1
  1165.       }
  1166.    }
  1167.  
  1168.    set a [otclNew EClass]
  1169.    $a m1
  1170. } 1 {Class "FClass" is not a superclass of class "EClass".}
  1171. catch {otclDelete $a}
  1172.  
  1173. Test 14.1 {
  1174.    # Test Unknown Instance Method
  1175.    otclInterface AClass {}
  1176.    otclImplementation AClass {}
  1177.    set a [otclNew AClass]
  1178.    $a m1
  1179.    otclDelete $a
  1180. } 1 {Instance method "m1" not found for object of class "AClass".}
  1181.  
  1182. Test 15.1 {
  1183.    # Not enough args for otclNew
  1184.    otclNew
  1185. } 1 {wrong # args: should be "otclNew className args"}
  1186.  
  1187. Test 15.2 {
  1188.    # Unknown class for otclNew
  1189.    otclNew AClass
  1190. } 1 {Class "AClass" is undefined.}
  1191.  
  1192. Test 16.1 {
  1193.    # Not enough arguments for otclDelete
  1194.    otclDelete
  1195. } 1 {wrong # args: should be "otclDelete object"}
  1196.  
  1197. Test 16.2 {
  1198.    # Bad object for otclDelete
  1199.    otclDelete 123bE
  1200. } 1 {Object (123bE) unknown.}
  1201.  
  1202. Test 17.1 {
  1203.    # Syntax error in constructor body no inheritance
  1204.    otclInterface AClass {
  1205.       constructor {}
  1206.    }
  1207.    otclImplementation AClass {
  1208.       constructor {} {} {
  1209.          some rubbish
  1210.       }
  1211.    }
  1212.  
  1213.    set a [otclNew AClass]
  1214.    otclDelete $a
  1215. } 1 {invalid command name "some"} -dontclean
  1216.  
  1217. Test 17.2 {
  1218.    # Syntax error in constructor body with inheritance
  1219.    otclInterface BClass -isA AClass {
  1220.    }
  1221.    otclImplementation BClass {
  1222.    }
  1223.    
  1224.    set a [otclNew BClass]
  1225.    otclDelete $a
  1226. } 1 {invalid command name "some"}
  1227.  
  1228. Test 17.3 {
  1229.    # Syntax error in class method
  1230.    otclInterface AClass {
  1231.       classMethod m1 {}
  1232.    }
  1233.    otclImplementation AClass {
  1234.       classMethod m1 {} {
  1235.          some rubbish
  1236.       }
  1237.    }
  1238.    AClass m1
  1239. } 1 {invalid command name "some"}
  1240.  
  1241. Test 17.4 {
  1242.    # Syntax error in instance method
  1243.    otclInterface AClass {
  1244.       method m1 {}
  1245.    }
  1246.    otclImplementation AClass {
  1247.       method m1 {} {
  1248.          some rubbish
  1249.       }
  1250.    }
  1251.    set a [otclNew AClass]
  1252.    $a m1
  1253.    otclDelete $a
  1254. } 1 {invalid command name "some"}
  1255.  
  1256. Test 17.5 {
  1257.    # Syntax error in destructor, no inheritance
  1258.    otclInterface AClass {
  1259.    }
  1260.    otclImplementation AClass {
  1261.       destructor {
  1262.          some rubbish
  1263.       }
  1264.    }
  1265.    set a [otclNew AClass]
  1266.    otclDelete $a
  1267. } 1 {invalid command name "some"} -dontclean
  1268.  
  1269. Test 17.6 {
  1270.    # Syntax error in destructor, inheritance
  1271.    otclInterface BClass -isA AClass {
  1272.    }
  1273.    otclImplementation BClass {
  1274.    }
  1275.    set a [otclNew AClass]
  1276.    otclDelete $a
  1277. } 1 {invalid command name "some"} -dontclean
  1278.  
  1279. Test 17.7 {
  1280.    # Syntax error in parent constructor
  1281.    otclInterface CClass -isA BClass {
  1282.       constructor {a}
  1283.    }
  1284.    otclImplementation CClass {
  1285.       constructor {a} {{BClass [expr $a + $b]}} {
  1286.       }
  1287.    }
  1288.    set a [otclNew CClass 55]
  1289. } 1 {can't read "b": no such variable}
  1290.  
  1291. Test 18.1 {
  1292.    # constructor duplicate in interface
  1293.    otclInterface AClass {
  1294.       constructor {}
  1295.       constructor {}
  1296.    }
  1297. } 1 {Method "constructor" duplicated in interface for class "AClass".}
  1298.  
  1299. Test 18.2 {
  1300.    # constructor duplicate in implementation
  1301.    otclInterface AClass {
  1302.       constructor {}
  1303.    }
  1304.    otclImplementation AClass {
  1305.       constructor {} {} {}
  1306.       constructor {} {} {}
  1307.    }
  1308. } 1 {Method "AClass::constructor" implementated twice.}
  1309.  
  1310. Test 18.3 {
  1311.    # destructor duplicated in implementation
  1312.    otclInterface AClass {}
  1313.    otclImplementation AClass {
  1314.       destructor {}
  1315.       destructor {}
  1316.    }
  1317. } 1 {Re-definition of destructor in class "AClass".}
  1318.  
  1319. Test 19.1 {
  1320.    # Constructor arg same as inst attribute
  1321.    otclInterface AClass {
  1322.       constructor {a}
  1323.    }
  1324.    otclImplementation AClass {
  1325.       constructor {a} {} {}
  1326.       attribute a
  1327.    }
  1328. } 1 {Method "constructor" of class "AClass" has a formal argument "a" that classes with an attribute of the same name.}
  1329.  
  1330. Test 19.2 {
  1331.    # Constructor arg same as class attribute
  1332.    otclInterface AClass {
  1333.       constructor {a}
  1334.    }
  1335.    otclImplementation AClass {
  1336.       constructor {a} {} {}
  1337.       classAttribute a 0
  1338.    }
  1339. } 1 {Method "constructor" of class "AClass" has a formal argument "a" that classes with an attribute of the same name.}
  1340.  
  1341. Test 19.3 {
  1342.    # Instance method arg same as inst attribute
  1343.    otclInterface AClass {
  1344.       method a {b}
  1345.    }
  1346.    otclImplementation AClass {
  1347.       method a {b} {}
  1348.       attribute b
  1349.    }
  1350. } 1 {Method "a" of class "AClass" has a formal argument "b" that classes with an attribute of the same name.}
  1351.  
  1352. Test 19.4 {
  1353.    # Instance method arg same as class attribute
  1354.    otclInterface AClass {
  1355.       method a {b}
  1356.    }
  1357.    otclImplementation AClass {
  1358.       method a {b} {}
  1359.       classAttribute b 0
  1360.    }
  1361. } 1 {Method "a" of class "AClass" has a formal argument "b" that classes with an attribute of the same name.}
  1362.  
  1363. Test 19.5 {
  1364.    # Class method arg same as instance attribute
  1365.    otclInterface AClass {
  1366.       classMethod a {b}
  1367.    }
  1368.    otclImplementation AClass {
  1369.       classMethod a {b} {}
  1370.       attribute b
  1371.    }
  1372. } 0 {}
  1373.  
  1374. Test 19.6 {
  1375.    # Class method arg same as class attribute
  1376.    otclInterface AClass {
  1377.       classMethod a {b}
  1378.    }
  1379.    otclImplementation AClass {
  1380.       classMethod a {b} {}
  1381.       classAttribute b 0
  1382.    }
  1383. } 1 {Method "a" of class "AClass" has a formal argument "b" that classes with an attribute of the same name.}
  1384.  
  1385. Test 20.1 {
  1386.    set results {}
  1387.  
  1388.    # Test unknown method
  1389.    otclInterface AClass {
  1390.       method unknown {args}
  1391.    }
  1392.    otclImplementation AClass {
  1393.       method unknown {args} {
  1394.          global results
  1395.          set results [list unknown $args]
  1396.       }
  1397.    }
  1398.  
  1399.    set o [otclNew AClass]
  1400.    $o notARealMethod 55 66 77
  1401.    otclDelete $o
  1402.  
  1403.    set results
  1404. } 0 {unknown {notARealMethod 55 66 77}} -dontclean
  1405.  
  1406. Test 20.2 {
  1407.    # Test unknown method is inherited
  1408.    set results {}
  1409.  
  1410.    otclInterface BClass -isA AClass {
  1411.    }
  1412.    otclImplementation BClass {}
  1413.  
  1414.    set o [otclNew BClass]
  1415.    $o notARealMethod 77 66 55
  1416.    otclDelete $o
  1417.  
  1418.    set results
  1419. } 0 {unknown {notARealMethod 77 66 55}}
  1420.  
  1421. Test 21.1 {
  1422.    # Test manipulation of a C++ class, object
  1423.    set results {}
  1424.  
  1425.    lappend results [SimpleCppClass getNoOfObjects]
  1426.    set a [otclNew SimpleCppClass "Hello" 55]
  1427.    lappend results [SimpleCppClass getNoOfObjects]
  1428.    lappend results [$a getValue]
  1429.    lappend results [$a getStr]
  1430.    $a setValue 12
  1431.    $a setStr "Goodbye"
  1432.    lappend results [$a getValue]
  1433.    lappend results [$a getStr]
  1434.    set b [otclNew SimpleCppClass "Bob" 99]
  1435.    otclDelete $a
  1436.    otclDelete $b
  1437.  
  1438.    set results
  1439. } 0 {0 {SimpleCppClass constructed} 1 55 Hello 12 Goodbye {SimpleCppClass constructed} {SimpleCppClass destructed} {SimpleCppClass destructed}}
  1440.  
  1441. Test 21.2 {
  1442.    # Test inheritance from C++ class
  1443.    set results {}
  1444.  
  1445.    otclInterface AClass -isA SimpleCppClass {
  1446.       constructor {str val}
  1447.    }
  1448.    otclImplementation AClass {
  1449.       constructor {str val} {{SimpleCppClass $str $val}} {
  1450.          lappend results "AClass constructed"
  1451.       }
  1452.       destructor {
  1453.          lappend results "AClass destructed"
  1454.       }
  1455.    }
  1456.    lappend results [SimpleCppClass getNoOfObjects]
  1457.    set a [otclNew AClass "Hello" 55]
  1458.    lappend results [SimpleCppClass getNoOfObjects]
  1459.    lappend results [$a getValue]
  1460.    lappend results [$a getStr]
  1461.    $a setValue 12
  1462.    $a setStr "Goodbye"
  1463.    lappend results [$a getValue]
  1464.    lappend results [$a getStr]
  1465.    otclDelete $a
  1466.  
  1467.    set results
  1468. } 0 {0 {SimpleCppClass constructed} 1 55 Hello 12 Goodbye {SimpleCppClass destructed}}
  1469.  
  1470. Test 21.3 {
  1471.    # Test dynamic binding of methods from C++.
  1472.    set results {}
  1473.  
  1474.    otclInterface AClass -isA TestCppClass {
  1475.       constructor {{val 0}}
  1476.       method methodTwo {}
  1477.    }
  1478.    otclImplementation AClass {
  1479.       constructor {v} {} {
  1480.          set val $v
  1481.       }
  1482.       method methodTwo {} {
  1483.          global results
  1484.          lappend results "AClass::methodTwo called, val = $val"
  1485.       }
  1486.       attribute val
  1487.    }
  1488.    set a [otclNew AClass]
  1489.    $a methodOne
  1490.    otclDelete $a
  1491.  
  1492.    set results
  1493. } 0 {{AClass::methodTwo called, val = 0}} -dontclean
  1494.  
  1495. Test 21.4 {
  1496.    # Test C++ manipulation of Object Tcl object
  1497.    set results {}
  1498.  
  1499.    set a [otclNew AClass]
  1500.    set b [otclNew AClass 99]
  1501.    $a setOtherObject $b
  1502.    if {[$a getOtherObject] != $b} {
  1503.       lappend results "object returned is different to object given"
  1504.    }
  1505.    $a doMethodTwoOnOtherObject
  1506.    otclDelete $a
  1507.    otclDelete $b
  1508.  
  1509.    set results
  1510. } 0 {{AClass::methodTwo called, val = 99}}
  1511.  
  1512. Test 22.1 {
  1513.    # Test this available from constructor
  1514.    set results {}
  1515.  
  1516.    otclInterface AClass {
  1517.       constructor {}
  1518.       method methodOne {}
  1519.    }
  1520.    otclImplementation AClass {
  1521.       constructor {} {} {
  1522.          $this methodOne
  1523.       }
  1524.       method methodOne {} {
  1525.          global results
  1526.          lappend results "AClass::methodOne called"
  1527.       }
  1528.    }
  1529.    otclNew AClass
  1530.  
  1531.    set results
  1532. } 0 {{AClass::methodOne called}} -dontclean
  1533.  
  1534. Test 22.2 {
  1535.    # Test this available from constructor of superclass part
  1536.    set results {}
  1537.  
  1538.    otclInterface BClass -isA AClass {
  1539.       constructor {}
  1540.       method methodTwo {}
  1541.    }
  1542.    otclImplementation BClass {
  1543.       constructor {} {} {
  1544.          $this methodTwo
  1545.       }
  1546.       method methodTwo {} {
  1547.          global results
  1548.          lappend results "BClass::methodTwo called"
  1549.       }
  1550.    }
  1551.    otclNew BClass
  1552.  
  1553.    set results 
  1554. } 0 {{AClass::methodOne called} {BClass::methodTwo called}}
  1555.  
  1556. Test 23.1 {
  1557.    # Test global commands are available
  1558.    set results {}
  1559.    
  1560.    proc constructor {} {global results; lappend results "constructor"}
  1561.    proc destructor {} {global results; lappend results "destructor"}
  1562.    proc method {} {global results; lappend results "method"}
  1563.    proc classMethod {} {global results; lappend results "classMethod"}
  1564.    proc attribute {} {global results; lappend results "attribute"}
  1565.    proc classAttribute {} {global results; lappend results "classAttribute"}
  1566.  
  1567.    constructor
  1568.    destructor
  1569.    method
  1570.    classMethod
  1571.    attribute
  1572.    classAttribute
  1573.  
  1574.    otclInterface AClass {}
  1575.  
  1576.    constructor
  1577.    destructor
  1578.    method
  1579.    classMethod
  1580.    attribute
  1581.    classAttribute
  1582.  
  1583.    otclImplementation AClass {}
  1584.  
  1585.    constructor
  1586.    destructor
  1587.    method
  1588.    classMethod
  1589.    attribute
  1590.    classAttribute
  1591.  
  1592.    set results
  1593.  
  1594. } 0 {constructor destructor method classMethod attribute classAttribute constructor destructor method classMethod attribute classAttribute constructor destructor method classMethod attribute classAttribute}
  1595.  
  1596. Test 24.1 {
  1597.    set results {}
  1598.    set a [otclNew PtrTestClass NULL]
  1599.    otclDelete $a
  1600.    set a [otclNew PtrTestClass null]
  1601.    otclDelete $a
  1602.    set a [otclNew PtrTestClass 0]
  1603.    set b [otclNew PtrTestClass $a]
  1604.    otclDelete $b
  1605.    
  1606.    PtrTestClass classMethodTest NULL
  1607.    PtrTestClass classMethodTest null
  1608.    PtrTestClass classMethodTest 0
  1609.    PtrTestClass classMethodTest $a
  1610.  
  1611.    $a instanceMethodTest NULL
  1612.    $a instanceMethodTest null
  1613.    $a instanceMethodTest 0
  1614.    $a instanceMethodTest $a
  1615.  
  1616.    otclDelete $a
  1617.  
  1618.    set results
  1619. } 0 {{passed ptr == NULL} {passed ptr == NULL} {passed ptr == NULL} {passed ptr != NULL} {passed ptr == NULL} {passed ptr == NULL} {passed ptr == NULL} {passed ptr != NULL} {passed ptr == NULL} {passed ptr == NULL} {passed ptr == NULL} {passed ptr != NULL}}
  1620.  
  1621. Test 24.2 {
  1622.    set results {}
  1623.  
  1624.    set a [otclNew PtrTestClass invalid]
  1625.  
  1626.    set results
  1627. } 1 {Argument 0 invalid}
  1628.  
  1629. Test 24.3 {
  1630.    set results {}
  1631.  
  1632.    PtrTestClass classMethodTest invalid
  1633.  
  1634.    set results
  1635. } 1 {Argument 0 invalid.}
  1636.  
  1637. Test 24.4 {
  1638.  
  1639.    set a [otclNew PtrTestClass NULL]
  1640.    $a instanceMethodTest invalid
  1641.  
  1642. } 1 {Argument 0 invalid.}
  1643.