1### 2# Test script build functions 3### 4 5set result {} 6putb result {# clay.test - Copyright (c) 2018 Sean Woods 7# ------------------------------------------------------------------------- 8 9set MODDIR [file dirname [file dirname [file join [pwd] [info script]]]] 10if {[file exists [file join $MODDIR devtools testutilities.tcl]]} { 11 # Running inside tcllib 12 set TCLLIBMOD $MODDIR 13} else { 14 set TCLLIBMOD [file join $MODDIR .. .. tcllib modules] 15} 16source [file join $TCLLIBMOD devtools testutilities.tcl] 17 18testsNeedTcl 8.6 19testsNeedTcltest 2 20testsNeed TclOO 1 21 22support {} 23testing { 24 useLocal clay.tcl clay 25} 26} 27 28putb result { 29set ::clay::trace 0 30} 31 32### 33# UUID test 34### 35putb result { 36 37# ------------------------------------------------------------------------- 38# Handle multiple implementation testing 39# 40 41array set preserve [array get ::clay::uuid::accel] 42 43proc implementations {} { 44 variable ::clay::uuid::accel 45 foreach {a v} [array get accel] {if {$v} {lappend r $a}} 46 lappend r tcl; set r 47} 48 49proc select_implementation {impl} { 50 variable ::clay::uuid::accel 51 foreach e [array names accel] { set accel($e) 0 } 52 if {[string compare "tcl" $impl] != 0} { 53 set accel($impl) 1 54 } 55} 56 57proc reset_implementation {} { 58 variable ::clay::uuid::accel 59 array set accel [array get ::preserve] 60} 61 62# ------------------------------------------------------------------------- 63# Setup any constraints 64# 65 66# ------------------------------------------------------------------------- 67# Now the package specific tests.... 68# ------------------------------------------------------------------------- 69 70# ------------------------------------------------------------------------- 71 72foreach impl [implementations] { 73 select_implementation $impl 74 75 test uuid-1.0-$impl "uuid requires args" { 76 list [catch {clay::uuid} msg] 77 } {1} 78 79 test uuid-1.1-$impl "uuid generate should create a 36 char string uuid" { 80 list [catch {string length [clay::uuid generate]} msg] $msg 81 } {0 36} 82 83 test uuid-1.2-$impl "uuid comparison of uuid with self should be true" { 84 list [catch { 85 set a [clay::uuid generate] 86 clay::uuid equal $a $a 87 } msg] $msg 88 } {0 1} 89 90 test uuid-1.3-$impl "uuid comparison of two different\ 91 uuids should be false" { 92 list [catch { 93 set a [clay::uuid generate] 94 set b [clay::uuid generate] 95 clay::uuid equal $a $b 96 } msg] $msg 97 } {0 0} 98 99 reset_implementation 100} 101} 102 103 104putb result { 105# Modification History: 106### 107# Modification 2018-10-30 108# Fixed an error in our ancestry mapping and developed tests to 109# ensure we are actually following in the order TclOO follows methods 110### 111# Modification 2018-10-21 112# The clay metaclass no longer exports the clay method 113# to oo::class and oo::object, and clay::ancestors no 114# longer returns any class that lacks the clay method 115### 116# Modification 2018-10-10 117# clay::ancestors now rigged to descend into all classes depth-first 118# and then place metaclasses at the end of the search 119### 120# ------------------------------------------------------------------------- 121 122# ------------------------------------------------------------------------- 123# Test Helpers 124### 125proc dict_compare {a b} { 126 set result {} 127 set A {} 128 dict for {f v} $a { 129 set f [string trim $f :/] 130 if {$f eq {.}} continue 131 dict set A $f $v 132 } 133 set B {} 134 dict for {f v} $b { 135 set f [string trim $f :/] 136 if {$f eq {.}} continue 137 dict set B $f $v 138 } 139 dict for {f v} $A { 140 if {[dict exists $B $f]} { 141 if {[dict get $B $f] ne $v} { 142 lappend result [list B $f [dict get $B $f] [list != $v]] 143 } 144 } else { 145 lappend result [list B $f $v missing] 146 } 147 } 148 dict for {f v} $B { 149 if {![dict exists $A $f]} { 150 lappend result [list A $f $v missing] 151 } 152 } 153 return $result 154} 155 156test dict-compare-001 {Test our testing method} { 157 dict_compare {} {} 158} {} 159 160test dict-compare-002 {Test our testing method} { 161 dict_compare {a 1} {} 162} {{B a 1 missing}} 163 164test dict-compare-003 {Test our testing method} { 165 dict_compare {a 1 b 2} {a 1 b 2} 166} {} 167 168test dict-compare-003.a {Test our testing method} { 169 dict_compare {a 1 b 2} {b 2 a 1 } 170} {} 171 172test dict-compare-003.b {Test our testing method} { 173 dict_compare {b 2 a 1} {a 1 b 2} 174} {} 175 176 177test dict-compare-004 {Test our testing method} { 178 dict_compare {a: 1 b: 2} {a 1 b 2} 179} {} 180 181test dict-compare-005 {Test our testing method} { 182 dict_compare {a 1 b 3} {a 1 b 2} 183} {{B b 2 {!= 3}}} 184} 185 186 187### 188# Tests for clay::tree 189### 190 191putb result { 192### 193# Test canonical mapping 194### 195} 196set test 0 197 foreach {pattern canonical storage} { 198 {foo bar baz} {foo/ bar/ baz} {foo bar baz} 199 {foo bar baz/} {foo/ bar/ baz/} {foo bar baz} 200 {foo bar .} {foo/ bar} {foo bar .} 201 {foo/ bar/ .} {foo/ bar} {foo bar .} 202 {foo . bar . baz .} {foo/ bar/ baz} {foo . bar . baz .} 203 {foo bar baz bat:} {foo/ bar/ baz/ bat:} {foo bar baz bat:} 204 {foo:} {foo:} {foo:} 205 {foo/bar/baz/bat:} {foo/ bar/ baz/ bat:} {foo bar baz bat:} 206} { 207 dict set map %pattern% $pattern 208 dict set map %canonical% $canonical 209 dict set map %storage% $storage 210 incr test 211 212 dict set map %test% [format "test-storage-%04d" $test] 213 putb result $map { 214test {%test%} {Test ::clay::tree::storage with %pattern%} { 215 clay::tree::storage {%pattern%} 216} {%storage%} 217} 218} 219 220putb result { 221dict set r foo/ bar/ baz 1 222dict set s foo/ bar/ baz 0 223set t [clay::tree::merge $r $s] 224 225test rmerge-0001 {Test that the root is marked as a branch} { 226 dict get $t foo bar baz 227} 0 228 229set r [dict create] 230clay::tree::dictmerge r { 231 foo/ { 232 bar/ { 233 baz 1 234 bing: 2 235 bang { bim 3 boom 4 } 236 womp: {a 1 b 2} 237 } 238 } 239} 240 241test dictmerge-0001 {Test that the root is marked as a branch} { 242 dict exists $r . 243} 1 244test dictmerge-0002 {Test that branch foo is marked correctly} { 245 dict exists $r foo . 246} 1 247test dictmerge-0003 {Test that branch bar is marked correctly} { 248 dict exists $r foo bar . 249} 1 250test dictmerge-0004 {Test that leaf foo/bar/bang is not marked as branch despite being a dict} { 251 dict exists $r foo bar bang . 252} 0 253test dictmerge-0004 {Test that leaf foo/bar/bang/bim exists} { 254 dict exists $r foo bar bang bim 255} 1 256test dictmerge-0005 {Test that leaf foo/bar/bang/boom exists} { 257 dict exists $r foo bar bang boom 258} 1 259 260### 261# Replace bang with bang/ 262### 263clay::tree::dictmerge r { 264 foo/ { 265 bar/ { 266 bang/ { 267 whoop 1 268 } 269 } 270 } 271} 272 273test dictmerge-0006 {Test that leaf foo/bar/bang/bim ceases to exist} { 274 dict exists $r foo bar bang bim 275} 0 276test dictmerge-0007 {Test that leaf foo/bar/bang/boom exists} { 277 dict exists $r foo bar bang boom 278} 0 279 280test dictmerge-0008 {Test that leaf foo/bar/bang is now a branch} { 281 dict exists $r foo bar bang . 282} 1 283 284test branch-0001 {Test that foo/ is a branch} { 285 clay::tree::is_branch $r foo/ 286} 1 287test branch-0002 {Test that foo is a branch} { 288 clay::tree::is_branch $r foo 289} 1 290test branch-0003 {Test that foo/bar/ is a branch} { 291 clay::tree::is_branch $r {foo/ bar/} 292} 1 293test branch-0004 {Test that foo bar is not branch} { 294 clay::tree::is_branch $r {foo bar} 295} 1 296test branch-0004 {Test that foo/ bar is not branch} { 297 clay::tree::is_branch $r {foo/ bar} 298} 0 299} 300 301set test 0 302foreach {path isbranch} { 303 foo 1 304 {foo bar} 1 305 {foo bar baz} 0 306 {foo bar bing} 0 307 {foo bar bang} 1 308 {foo bar bang whoop} 0 309} { 310 set mpath [lrange $path 0 end-1] 311 set item [lindex $path end] 312 set tests [list {} {} $isbranch {} : 0 {} / 1 . {} 0] 313 dict set map %mpath% $mpath 314 dict set map %item% $item 315 foreach {head tail isbranch} $tests { 316 dict set map %head% $head 317 dict set map %tail% $tail 318 dict set map %isbranch% $isbranch 319 dict set map %test% [format "test-branch-%04d" [incr test]] 320 putb result $map { 321test {%test%} {Test that %mpath% %head%%item%%tail% is_branch = %isbranch%} { 322 clay::tree::is_branch $r {%mpath% %head%%item%%tail%} 323} %isbranch% 324} 325 } 326} 327 328putb result { 329# ------------------------------------------------------------------------- 330# dictmerge Testing - oometa 331unset -nocomplain foo 332clay::tree::dictmerge foo { 333 option/ { 334 color/ { 335 label Color 336 default green 337 } 338 } 339} 340clay::tree::dictmerge foo { 341 option/ { 342 color/ { 343 default purple 344 } 345 } 346} 347 348test oometa-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} { 349 dict get $foo option color default 350} purple 351test oometa-0002 {Invoking dictmerge with empty args on a non existent variable create an empty variable} { 352 dict get $foo option color label 353} Color 354 355unset -nocomplain foo 356set foo {. {}} 357::clay::tree::dictmerge foo {. {} color {. {} default green label Color}} 358::clay::tree::dictmerge foo {. {} color {. {} default purple}} 359test oometa-0003 {Recursive merge problem from oometa/clay find} { 360 dict get $foo color default 361} purple 362test oometa-0004 {Recursive merge problem from oometa/clay find} { 363 dict get $foo color label 364} Color 365 366unset -nocomplain foo 367set foo {. {}} 368::clay::tree::dictmerge foo {. {} color {. {} default purple}} 369::clay::tree::dictmerge foo {. {} color {. {} default green label Color}} 370test oometa-0005 {Recursive merge problem from oometa/clay find} { 371 dict get $foo color default 372} green 373test oometa-0006 {Recursive merge problem from oometa/clay find} { 374 dict get $foo color label 375} Color 376 377test oometa-0008 {Un-Sanitized output} { 378 set foo 379} {. {} color {. {} default green label Color}} 380 381test oometa-0009 {Sanitize} { 382 clay::tree::sanitize $foo 383} {color {default green label Color}} 384} 385 386 387putb result { 388# ------------------------------------------------------------------------- 389# dictmerge Testing - clay 390unset -nocomplain foo 391test clay-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} { 392 ::clay::tree::dictmerge foo 393 set foo 394} {. {}} 395 396unset -nocomplain foo 397::clay::tree::dictset foo bar/ baz/ bell bang 398 399test clay-0002 {For new entries dictmerge is essentially a set} { 400 dict get $foo bar baz bell 401} {bang} 402::clay::tree::dictset foo bar/ baz/ boom/ bang 403test clay-0003 {For entries that do exist a zipper merge is performed} { 404 dict get $foo bar baz bell 405} {bang} 406test clay-0004 {For entries that do exist a zipper merge is performed} { 407 dict get $foo bar baz boom 408} {bang} 409 410::clay::tree::dictset foo bar/ baz/ bop {color green flavor strawberry} 411 412test clay-0005 {Leaves are replaced even if they look like a dict} { 413 dict get $foo bar baz bop 414} {color green flavor strawberry} 415 416::clay::tree::dictset foo bar/ baz/ bop {color yellow} 417test clay-0006 {Leaves are replaced even if they look like a dict} { 418 dict get $foo bar baz bop 419} {color yellow} 420 421::clay::tree::dictset foo bar/ baz/ bang/ {color green flavor strawberry} 422test clay-0007a {Branches are merged} { 423 dict get $foo bar baz bang 424} {. {} color green flavor strawberry} 425 426::clay::tree::dictset foo bar/ baz/ bang/ color yellow 427test clay-0007b {Branches are merged} { 428 dict get $foo bar baz bang 429} {. {} color yellow flavor strawberry} 430 431::clay::tree::dictset foo bar/ baz/ bang/ {color blue} 432test clay-0007c {Branches are merged} { 433 dict get $foo bar baz bang 434} {. {} color blue flavor strawberry} 435 436::clay::tree::dictset foo bar/ baz/ bang/ shape: {Sort of round} 437test clay-0007d {Branches are merged} { 438 dict get $foo bar baz bang 439} {. {} color blue flavor strawberry shape: {Sort of round}} 440 441::clay::tree::dictset foo bar/ baz/ bang/ color yellow 442test clay-0007e {Branches are merged} { 443 dict get $foo bar baz bang 444} {. {} color yellow flavor strawberry shape: {Sort of round}} 445 446::clay::tree::dictset foo bar/ baz/ bang/ {color blue} 447test clay-0007f {Branches are merged} { 448 dict get $foo bar baz bang 449} {. {} color blue flavor strawberry shape: {Sort of round}} 450 451::clay::tree::dictset foo dict my_var 10 452::clay::tree::dictset foo dict my_other_var 9 453 454test clay-0007g {Branches are merged} { 455 dict get $foo dict 456} {. {} my_var 10 my_other_var 9} 457 458::clay::tree::dictset foo dict/ my_other_other_var 8 459test clay-0007h {Branches are merged} { 460 dict get $foo dict 461} {. {} my_var 10 my_other_var 9 my_other_other_var 8} 462 463 464::clay::tree::dictmerge foo {option/ {color {type color} flavor {sense taste}}} 465::clay::tree::dictmerge foo {option/ {format {default ascii}}} 466 467test clay-0008 {Whole dicts are merged} { 468 dict get $foo option color 469} {type color} 470test clay-0009 {Whole dicts are merged} { 471 dict get $foo option flavor 472} {sense taste} 473test clay-0010 {Whole dicts are merged} { 474 dict get $foo option format 475} {default ascii} 476 477### 478# Tests for the httpd module 479### 480test clay-0010 {Test that leaves are merged properly} 481set bar {} 482::clay::tree::dictmerge bar { 483 proxy/ {port 10101 host myhost.localhost} 484} 485::clay::tree::dictmerge bar { 486 mimetxt {Host: localhost 487Content_Type: text/plain 488Content-Length: 15 489} 490 http {HTTP_HOST {} CONTENT_LENGTH 15 HOST localhost CONTENT_TYPE text/plain UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e REMOTE_ADDR 127.0.0.1 REMOTE_HOST 127.0.0.1 REQUEST_METHOD POST REQUEST_URI /echo REQUEST_PATH echo REQUEST_VERSION 1.0 DOCUMENT_ROOT {} QUERY_STRING {} REQUEST_RAW {POST /echo HTTP/1.0} SERVER_PORT 10001 SERVER_NAME 127.0.0.1 SERVER_PROTOCOL HTTP/1.1 SERVER_SOFTWARE {TclHttpd 4.2.0} LOCALHOST 0} UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e uriinfo {fragment {} port {} path echo scheme http host {} query {} pbare 0 pwd {} user {}} 491 mixin {reply ::test::content.echo} 492 prefix /echo 493 proxy_port 10010 494 proxy/ {host localhost} 495} 496 497test clay-0011 {Whole dicts are merged} { 498 dict get $bar proxy_port 499} {10010} 500 501test clay-0012 {Whole dicts are merged} { 502 dict get $bar http CONTENT_LENGTH 503} 15 504test clay-0013 {Whole dicts are merged} { 505 dict get $bar proxy host 506} localhost 507test clay-0014 {Whole dicts are merged} { 508 dict get $bar proxy port 509} 10101 510} 511 512putb result { 513### 514# Dialect Testing 515### 516::clay::dialect::create ::alpha 517 518proc ::alpha::define::is_alpha {} { 519 dict set ::testinfo([current_class]) is_alpha 1 520} 521 522::alpha::define ::alpha::object { 523 is_alpha 524} 525 526::clay::dialect::create ::bravo ::alpha 527 528proc ::bravo::define::is_bravo {} { 529 dict set ::testinfo([current_class]) is_bravo 1 530} 531 532::bravo::define ::bravo::object { 533 is_bravo 534} 535 536::clay::dialect::create ::charlie ::bravo 537 538proc ::charlie::define::is_charlie {} { 539 dict set ::testinfo([current_class]) is_charlie 1 540} 541 542::charlie::define ::charlie::object { 543 is_charlie 544} 545 546::clay::dialect::create ::delta ::charlie 547 548proc ::delta::define::is_delta {} { 549 dict set ::testinfo([current_class]) is_delta 1 550} 551 552::delta::define ::delta::object { 553 is_delta 554} 555 556::delta::class create adam { 557 is_alpha 558 is_bravo 559 is_charlie 560 is_delta 561} 562 563test oodialect-keyword-001 {Testing keyword application} { 564 set ::testinfo(::adam) 565} {is_alpha 1 is_bravo 1 is_charlie 1 is_delta 1} 566 567test oodialect-keyword-002 {Testing keyword application} { 568 set ::testinfo(::alpha::object) 569} {is_alpha 1} 570 571test oodialect-keyword-003 {Testing keyword application} { 572 set ::testinfo(::bravo::object) 573} {is_bravo 1} 574 575test oodialect-keyword-004 {Testing keyword application} { 576 set ::testinfo(::charlie::object) 577} {is_charlie 1} 578 579test oodialect-keyword-005 {Testing keyword application} { 580 set ::testinfo(::delta::object) 581} {is_delta 1} 582 583### 584# Declare an object from a namespace 585### 586namespace eval ::test1 { 587 ::alpha::class create a { 588 aliases A 589 is_alpha 590 } 591 ::alpha::define b { 592 aliases B BEE 593 is_alpha 594 } 595 ::alpha::class create ::c { 596 aliases C 597 is_alpha 598 } 599 ::alpha::define ::d { 600 aliases D 601 is_alpha 602 } 603} 604 605test oodialect-naming-001 {Testing keyword application} { 606 set ::testinfo(::test1::a) 607} {is_alpha 1} 608 609test oodialect-naming-002 {Testing keyword application} { 610 set ::testinfo(::test1::b) 611} {is_alpha 1} 612 613test oodialect-naming-003 {Testing keyword application} { 614 set ::testinfo(::c) 615} {is_alpha 1} 616 617test oodialect-naming-004 {Testing keyword application} { 618 set ::testinfo(::d) 619} {is_alpha 1} 620 621test oodialect-aliasing-001 {Testing keyword application} { 622namespace eval ::test1 { 623 ::alpha::define e { 624 superclass A 625 } 626} 627} ::test1::e 628 629test oodialect-aliasing-002 {Testing keyword application} { 630namespace eval ::test1 { 631 ::bravo::define f { 632 superclass A 633 } 634} 635} ::test1::f 636 637 638test oodialect-aliasing-003 {Testing aliase method on class} { 639 ::test1::a aliases 640} {::test1::A} 641 642### 643# Test modified 2018-10-21 644### 645test oodialect-ancestry-003 {Testing heritage} { 646 ::clay::ancestors ::test1::f 647} {} 648 649### 650# Test modified 2018-10-21 651### 652test oodialect-ancestry-004 {Testing heritage} { 653 ::clay::ancestors ::alpha::object 654} {} 655 656### 657# Test modified 2018-10-21 658### 659test oodialect-ancestry-005 {Testing heritage} { 660 ::clay::ancestors ::delta::object 661} {} 662 663} 664 665putb result { 666# ------------------------------------------------------------------------- 667# clay submodule testing 668# ------------------------------------------------------------------------- 669 670} 671putb result { 672# Test canonical path building 673set path {const/ foo/ bar/ baz/} 674} 675set testnum 0 676foreach {pattern} { 677 {const foo bar baz} 678 {const/ foo/ bar/ baz} 679 {const/foo/bar/baz} 680 {const/foo bar/baz} 681 {const/foo/bar baz} 682 {const foo/bar/baz} 683 {const foo bar/baz} 684 {const/foo bar baz} 685} { 686 putb result [list %pattern% $pattern %testnum% [format %04d [incr testnum]]] { 687test oo-clay-path-%testnum% "Test path: %pattern%" { 688 ::clay::path %pattern% 689} $path 690} 691} 692putb result {set path {const/ foo/ bar/ baz/ bing}} 693set testnum 0 694foreach {pattern} { 695 {const foo bar baz bing} 696 {const/ foo/ bar/ baz/ bing} 697 {const/foo/bar/baz/bing} 698 {const/foo bar/baz/bing:} 699 {const/foo/bar baz bing} 700 {const/foo/bar baz bing:} 701 {const foo/bar/baz/bing} 702 {const foo bar/baz/bing} 703 {const/foo bar baz bing} 704} { 705 putb result [list %pattern% $pattern %testnum% [format %04d [incr testnum]]] { 706test oo-clay-leaf-%testnum% "Test leaf: %pattern%" { 707 ::clay::leaf %pattern% 708} $path 709} 710} 711 712putb result {namespace eval ::foo {}} 713 714set class-a ::foo::classa 715set commands-a { 716 clay set const color blue 717 clay set const/flavor strawberry 718 clay set {const/ sound} zoink 719 clay set info/ { 720 animal no 721 building no 722 subelement {pedantic yes} 723 } 724 725 # Provide a method that returns a constant so we can compare clay's inheritance to 726 # TclOO 727 method color {} { 728 return blue 729 } 730 method flavor {} { 731 return strawberry 732 } 733 method sound {} { 734 return zoink 735 } 736} 737set claydict-a { 738 const/ {color blue flavor strawberry sound zoink} 739 info/ { 740 animal no 741 building no 742 subelement {pedantic yes} 743 } 744} 745 746putb result [list %class% ${class-a} %commands% ${commands-a}] { 747clay::define %class% { 748%commands% 749} 750} 751 752set testnum 0 753foreach {top children} ${claydict-a} { 754 foreach {child value} $children { 755 set map {} 756 dict set map %class% ${class-a} 757 dict set map %top% $top 758 dict set map %child% $child 759 dict set map %value% $value 760 dict set map %testnum% [format %04d [incr testnum]] 761 putb result $map { 762test oo-class-clay-method-%testnum% "Test %class% %top% %child% exists" { 763 %class% clay exists %top% %child% 764} 1 765} 766 dict set map %test% [format %04d [incr testnum]] 767 putb result $map { 768test oo-class-clay-method-%testnum% "Test %class% %top% %child% value" { 769 %class% clay get %top% %child% 770} {%value%} 771} 772 } 773} 774 775 776set class-b ::foo::classb 777set claydict-b { 778 const/ {color black flavor vanilla feeling dread} 779 info/ {subelement {spoon yes}} 780} 781set commands-b {} 782foreach {top children} ${claydict-b} { 783 foreach {child value} $children { 784 putb commands-b " [list clay set $top $child $value]" 785 putb commands-b " [list method $child {} [list return $value]]" 786 } 787} 788putb result [list %class% ${class-b} %commands% ${commands-b}] { 789clay::define %class% { 790%commands% 791} 792} 793 794foreach {top children} ${claydict-b} { 795 foreach {child value} $children { 796 set map {} 797 dict set map %class% ${class-b} 798 dict set map %top% $top 799 dict set map %child% $child 800 dict set map %value% $value 801 dict set map %testnum% [format %04d [incr testnum]] 802 putb result $map { 803test oo-class-clay-method-%testnum% "Test %class% %top% %child% exists" { 804 %class% clay exists %top% %child% 805} 1 806} 807 dict set map %test% [format %04d [incr testnum]] 808 putb result $map { 809test oo-class-clay-method-%testnum% "Test %class% %top% %child% value" { 810 %class% clay get %top% %child% 811} {%value%} 812} 813 } 814} 815 816set commands-c {superclass ::foo::classb ::foo::classa} 817set class-c ::foo::class.ab 818putb result [list %class% ${class-c} %commands% ${commands-c}] { 819clay::define %class% { 820%commands% 821} 822} 823set commands-d {superclass ::foo::classa ::foo::classb} 824set class-d ::foo::class.ba 825putb result [list %class% ${class-d} %commands% ${commands-d}] { 826clay::define %class% { 827%commands% 828} 829} 830 831### 832# Tests for objects 833### 834 835putb result {# ------------------------------------------------------------------------- 836# Singleton 837::clay::define ::test::singletonbehavior { 838 method bar {} { 839 return CLASS 840 } 841 method booze {} { 842 return CLASS 843 } 844 Ensemble foo::bang {} { 845 return CLASS 846 } 847 Ensemble foo::both {} { 848 return CLASS 849 } 850 Ensemble foo::mixin {} { 851 return CLASS 852 } 853 Ensemble foo::sloppy {} { 854 return CLASS 855 } 856} 857::clay::define ::test::flavor.strawberry { 858 clay define property flavor strawbery 859 method bar {} { 860 return STRAWBERRY 861 } 862 Ensemble foo::bing {} { 863 return STRAWBERRY 864 } 865 Ensemble foo::both {} { 866 return STRAWBERRY 867 } 868 Ensemble foo::mixin {} { 869 return STRAWBERRY 870 } 871 Ensemble foo::sloppy {} { 872 return STRAWBERRY 873 } 874} 875::clay::singleton ::TEST { 876 class ::test::singletonbehavior 877 clay mixinmap flavor ::test::flavor.strawberry 878 clay set property color green 879 method bar {} { 880 return OBJECT 881 } 882 method booze {} { 883 return OBJECT 884 } 885 method baz {} { 886 return OBJECT 887 } 888 Ensemble foo::bar {} { 889 return OBJECT 890 } 891 Ensemble foo::both {} { 892 return OBJECT 893 } 894} 895 896test oo-object-singleton-001 {Test singleton superclass keyword} { 897 ::TEST clay delegate class 898} {::test::singletonbehavior} 899 900test oo-object-singleton-002 {Test singleton ensemble 1} { 901 ::TEST foo <list> 902} {bang bar bing both mixin sloppy} 903 904test oo-object-singleton-003 {Test singleton ensemble from script} { 905 ::TEST foo bar 906} {OBJECT} 907test oo-object-singleton-004 {Test singleton ensemble from mixin} { 908 ::TEST foo bing 909} {STRAWBERRY} 910test oo-object-singleton-005 {Test singleton ensemble from class} { 911 ::TEST foo bang 912} {CLASS} 913# Test note: the behavior from TclOO is unexpected 914# Intuitively, a local method should override a mixin 915# but this is not the case 916test oo-object-singleton-006 {Test singleton ensemble from conflict, should resolve to object} { 917 ::TEST foo both 918} {STRAWBERRY} 919test oo-object-singleton-007 {Test singleton ensemble from conflict, should resolve to mixin} { 920 ::TEST foo sloppy 921} {STRAWBERRY} 922### 923# Test note: 924# This should work but does not 925### 926#test oo-object-singleton-009 {Test property from mixin/class} { 927# ::TEST clay get property flavor 928#} {strawberry} 929test oo-object-singleton-008 {Test property from script} { 930 ::TEST clay get property color 931} {green} 932 933 934# Test note: the behavior from TclOO is unexpected 935# Intuitively, a local method should override a mixin 936# but this is not the case 937test oo-object-singleton-010 {Test method declared in script} { 938 ::TEST bar 939} {STRAWBERRY} 940 941test oo-object-singleton-011 {Test method declared in script} { 942 ::TEST booze 943} {OBJECT} 944TEST destroy 945 946# OBJECT of ::foo::classa 947set OBJECTA [::foo::classa new] 948 949### 950# Test object degation 951### 952proc ::foo::fakeobject {a b} { 953 return [expr {$a + $b}] 954} 955 956::clay::object create TEST 957TEST clay delegate funct ::foo::fakeobject 958test oo-object-delegate-001 {Test object delegation} { 959 ::TEST clay delegate 960} {<class> ::clay::object <funct> ::foo::fakeobject} 961 962test oo-object-delegate-002 {Test object delegation} { 963 ::TEST clay delegate funct 964} {::foo::fakeobject} 965 966test oo-object-delegate-002a {Test object delegation} { 967 ::TEST clay delegate <funct> 968} {::foo::fakeobject} 969 970test oo-object-delegate-003 {Test object delegation} { 971 ::TEST <funct> 1 1 972} {2} 973test oo-object-delegate-004 {Test object delegation} { 974 ::TEST <funct> 10 -7 975} {3} 976 977# Replace the function out from under 978proc ::foo::fakeobject {a b} { 979 return [expr {$a * $b}] 980} 981test oo-object-delegate-005 {Test object delegation} { 982 ::TEST <funct> 10 -7 983} {-70} 984 985# Object with ::foo::classa mixed in 986set MIXINA [::oo::object new] 987oo::objdefine $MIXINA mixin ::foo::classa 988} 989set matrix ${claydict-a} 990set testnum 0 991foreach {top children} $matrix { 992 foreach {child value} $children { 993 set map {} 994 dict set map %object1% OBJECTA 995 dict set map %object2% MIXINA 996 997 dict set map %top% $top 998 dict set map %child% $child 999 dict set map %value% $value 1000 dict set map %testnum% [format %04d [incr testnum]] 1001 putb result $map { 1002test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} { 1003 $%object1% clay get %top% %child% 1004} {%value%} 1005test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} { 1006 $%object2% clay get %top% %child% 1007} {%value%} 1008} 1009 if {$top eq "const/"} { 1010 putb result $map { 1011test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} { 1012 $%object1% %child% 1013} {%value%} 1014test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} { 1015 $%object2% %child% 1016} {%value%} 1017 } 1018 } 1019 } 1020} 1021 1022putb result {# ------------------------------------------------------------------------- 1023# OBJECT of ::foo::classb 1024set OBJECTB [::foo::classb new] 1025# Object with ::foo::classb mixed in 1026set MIXINB [::oo::object new] 1027oo::objdefine $MIXINB mixin ::foo::classb 1028} 1029set matrix ${claydict-b} 1030#set testnum 0 1031foreach {top children} $matrix { 1032 foreach {child value} $children { 1033 set map {} 1034 dict set map %object1% OBJECTB 1035 dict set map %object2% MIXINB 1036 1037 dict set map %top% $top 1038 dict set map %child% $child 1039 dict set map %value% $value 1040 dict set map %testnum% [format %04d [incr testnum]] 1041 putb result $map { 1042test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} { 1043 $%object1% clay get %top% %child% 1044} {%value%} 1045test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} { 1046 $%object2% clay get %top% %child% 1047} {%value%} 1048} 1049 if {$top eq "const/"} { 1050 putb result $map { 1051test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} { 1052 $%object1% %child% 1053} {%value%} 1054test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} { 1055 $%object2% %child% 1056} {%value%} 1057 } 1058 } 1059 } 1060} 1061 1062putb result {# ------------------------------------------------------------------------- 1063# OBJECT descended from ::foo::classa ::foo::classb 1064set OBJECTAB [::foo::class.ab new] 1065# Object where classes were mixed in ::foo::classa ::foo::classb 1066set MIXINAB [::oo::object new] 1067# Test modified 2018-10-30, mixin order was wrong before 1068oo::objdefine $MIXINAB mixin ::foo::classb ::foo::classa 1069} 1070set matrix ${claydict-b} 1071foreach {top children} ${claydict-a} { 1072 foreach {child value} $children { 1073 if {![dict exists $matrix $top $child]} { 1074 dict set matrix $top $child $value 1075 } 1076 } 1077} 1078#set testnum 0 1079foreach {top children} $matrix { 1080 foreach {child value} $children { 1081 set map {} 1082 dict set map %object1% OBJECTAB 1083 dict set map %object2% MIXINAB 1084 1085 dict set map %top% $top 1086 dict set map %child% $child 1087 dict set map %value% $value 1088 dict set map %testnum% [format %04d [incr testnum]] 1089 putb result $map { 1090test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} { 1091 $%object1% clay get %top% %child% 1092} {%value%} 1093test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} { 1094 $%object2% clay get %top% %child% 1095} {%value%} 1096} 1097 if {$top eq "const/"} { 1098 putb result $map { 1099test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} { 1100 $%object1% %child% 1101} {%value%} 1102test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} { 1103 $%object2% %child% 1104} {%value%} 1105 } 1106 } 1107 } 1108} 1109 1110putb result {# ------------------------------------------------------------------------- 1111# OBJECT descended from ::foo::classb ::foo::classa 1112set OBJECTBA [::foo::class.ba new] 1113# Object where classes were mixed in ::foo::classb ::foo::classa 1114set MIXINBA [::oo::object new] 1115# Test modified 2018-10-30, mixin order was wrong before 1116oo::objdefine $MIXINBA mixin ::foo::classa ::foo::classb 1117} 1118set matrix ${claydict-a} 1119foreach {top children} ${claydict-b} { 1120 foreach {child value} $children { 1121 if {![dict exists $matrix $top $child]} { 1122 dict set matrix $top $child $value 1123 } 1124 } 1125} 1126#set testnum 0 1127foreach {top children} $matrix { 1128 foreach {child value} $children { 1129 set map {} 1130 dict set map %object1% OBJECTBA 1131 dict set map %object2% MIXINBA 1132 1133 dict set map %top% $top 1134 dict set map %child% $child 1135 dict set map %value% $value 1136 dict set map %testnum% [format %04d [incr testnum]] 1137 putb result $map { 1138test oo-object-clay-method-native-%testnum% {Test native object gets the property} { 1139 $%object1% clay get %top% %child% 1140} {%value%} 1141test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property} { 1142 $%object2% clay get %top% %child% 1143} {%value%} 1144} 1145 1146 if {$top eq "const/"} { 1147 putb result $map { 1148test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} { 1149 $%object1% %child% 1150} {%value%} 1151test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} { 1152 $%object2% %child% 1153} {%value%} 1154 } 1155 } 1156 } 1157} 1158 1159putb resut { 1160### 1161# Test local setting if clay data in an object 1162### 1163set OBJECT [::foo::classa new] 1164test oo-object-clay-method-local-0001 {Test native object gets the property} { 1165 $OBJECT clay get const/ color 1166} {blue} 1167test oo-object-clay-method-local-0002 {Test that local settings override the inherited properties} { 1168 $OBJECT clay set const/ color black 1169 $OBJECT clay set const/ 1170} {black} 1171 1172test oo-object-clay-method-local-0003 {Test native object gets an empty property} { 1173 $OBJECT clay get color 1174} {} 1175test oo-object-clay-method-local-0004 {Test that local settings override the empty property} { 1176 $OBJECT clay set color orange 1177 $OBJECT clay get color 1178} {orange} 1179 1180} 1181 1182putb result { 1183### 1184# put a do-nothing constructor on the books 1185### 1186::clay::define ::clay::object { 1187 constructor args {} 1188} 1189 1190oo::objdefine ::clay::object method foo args { return bar } 1191 1192test clay-core-method-0001 {Test that adding methods to the core ::clay::object class works} { 1193 ::clay::object foo 1194} {bar} 1195 1196namespace eval ::TEST {} 1197::clay::define ::TEST::myclass { 1198 clay color red 1199 clay flavor strawberry 1200 1201} 1202 1203### 1204# Test adding a clay property 1205### 1206test clay-class-clay-0001 {Test that a clay statement is recorded in the object of the class} { 1207 ::TEST::myclass clay get color 1208} red 1209test clay-class-clay-0002 {Test that a clay statement is recorded in the object of the class} { 1210 ::TEST::myclass clay get flavor 1211} strawberry 1212 1213### 1214# Test that objects of the class get the same properties 1215### 1216set OBJ [::clay::object new {}] 1217set OBJ2 [::TEST::myclass new {}] 1218 1219test clay-object-clay-a-0001 {Test that objects not thee class do not get properties} { 1220 $OBJ clay get color 1221} {} 1222test clay-object-clay-a-0002 {Test that objects not thee class do not get properties} { 1223 $OBJ clay get flavor 1224} {} 1225test clay-object-clay-a-0003 {Test that objects of the class get properties} { 1226 $OBJ2 clay get color 1227} red 1228test clay-object-clay-a-0004 {Test that objects of the class get properties} { 1229 $OBJ2 clay get flavor 1230} strawberry 1231 1232### 1233# Test modified 2018-10-21 1234### 1235test clay-object-clay-a-0005 {Test the clay ancestors function} { 1236 $OBJ clay ancestors 1237} {::clay::object} 1238 1239### 1240# Test modified 2018-10-21 1241### 1242test clay-object-clay-a-0006 {Test the clay ancestors function} { 1243 $OBJ2 clay ancestors 1244} {::TEST::myclass ::clay::object} 1245 1246test clay-object-clay-a-0007 {Test the clay provenance function} { 1247 $OBJ2 clay provenance flavor 1248} ::TEST::myclass 1249 1250### 1251# Test that object local setting override the class 1252### 1253test clay-object-clay-a-0008 {Test that object local setting override the class} { 1254 $OBJ2 clay set color purple 1255 $OBJ2 clay get color 1256} purple 1257test clay-object-clay-a-0009 {Test that object local setting override the class} { 1258 $OBJ2 clay provenance color 1259} self 1260 1261::clay::define ::TEST::myclasse { 1262 superclass ::TEST::myclass 1263 1264 clay color blue 1265 method do args { 1266 return "I did $args" 1267 } 1268 1269 Ensemble which::color {} { 1270 return [my clay get color] 1271 } 1272 clay set method_ensemble which farbe: {tailcall my Which_color {*}$args} 1273} 1274 1275### 1276# Test clay information is passed town to subclasses 1277### 1278test clay-class-clay-0003 {Test that a clay statement is recorded in the object of the class} { 1279 ::TEST::myclasse clay get color 1280} blue 1281test clay-class-clay-0004 {Test that clay statements from the ancestors of this class are not present (we handle them seperately in objects)} { 1282 ::TEST::myclasse clay get flavor 1283} {} 1284test clay-class-clay-0005 {Test that clay statements from the ancestors of this class are found with the FIND method} { 1285 ::TEST::myclasse clay find flavor 1286} {strawberry} 1287 1288### 1289# Test that properties reach objects 1290### 1291set OBJ3 [::TEST::myclasse new {}] 1292test clay-object-clay-b-0001 {Test that objects of the class get properties} { 1293 $OBJ3 clay get color 1294} blue 1295test clay-object-clay-b-0002 {Test the clay provenance function} { 1296 $OBJ3 clay provenance color 1297} ::TEST::myclasse 1298test clay-object-clay-b-0003 {Test that objects of the class get properties} { 1299 $OBJ3 clay get flavor 1300} strawberry 1301test clay-object-clay-b-0004 {Test the clay provenance function} { 1302 $OBJ3 clay provenance flavor 1303} ::TEST::myclass 1304 1305### 1306# Test modified 2018-10-21 1307### 1308test clay-object-clay-b-0005 {Test the clay provenance function} { 1309 $OBJ3 clay ancestors 1310} {::TEST::myclasse ::TEST::myclass ::clay::object} 1311 1312### 1313# Test defining a standard method 1314### 1315test clay-object-method-0001 {Test and standard method} { 1316 $OBJ3 do this really cool thing 1317} {I did this really cool thing} 1318 1319test clay-object-method-0003 {Test an ensemble} { 1320 $OBJ3 which color 1321} blue 1322# Test setting properties 1323test clay-object-method-0004 {Test an ensemble} { 1324 $OBJ3 clay set color black 1325 $OBJ3 which color 1326} black 1327 1328# Test setting properties 1329test clay-object-method-0004 {Test an ensemble alias} { 1330 $OBJ3 which farbe 1331} black 1332 1333 1334### 1335# Added 2019-06-24 1336# Test that grabbing a leaf does not pollute the cache 1337### 1338::clay::define ::TEST::class_with_deep_tree { 1339 clay set tree deep has depth 1 1340 clay set tree shallow has depth 0 1341} 1342 1343$OBJ3 clay mixinmap deep ::TEST::class_with_deep_tree 1344 1345test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} { 1346 $OBJ3 clay get tree shallow has depth 1347} 0 1348test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} { 1349 $OBJ3 clay get tree 1350} {deep {has {depth 1}} shallow {has {depth 0}}} 1351 1352 1353 1354### 1355# Test that if you try to replace a global command you get an error 1356### 1357test clay-nspace-0001 {Test that if you try to replace a global command you get an error} -body { 1358::clay::define open { 1359 method bar {} { return foo } 1360 1361} 1362} -returnCodes {error} -result "::open does not refer to an object" 1363 1364::clay::define fubar { 1365 method bar {} { return foo } 1366} 1367test clay-nspace-0002 {Test a non qualified class ends up in the current namespace} { 1368 info commands ::fubar 1369} {::fubar} 1370 1371namespace eval ::cluster { 1372::clay::define fubar { 1373 method bar {} { return foo } 1374} 1375 1376::clay::define ::clay::pot { 1377 method bar {} { return foo } 1378} 1379 1380} 1381test clay-nspace-0003 {Test a non qualified class ends up in the current namespace} { 1382 info commands ::cluster::fubar 1383} {::cluster::fubar} 1384test clay-nspace-0003 {Test a fully qualified class ends up in the proper namespace} { 1385 info commands ::clay::pot 1386} {::clay::pot} 1387 1388#set ::clay::trace 3 1389 1390### 1391# New test - Added 2019-09-15 1392# Test that the "method" variable is exposed to a default method 1393### 1394 1395::clay::define ::ensembleWithDefault { 1396 Ensemble foo::bar {} { return A } 1397 Ensemble foo::baz {} { return B } 1398 Ensemble foo::bang {} { return C } 1399 1400 Ensemble foo::default {} { return $method } 1401} 1402 1403 1404set OBJ [::ensembleWithDefault new] 1405test clay-ensemble-default-0001 {Test a normal ensemble method} { 1406 $OBJ foo bar 1407} {A} 1408test clay-ensemble-default-0002 {Test a normal ensemble method} { 1409 $OBJ foo baz 1410} {B} 1411test clay-ensemble-default-0003 {Test a normal ensemble method} { 1412 $OBJ foo <list> 1413} [lsort -dictionary {bar baz bang}] 1414 1415test clay-ensemble-default-0004 {Test a normal ensemble method} { 1416 $OBJ foo bing 1417} {bing} 1418test clay-ensemble-default-0005 {Test a normal ensemble method} { 1419 $OBJ foo bong 1420} {bong} 1421### 1422# Mixin tests 1423### 1424 1425### 1426# Define a core class 1427### 1428::clay::define ::TEST::thing { 1429 1430 method do args { 1431 return "I did $args" 1432 } 1433} 1434 1435 1436::clay::define ::TEST::vegetable { 1437 1438 clay color unknown 1439 clay flavor unknown 1440 1441 Ensemble which::flavor {} { 1442 return [my clay get flavor] 1443 } 1444 Ensemble which::color {} { 1445 return [my clay get color] 1446 } 1447 1448} 1449 1450::clay::define ::TEST::animal { 1451 1452 clay color unknown 1453 clay sound unknown 1454 1455 Ensemble which::sound {} { 1456 return [my clay get sound] 1457 } 1458 Ensemble which::color {} { 1459 return [my clay get color] 1460 } 1461 method sound {} { 1462 return unknown 1463 } 1464} 1465 1466::clay::define ::TEST::species.cat { 1467 superclass ::TEST::animal 1468 clay sound meow 1469 method sound {} { 1470 return meow 1471 } 1472} 1473 1474::clay::define ::TEST::coloring.calico { 1475 clay color calico 1476 1477} 1478 1479::clay::define ::TEST::condition.dark { 1480 Ensemble which::color {} { 1481 return grey 1482 } 1483} 1484 1485::clay::define ::TEST::mood.happy { 1486 Ensemble which::sound {} { 1487 return purr 1488 } 1489 method sound {} { 1490 return purr 1491 } 1492} 1493test clay-object-0001 {Test than an object is created when clay::define is invoked} { 1494 info commands ::TEST::mood.happy 1495} ::TEST::mood.happy 1496 1497set OBJ [::TEST::thing new] 1498test clay-mixin-a-0001 {Test that prior to a mixin an ensemble doesn't exist} -body { 1499 $OBJ which color 1500} -returnCodes error -result {unknown method "which": must be clay, destroy or do} 1501 1502test clay-mixin-a-0002 {Test and standard method from an ancestor} { 1503 $OBJ do this really cool thing 1504} {I did this really cool thing} 1505 1506$OBJ clay mixinmap species ::TEST::animal 1507test clay-mixin-b-0001 {Test that an ensemble is created during a mixin} { 1508 $OBJ which color 1509} {unknown} 1510 1511test clay-mixin-b-0002 {Test that an ensemble is created during a mixin} { 1512 $OBJ which sound 1513} {unknown} 1514 1515test clay-mixin-b-0003 {Test that an ensemble is created during a mixin} \ 1516 -body {$OBJ which flavor} -returnCodes {error} \ 1517 -result {unknown method which flavor. Valid: color sound} 1518 1519### 1520# Test Modified: 2018-10-21 1521### 1522test clay-mixin-b-0004 {Test that mixins resolve in the correct order} { 1523 $OBJ clay ancestors 1524} {::TEST::animal ::TEST::thing ::clay::object} 1525 1526### 1527# Replacing a mixin replaces the behaviors 1528### 1529$OBJ clay mixinmap species ::TEST::vegetable 1530test clay-mixin-c-0001 {Test that an ensemble is created during a mixin} { 1531 $OBJ which color 1532} {unknown} 1533test clay-mixin-c-0002 {Test that an ensemble is created during a mixin} \ 1534 -body {$OBJ which sound} \ 1535 -returnCodes {error} \ 1536 -result {unknown method which sound. Valid: color flavor} 1537test clay-mixin-c-0003 {Test that an ensemble is created during a mixin} { 1538 $OBJ which flavor 1539} {unknown} 1540### 1541# Test Modified: 2018-10-21 1542### 1543test clay-mixin-c-0004 {Test that mixins resolve in the correct order} { 1544 $OBJ clay ancestors 1545} {::TEST::vegetable ::TEST::thing ::clay::object} 1546 1547### 1548# Replacing a mixin 1549$OBJ clay mixinmap species ::TEST::species.cat 1550test clay-mixin-e-0001 {Test that an ensemble is created during a mixin} { 1551 $OBJ which color 1552} {unknown} 1553test clay-mixin-e-0002a {Test that an ensemble is created during a mixin} { 1554 $OBJ sound 1555} {meow} 1556test clay-mixin-e-0002b {Test that an ensemble is created during a mixin} { 1557 $OBJ clay get sound 1558} {meow} 1559test clay-mixin-e-0002 {Test that an ensemble is created during a mixin} { 1560 $OBJ which sound 1561} {meow} 1562test clay-mixin-e-0003 {Test that an ensemble is created during a mixin} \ 1563 -body {$OBJ which flavor} -returnCodes {error} \ 1564 -result {unknown method which flavor. Valid: color sound} 1565### 1566# Test Modified: 2018-10-30, 2018-10-21, 2018-10-10 1567### 1568test clay-mixin-e-0004 {Test that clay data follows the rules of inheritence and order of mixin} { 1569 $OBJ clay ancestors 1570} {::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object} 1571 1572$OBJ clay mixinmap coloring ::TEST::coloring.calico 1573test clay-mixin-f-0001 {Test that an ensemble is created during a mixin} { 1574 $OBJ which color 1575} {calico} 1576test clay-mixin-f-0002 {Test that an ensemble is created during a mixin} { 1577 $OBJ which sound 1578} {meow} 1579test clay-mixin-f-0003 {Test that an ensemble is created during a mixin} \ 1580 -body {$OBJ which flavor} -returnCodes {error} \ 1581 -result {unknown method which flavor. Valid: color sound} 1582 1583### 1584# Test modified 2018-10-30, 2018-10-21, 2018-10-10 1585### 1586test clay-mixin-f-0004 {Test that clay data follows the rules of inheritence and order of mixin} { 1587 $OBJ clay ancestors 1588} {::TEST::coloring.calico ::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object} 1589 1590test clay-mixin-f-0005 {Test that clay data from a mixin works} { 1591 $OBJ clay provenance color 1592} {::TEST::coloring.calico} 1593 1594### 1595# Test variable initialization 1596### 1597::clay::define ::TEST::has_var { 1598 Variable my_variable 10 1599 1600 method get_my_variable {} { 1601 my variable my_variable 1602 return $my_variable 1603 } 1604} 1605 1606set OBJ [::TEST::has_var new] 1607test clay-class-variable-0001 {Test that the parser injected the right value in the right place for clay to catch it} { 1608 $OBJ clay get variable/ my_variable 1609} {10} 1610 1611# Modified 2018-10-30 (order is different) 1612test clay-class-variable-0002 {Test that the parser injected the right value in the right place for clay to catch it} { 1613 $OBJ clay get variable 1614} {my_variable 10 DestroyEvent 0} 1615 1616# Modified 2018-10-30 (order is different) 1617test clay-class-variable-0003 {Test that the parser injected the right value in the right place for clay to catch it} { 1618 $OBJ clay dget variable 1619} {. {} my_variable 10 DestroyEvent 0} 1620 1621test clay-class-variable-0004 {Test that variables declared in the class definition are initialized} { 1622 $OBJ get_my_variable 1623} 10 1624 1625### 1626# Test array initialization 1627### 1628::clay::define ::TEST::has_array { 1629 Array my_array {timeout 10} 1630 1631 method get_my_array {field} { 1632 my variable my_array 1633 return $my_array($field) 1634 } 1635} 1636 1637set OBJ [::TEST::has_array new] 1638test clay-class-array-0001 {Test that the parser injected the right value in the right place for clay to catch it} { 1639 $OBJ clay get array 1640} {my_array {timeout 10}} 1641 1642test clay-class-array-0002 {Test that the parser injected the right value in the right place for clay to catch it} { 1643 $OBJ clay dget array 1644} {. {} my_array {. {} timeout 10}} 1645 1646test clay-class-array-0003 {Test that variables declared in the class definition are initialized} { 1647 $OBJ get_my_array timeout 1648} 10 1649 1650::clay::define ::TEST::has_more_array { 1651 superclass ::TEST::has_array 1652 Array my_array {color blue} 1653} 1654test clay-class-array-0008 {Test that the parser injected the right value in the right place for clay to catch it} { 1655 ::TEST::has_more_array clay get array 1656} {my_array {color blue}} 1657 1658test clay-class-array-0009 {Test that the parser injected the right value in the right place for clay to catch it} { 1659 ::TEST::has_more_array clay find array 1660} {my_array {timeout 10 color blue}} 1661 1662# Modified 2018-10-30 (order is different) 1663set BOBJ [::TEST::has_more_array new] 1664test clay-class-array-0004 {Test that the parser injected the right value in the right place for clay to catch it} { 1665 $BOBJ clay get array 1666} {my_array {color blue timeout 10}} 1667 1668# Modified 2018-10-30 (order is different) 1669test clay-class-array-0005 {Test that the parser injected the right value in the right place for clay to catch it} { 1670 $BOBJ clay dget array 1671} {. {} my_array {. {} color blue timeout 10}} 1672 1673test clay-class-arrau-0006 {Test that variables declared in the class definition are initialized} { 1674 $BOBJ get_my_array timeout 1675} 10 1676test clay-class-arrau-0007 {Test that variables declared in the class definition are initialized} { 1677 $BOBJ get_my_array color 1678} blue 1679 1680::clay::define ::TEST::has_empty_array { 1681 Array my_array {} 1682 1683 method my_array_exists {} { 1684 my variable my_array 1685 return [info exists my_array] 1686 } 1687 method get {field} { 1688 my variable my_array 1689 return $my_array($field) 1690 } 1691 method set {field value} { 1692 my variable my_array 1693 set my_array($field) $value 1694 } 1695} 1696 1697test clay-class-array-0008 {Test that an declaration of an array with no values produces and empty array} { 1698 set COBJ [::TEST::has_empty_array new] 1699 $COBJ my_array_exists 1700} 1 1701 1702test clay-class-array-0009 {Test that an declaration of an array with no values produces and empty array} { 1703 $COBJ set test "A random value" 1704 $COBJ get test 1705} {A random value} 1706### 1707# Test dict initialization 1708### 1709::clay::define ::TEST::has_dict { 1710 Dict my_dict {timeout 10} 1711 1712 method get_my_dict {args} { 1713 my variable my_dict 1714 if {[llength $args]==0} { 1715 return $my_dict 1716 } 1717 return [dict get $my_dict {*}$args] 1718 } 1719 1720} 1721 1722set OBJ [::TEST::has_dict new] 1723test clay-class-dict-0001 {Test that the parser injected the right value in the right place for clay to catch it} { 1724 $OBJ clay get dict 1725} {my_dict {timeout 10}} 1726 1727test clay-class-dict-0002 {Test that the parser injected the right value in the right place for clay to catch it} { 1728 $OBJ clay dget dict 1729} {. {} my_dict {. {} timeout 10}} 1730 1731test clay-class-dict-0003 {Test that variables declared in the class definition are initialized} { 1732 $OBJ get_my_dict timeout 1733} 10 1734 1735test clay-class-dict-0004 {Test that an empty dict is annotated} { 1736 $OBJ clay get dict 1737} {my_dict {timeout 10}} 1738 1739 1740::clay::define ::TEST::has_more_dict { 1741 superclass ::TEST::has_dict 1742 Dict my_dict {color blue} 1743} 1744set BOBJ [::TEST::has_more_dict new] 1745 1746# Modified 2018-10-30 1747test clay-class-dict-0004 {Test that the parser injected the right value in the right place for clay to catch it} { 1748 $BOBJ clay get dict 1749} {my_dict {color blue timeout 10}} 1750 1751# Modified 2018-10-30 1752test clay-class-dict-0005 {Test that the parser injected the right value in the right place for clay to catch it} { 1753 $BOBJ clay dget dict 1754} {. {} my_dict {. {} color blue timeout 10}} 1755 1756test clay-class-dict-0006 {Test that variables declared in the class definition are initialized} { 1757 $BOBJ get_my_dict timeout 1758} 10 1759 1760test clay-class-dict-0007 {Test that variables declared in the class definition are initialized} { 1761 $BOBJ get_my_dict color 1762} blue 1763 1764::clay::define ::TEST::has_empty_dict { 1765 Dict my_empty_dict {} 1766 1767 method get_my_empty_dict {args} { 1768 my variable my_empty_dict 1769 if {[llength $args]==0} { 1770 return $my_empty_dict 1771 } 1772 return [dict get $my_empty_dict {*}$args] 1773 } 1774} 1775 1776set COBJ [::TEST::has_empty_dict new] 1777 1778test clay-class-dict-0008 {Test that the parser injected the right value in the right place for clay to catch it} { 1779 $COBJ clay dget dict 1780} {my_empty_dict {. {}}} 1781 1782test clay-class-dict-0009 {Test that an empty dict is initialized} { 1783 $COBJ get_my_empty_dict 1784} {} 1785 1786### 1787# Test object delegation 1788### 1789::clay::define ::TEST::organelle { 1790 method add args { 1791 set total 0 1792 foreach item $args { 1793 set total [expr {$total+$item}] 1794 } 1795 return $total 1796 } 1797} 1798::clay::define ::TEST::master { 1799 constructor {} { 1800 set mysub [namespace current]::sub 1801 ::TEST::organelle create $mysub 1802 my clay delegate sub $mysub 1803 } 1804} 1805 1806set OBJ [::TEST::master new] 1807### 1808# Test that delegation is working 1809### 1810test clay-delegation-0001 {Test an array driven ensemble} { 1811 $OBJ <sub> add 5 5 1812} 10 1813 1814 1815### 1816# Test the Ensemble keyword 1817### 1818::clay::define ::TEST::with_ensemble { 1819 1820 Ensemble myensemble {pattern args} { 1821 set ensemble [self method] 1822 set emap [my clay ensemble_map $ensemble] 1823 set mlist [dict keys $emap [string tolower $pattern]] 1824 if {[llength $mlist] != 1} { 1825 error "Couldn't figure out what to do with $pattern" 1826 } 1827 set method [lindex $mlist 0] 1828 set argspec [dict get $emap $method argspec] 1829 set body [dict get $emap $method body] 1830 if {$argspec ni {args {}}} { 1831 ::clay::dynamic_arguments $ensemble $method [list $argspec] {*}$args 1832 } 1833 eval $body 1834 } 1835 1836 Ensemble myensemble::go args { 1837 return 1 1838 } 1839} 1840 1841::clay::define ::TEST::with_ensemble.dance { 1842 Ensemble myensemble::dance args { 1843 return 1 1844 } 1845} 1846::clay::define ::TEST::with_ensemble.cannot_dance { 1847 Ensemble myensemble::dance args { 1848 return 0 1849 } 1850} 1851 1852set OBJA [::clay::object new] 1853set OBJB [::clay::object new] 1854 1855$OBJA clay mixinmap \ 1856 core ::TEST::with_ensemble \ 1857 friends ::TEST::with_ensemble.dance 1858 1859$OBJB clay mixinmap \ 1860 core ::TEST::with_ensemble \ 1861 friends ::TEST::with_ensemble.cannot_dance 1862} 1863 1864set testnum 0 1865 1866set matrix { 1867 go { 1868 OBJA 1 1869 OBJB 1 1870 } 1871 dance { 1872 OBJA 1 1873 OBJB 0 1874 } 1875} 1876foreach {action output} $matrix { 1877 putb result "# Test $action" 1878 foreach {object value} $output { 1879 set map [dict create %object% $object %action% $action %value% $value] 1880 dict set map %testnum% [format %04d [incr testnum]] 1881 putb result $map {test clay-dynamic-ensemble-%testnum% {Test ensemble with static method} { 1882 $%object% myensemble %action% 1883} {%value%}} 1884 } 1885} 1886 1887putb result { 1888 1889### 1890# Class method testing 1891### 1892 1893clay::class create WidgetClass { 1894 Class_Method working {} { 1895 return {Works} 1896 } 1897 1898 Class_Method unknown args { 1899 set tkpath [lindex $args 0] 1900 if {[string index $tkpath 0] eq "."} { 1901 set obj [my new $tkpath {*}[lrange $args 1 end]] 1902 $obj tkalias $tkpath 1903 return $tkpath 1904 } 1905 next {*}$args 1906 } 1907 1908 constructor {TkPath args} { 1909 my variable hull 1910 set hull $TkPath 1911 my clay delegate hull $TkPath 1912 } 1913 1914 method tkalias tkname { 1915 set oldname $tkname 1916 my variable tkalias 1917 set tkalias $tkname 1918 set self [self] 1919 set hullwidget [::info object namespace $self]::tkwidget 1920 my clay delegate tkwidget $hullwidget 1921 #rename ::$tkalias $hullwidget 1922 my clay delegate hullwidget $hullwidget 1923 #::tool::object_rename [self] ::$tkalias 1924 rename [self] ::$tkalias 1925 #my Hull_Bind $tkname 1926 return $hullwidget 1927 } 1928} 1929 1930test tool-class-method-000 {Test that class methods actually work...} { 1931 WidgetClass working 1932} {Works} 1933 1934test tool-class-method-001 {Test Tk style creator} { 1935 WidgetClass .foo 1936 .foo clay delegate hull 1937} {.foo} 1938 1939::clay::define WidgetNewClass { 1940 superclass WidgetClass 1941} 1942 1943test tool-class-method-002 {Test Tk style creator inherited by morph} { 1944 WidgetNewClass .bar 1945 .bar clay delegate hull 1946} {.bar} 1947 1948 1949 1950### 1951# Test ensemble inheritence 1952### 1953clay::define NestedClassA { 1954 Ensemble do::family {} { 1955 return NestedClassA 1956 } 1957 Ensemble do::something {} { 1958 return A 1959 } 1960 Ensemble do::whop {} { 1961 return A 1962 } 1963} 1964clay::define NestedClassB { 1965 superclass NestedClassA 1966 Ensemble do::family {} { 1967 set r [next family] 1968 lappend r NestedClassB 1969 return $r 1970 } 1971 Ensemble do::whop {} { 1972 return B 1973 } 1974} 1975clay::define NestedClassC { 1976 superclass NestedClassB 1977 1978 Ensemble do::somethingelse {} { 1979 return C 1980 } 1981} 1982clay::define NestedClassD { 1983 superclass NestedClassB 1984 1985 Ensemble do::somethingelse {} { 1986 return D 1987 } 1988} 1989 1990clay::define NestedClassE { 1991 superclass NestedClassD NestedClassC 1992} 1993 1994clay::define NestedClassF { 1995 superclass NestedClassC NestedClassD 1996} 1997 1998NestedClassC create NestedObjectC 1999 2000### 2001# These tests no longer work because method ensembles are now dynamically 2002# generated by object, that are not attached to the class anymore 2003# 2004#### 2005#test tool-ensemble-001 {Test that an ensemble can access [next] even if no object of the ancestor class have been instantiated} { 2006# NestedObjectC do family 2007#} {::NestedClassA ::NestedClassB ::NestedClassC} 2008 2009test tool-ensemble-002 {Test that a later ensemble definition trumps a more primitive one} { 2010 NestedObjectC do whop 2011} {B} 2012test tool-ensemble-003 {Test that an ensemble definitions in an ancestor carry over} { 2013 NestedObjectC do something 2014} {A} 2015 2016NestedClassE create NestedObjectE 2017NestedClassF create NestedObjectF 2018 2019 2020test tool-ensemble-004 {Test that ensembles follow the same rules for inheritance as methods} { 2021 NestedObjectE do somethingelse 2022} {D} 2023 2024test tool-ensemble-005 {Test that ensembles follow the same rules for inheritance as methods} { 2025 NestedObjectF do somethingelse 2026} {C} 2027 2028### 2029# Set of tests to exercise the mixinmap system 2030### 2031clay::define MixinMainClass { 2032 Variable mainvar unchanged 2033 2034 Ensemble test::which {} { 2035 my variable mainvar 2036 return $mainvar 2037 } 2038 2039 Ensemble test::main args { 2040 puts [list this is main $method $args] 2041 } 2042 2043} 2044 2045set mixoutscript {my test untool $class} 2046set mixinscript {my test tool $class} 2047clay::define MixinTool { 2048 Variable toolvar unchanged.mixin 2049 clay set mixin/ unmap-script $mixoutscript 2050 clay set mixin/ map-script $mixinscript 2051 clay set mixin/ name {Generic Tool} 2052 2053 Ensemble test::untool class { 2054 my variable toolvar mainvar 2055 set mainvar {} 2056 set toolvar {} 2057 } 2058 2059 Ensemble test::tool class { 2060 my variable toolvar mainvar 2061 set mainvar [$class clay get mixin name] 2062 set toolvar [$class clay get mixin name] 2063 } 2064} 2065 2066clay::define MixinToolA { 2067 superclass MixinTool 2068 2069 clay set mixin/ name {Tool A} 2070} 2071 2072clay::define MixinToolB { 2073 superclass MixinTool 2074 2075 clay set mixin/ name {Tool B} 2076 2077 method test_newfunc {} { 2078 return "B" 2079 } 2080} 2081 2082test tool-mixinspec-001 {Test application of mixin specs} { 2083 MixinTool clay get mixin map-script 2084} $mixinscript 2085 2086test tool-mixinspec-002 {Test application of mixin specs} { 2087 MixinToolA clay get mixin map-script 2088} {} 2089 2090test tool-mixinspec-003 {Test application of mixin specs} { 2091 MixinToolA clay find mixin map-script 2092} $mixinscript 2093 2094test tool-mixinspec-004 {Test application of mixin specs} { 2095 MixinToolB clay find mixin map-script 2096} $mixinscript 2097 2098 2099MixinMainClass create mixintest 2100 2101test tool-mixinmap-001 {Test object prior to mixins} { 2102 mixintest test which 2103} {unchanged} 2104 2105mixintest clay mixinmap tool MixinToolA 2106test tool-mixinmap-002 {Test mixin map script ran} { 2107 mixintest test which 2108} {Tool A} 2109 2110mixintest clay mixinmap tool MixinToolB 2111 2112test tool-mixinmap-003 {Test mixin map script ran} { 2113 mixintest test which 2114} {Tool B} 2115 2116test tool-mixinmap-003 {Test mixin map script ran} { 2117 mixintest test_newfunc 2118} {B} 2119 2120mixintest clay mixinmap tool {} 2121test tool-mixinmap-004 {Test object prior to mixins} { 2122 mixintest test which 2123} {} 2124} 2125 2126### 2127# Test clay mixinslots 2128### 2129putb result { 2130 2131clay::define ::clay::object { 2132 method path {} { 2133 return [self class] 2134 } 2135} 2136 2137 2138clay::define ::MixinRoot { 2139 clay set opts core root 2140 clay set opts option unset 2141 clay set opts color unset 2142 2143 Ensemble info::root {} { 2144 return MixinRoot 2145 } 2146 Ensemble info::shade {} { 2147 return avacodo 2148 } 2149 Ensemble info::default {} { 2150 return Undefined 2151 } 2152 2153 method did {} { 2154 return MixinRoot 2155 } 2156 2157 method path {} { 2158 return [list [self class] {*}[next]] 2159 } 2160} 2161 2162clay::define ::MixinOption1 { 2163 clay set opts option option1 2164 2165 Ensemble info::option {} { 2166 return MixinOption1 2167 } 2168 Ensemble info::other {} { 2169 return MixinOption1 2170 } 2171 2172 method did {} { 2173 return MixinOption1 2174 } 2175 2176 method path {} { 2177 return [list [self class] {*}[next]] 2178 } 2179} 2180 2181clay::define ::MixinOption2 { 2182 superclass ::MixinOption1 2183 2184 clay set opts option option2 2185 2186 Ensemble info::option {} { 2187 return MixinOption2 2188 } 2189 2190 method did {} { 2191 return MixinOption2 2192 } 2193 2194 method path {} { 2195 return [list [self class] {*}[next]] 2196 } 2197} 2198 2199 2200clay::define ::MixinColor1 { 2201 clay set opts color blue 2202 2203 Ensemble info::color {} { 2204 return MixinColor1 2205 } 2206 Ensemble info::shade {} { 2207 return blue 2208 } 2209 2210 method did {} { 2211 return MixinColor1 2212 } 2213 2214 method path {} { 2215 return [list [self class] {*}[next]] 2216 } 2217} 2218 2219clay::define ::MixinColor2 { 2220 clay set opts color green 2221 2222 Ensemble info::color {} { 2223 return MixinColor2 2224 } 2225 Ensemble info::shade {} { 2226 return green 2227 } 2228 2229 method did {} { 2230 return MixinColor2 2231 } 2232 2233 method path {} { 2234 return [list [self class] {*}[next]] 2235 } 2236} 2237 2238set obj [clay::object new] 2239 2240$obj clay mixinmap root ::MixinRoot 2241} 2242set testnum 0 2243set batnum 0 2244 2245set obj {$obj} 2246set template { 2247test tool-prototype-%battery%-%test% {%comment%} { 2248 %obj% %method% 2249} {%answer%} 2250} 2251set map {} 2252 2253dict set map %obj% {$obj} 2254dict set map %battery% [format %04d [incr batnum]] 2255dict set map %comment% {Mixin core} 2256 2257foreach {method answer} { 2258 {info root} {MixinRoot} 2259 {info option} {Undefined} 2260 {info color} {Undefined} 2261 {info other} {Undefined} 2262 {info shade} {avacodo} 2263 {did} {MixinRoot} 2264 {path} {::MixinRoot ::clay::object} 2265 {clay get opts} {core root option unset color unset} 2266 {clay get opts core} root 2267 {clay get opts option} unset 2268 {clay get opts color} unset 2269 {clay ancestors} {::MixinRoot ::clay::object} 2270} { 2271 set testid [format %04d [incr testnum]] 2272 dict set map %test% $testid 2273 dict set map %method% $method 2274 dict set map %answer% $answer 2275 putb result $map $template 2276} 2277 2278set testnum 0 2279putb result {$obj clay mixinmap option ::MixinOption1} 2280dict set map %battery% [format %04d [incr batnum]] 2281dict set map %comment% {Mixin option1} 2282foreach {method answer} { 2283 {info root} {MixinRoot} 2284 {info option} {MixinOption1} 2285 {info color} {Undefined} 2286 {info other} {MixinOption1} 2287 {info shade} {avacodo} 2288 {did} {MixinOption1} 2289 {path} {::MixinOption1 ::MixinRoot ::clay::object} 2290 {clay get opts} {option option1 core root color unset} 2291 {clay get opts core} root 2292 {clay get opts option} option1 2293 {clay get opts color} unset 2294 {clay ancestors} {::MixinOption1 ::MixinRoot ::clay::object} 2295} { 2296 set testid [format %04d [incr testnum]] 2297 dict set map %test% $testid 2298 dict set map %method% $method 2299 dict set map %answer% $answer 2300 putb result $map $template 2301} 2302 2303set testnum 0 2304putb result { 2305set obj2 [clay::object new] 2306$obj2 clay mixinmap root ::MixinRoot option ::MixinOption1 2307} 2308putb result {$obj clay mixinmap option ::MixinOption1} 2309dict set map %obj% {$obj2} 2310dict set map %battery% [format %04d [incr batnum]] 2311dict set map %comment% {Mixin option1 - clean object} 2312foreach {method answer} { 2313 {info root} {MixinRoot} 2314 {info option} {MixinOption1} 2315 {info color} {Undefined} 2316 {info other} {MixinOption1} 2317 {info shade} {avacodo} 2318 {did} {MixinOption1} 2319 {path} {::MixinOption1 ::MixinRoot ::clay::object} 2320 {clay get opts} {option option1 core root color unset} 2321 {clay get opts core} root 2322 {clay get opts option} option1 2323 {clay get opts color} unset 2324 {clay ancestors} {::MixinOption1 ::MixinRoot ::clay::object} 2325} { 2326 set testid [format %04d [incr testnum]] 2327 dict set map %test% $testid 2328 dict set map %method% $method 2329 dict set map %answer% $answer 2330 putb result $map $template 2331} 2332 2333set testnum 0 2334putb result {$obj clay mixinmap option ::MixinOption2} 2335dict set map %battery% [format %04d [incr batnum]] 2336dict set map %comment% {Mixin option2} 2337dict set map %obj% {$obj} 2338foreach {method answer} { 2339 {info root} {MixinRoot} 2340 {info option} {MixinOption2} 2341 {info color} {Undefined} 2342 {info other} {MixinOption1} 2343 {info shade} {avacodo} 2344 {did} {MixinOption2} 2345 {path} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object} 2346 {clay get opts} {option option2 core root color unset} 2347 {clay get opts core} root 2348 {clay get opts option} option2 2349 {clay get opts color} unset 2350 {clay ancestors} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object} 2351} { 2352 set testid [format %04d [incr testnum]] 2353 dict set map %test% $testid 2354 dict set map %method% $method 2355 dict set map %answer% $answer 2356 putb result $map $template 2357} 2358 2359set testnum 0 2360putb result {$obj clay mixinmap color MixinColor1} 2361dict set map %battery% [format %04d [incr batnum]] 2362dict set map %comment% {Mixin color1} 2363foreach {method answer} { 2364 {info root} {MixinRoot} 2365 {info option} {MixinOption2} 2366 {info color} {MixinColor1} 2367 {info other} {MixinOption1} 2368 {info shade} {blue} 2369 {did} {MixinColor1} 2370 {path} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object} 2371 {clay get opts} {color blue option option2 core root} 2372 {clay get opts core} root 2373 {clay get opts option} option2 2374 {clay get opts color} blue 2375 {clay ancestors} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object} 2376} { 2377 set testid [format %04d [incr testnum]] 2378 dict set map %test% $testid 2379 dict set map %method% $method 2380 dict set map %answer% $answer 2381 putb result $map $template 2382} 2383set testnum 0 2384putb result {$obj clay mixinmap color MixinColor2} 2385dict set map %battery% [format %04d [incr batnum]] 2386dict set map %comment% {Mixin color2} 2387foreach {method answer} { 2388 {info root} {MixinRoot} 2389 {info option} {MixinOption2} 2390 {info color} {MixinColor2} 2391 {info other} {MixinOption1} 2392 {info shade} {green} 2393 {clay get opts} {color green option option2 core root} 2394 {clay get opts core} root 2395 {clay get opts option} option2 2396 {clay get opts color} green 2397 {clay ancestors} {::MixinColor2 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object} 2398} { 2399 set testid [format %04d [incr testnum]] 2400 dict set map %test% $testid 2401 dict set map %method% $method 2402 dict set map %answer% $answer 2403 putb result $map $template 2404} 2405 2406set testnum 0 2407putb result {$obj clay mixinmap option MixinOption1} 2408dict set map %battery% [format %04d [incr batnum]] 2409dict set map %comment% {Mixin color2 + Option1} 2410foreach {method answer} { 2411 {info root} {MixinRoot} 2412 {info option} {MixinOption1} 2413 {info color} {MixinColor2} 2414 {info other} {MixinOption1} 2415 {info shade} {green} 2416 {clay get opts} {color green option option1 core root} 2417 {clay get opts core} root 2418 {clay get opts option} option1 2419 {clay get opts color} green 2420 {clay ancestors} {::MixinColor2 ::MixinOption1 ::MixinRoot ::clay::object} 2421} { 2422 set testid [format %04d [incr testnum]] 2423 dict set map %test% $testid 2424 dict set map %method% $method 2425 dict set map %answer% $answer 2426 putb result $map $template 2427} 2428 2429set testnum 0 2430putb result {$obj clay mixinmap option {}} 2431dict set map %battery% [format %04d [incr batnum]] 2432dict set map %comment% {Mixin color2 + no option} 2433foreach {method answer} { 2434 {info root} {MixinRoot} 2435 {info option} {Undefined} 2436 {info color} {MixinColor2} 2437 {info other} {Undefined} 2438 {info shade} {green} 2439 {clay get opts} {color green core root option unset} 2440 {clay get opts core} root 2441 {clay get opts option} unset 2442 {clay get opts color} green 2443 {clay ancestors} {::MixinColor2 ::MixinRoot ::clay::object} 2444} { 2445 set testid [format %04d [incr testnum]] 2446 dict set map %test% $testid 2447 dict set map %method% $method 2448 dict set map %answer% $answer 2449 putb result $map $template 2450} 2451 2452set testnum 0 2453putb result {$obj clay mixinmap color {}} 2454dict set map %battery% [format %04d [incr batnum]] 2455dict set map %comment% {Mixin core (return to normal)} 2456foreach {method answer} { 2457 {info root} {MixinRoot} 2458 {info option} {Undefined} 2459 {info color} {Undefined} 2460 {info other} {Undefined} 2461 {info shade} {avacodo} 2462 {clay get opts} {core root option unset color unset} 2463 {clay get opts core} root 2464 {clay get opts option} unset 2465 {clay get opts color} unset 2466 {clay ancestors} {::MixinRoot ::clay::object} 2467} { 2468 set testid [format %04d [incr testnum]] 2469 dict set map %test% $testid 2470 dict set map %method% $method 2471 dict set map %answer% $answer 2472 putb result $map $template 2473} 2474 2475putb result { 2476### 2477# Tip479 Tests 2478### 2479clay::define tip479class { 2480 2481 Method newitem dictargs { 2482 id {type: number} 2483 color {default: green} 2484 shape {options: {round square}} 2485 flavor {default: grape} 2486 } { 2487 my variable items 2488 foreach {f v} $args { 2489 dict set items $id $f $v 2490 } 2491 if {"color" ni [dict keys $args]} { 2492 dict set items $id color $color 2493 } 2494 return [dict get $items $id] 2495 } 2496 2497 method itemget {id field} { 2498 my variable items 2499 return [dict get $id $field] 2500 } 2501} 2502 2503set obj [tip479class new] 2504test tip479-001 {Test that a later ensemble definition trumps a more primitive one} { 2505 $obj newitem id 1 color orange shape round 2506} {id 1 color orange shape round} 2507 2508# Fail because we left off a mandatory argument 2509test tip479-002 {Test that a later ensemble definition trumps a more primitive one} \ 2510 -errorCode NONE -body { 2511 $obj newitem id 2 2512} -result {shape is required} 2513 2514### 2515# Leave off a value that has a default 2516# note: Method had special handling for color, but not flavor 2517### 2518test tip479-003 {Test that a later ensemble definition trumps a more primitive one} { 2519 $obj newitem id 3 shape round 2520} {id 3 shape round color green} 2521 2522### 2523# Add extra arguments 2524### 2525test tip479-004 {Test that a later ensemble definition trumps a more primitive one} { 2526 $obj newitem id 4 shape round trim leather 2527} {id 4 shape round trim leather color green} 2528 2529clay::define tip479classE { 2530 2531 Ensemble item::new dictargs { 2532 id {type: number} 2533 color {default: green} 2534 shape {options: {round square}} 2535 flavor {default: grape} 2536 } { 2537 my variable items 2538 foreach {f v} $args { 2539 dict set items $id $f $v 2540 } 2541 if {"color" ni [dict keys $args]} { 2542 dict set items $id color $color 2543 } 2544 return [dict get $items $id] 2545 } 2546 2547 Ensemble item::get {id field} { 2548 my variable items 2549 return [dict get $id $field] 2550 } 2551} 2552 2553 2554set obj [tip479classE new] 2555test tip479-001 {Test that a later ensemble definition trumps a more primitive one} { 2556 $obj item new id 1 color orange shape round 2557} {id 1 color orange shape round} 2558 2559# Fail because we left off a mandatory argument 2560test tip479-002 {Test that a later ensemble definition trumps a more primitive one} \ 2561 -errorCode NONE -body { 2562 $obj item new id 2 2563} -result {shape is required} 2564 2565### 2566# Leave off a value that has a default 2567# note: Method had special handling for color, but not flavor 2568### 2569test tip479-003 {Test that a later ensemble definition trumps a more primitive one} { 2570 $obj item new id 3 shape round 2571} {id 3 shape round color green} 2572 2573### 2574# Add extra arguments 2575### 2576test tip479-004 {Test that a later ensemble definition trumps a more primitive one} { 2577 $obj item new id 4 shape round trim leather 2578} {id 4 shape round trim leather color green} 2579 2580} 2581 2582### 2583# TESTS NEEDED: 2584# destructor 2585### 2586 2587putb result { 2588testsuiteCleanup 2589 2590# Local variables: 2591# mode: tcl 2592# indent-tabs-mode: nil 2593# End: 2594} 2595return $result 2596