File: tool.test

package info (click to toggle)
tcllib 1.20%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 68,064 kB
  • sloc: tcl: 216,842; ansic: 14,250; sh: 2,846; xml: 1,766; yacc: 1,145; pascal: 881; makefile: 107; perl: 84; f90: 84; python: 33; ruby: 13; php: 11
file content (975 lines) | stat: -rw-r--r-- 23,544 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
# tool.test - Copyright (c) 2015 Sean Woods
# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2
testsNeed        TclOO 1


support {
    use oodialect/oodialect.tcl oo::dialect
    use dicttool/dicttool.tcl   dicttool
    use cron/cron.tcl           cron
    use oometa/oometa.tcl       oo::meta
    use sha1/sha1.tcl           sha1
}
testing {
    useLocal tool.tcl tool
}

# -------------------------------------------------------------------------

###
# Test the underlying components
###
::tool::event::subscribe ::BARNEY ::BETTY *
test tool-subscribe-001 {Test that tool subscribe inserts a pattern into the dictionary} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY *}

test tool-notify-001 {Test the distribution list} {
  ::tool::event::Notification_list ::BETTY niceday
} ::BARNEY

::tool::event::subscribe ::BARNEY ::BETTY *
test tool-subscribe-002 {Test that tool subscribe inserts a pattern into the dictionary only once} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY *}

::tool::event::subscribe ::BARNEY ::BETTY niceday
test tool-subscribe-002 {Test that tool subscribe will not add a more specific pattern if a general one already exists} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY *}

test tool-notify-002 {Test the distribution list} {
  ::tool::event::Notification_list ::BETTY niceday
} ::BARNEY

::tool::event::subscribe ::BARNEY * caring
test tool-subscribe-003 {Test that tool subscribe inserts a global pattern} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY * * caring}

::tool::event::subscribe ::BARNEY * sharing
test tool-subscribe-004 {Test that tool subscribe inserts a global pattern} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY * * {caring sharing}}

::tool::event::subscribe ::BARNEY ::FRED sharing
::tool::event::unsubscribe ::BARNEY * sharing
test tool-subscribe-005 {Test that tool unsubscribe removes a global pattern} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY * * caring}

::tool::event::subscribe ::BARNEY ::FRED sharing
::tool::event::subscribe ::BARNEY ::FRED niceday
::tool::event::subscribe ::BETTY ::FRED niceday

test tool-subscribe-005 {Test that tool unsubscribe removes a global pattern} {
  set ::tool::object_subscribe(::BARNEY)
} {::BETTY * * caring ::FRED {sharing niceday}}

test tool-notify-002 {Test the distribution list} {
  ::tool::event::Notification_list ::BETTY caring
} ::BARNEY

test tool-notify-002 {Test the distribution list} {
  lsort -dictionary [::tool::event::Notification_list ::FRED niceday]
} {::BARNEY ::BETTY}

# Test that destroy auto-cleans up the event list
::tool::object_destroy ::BARNEY
test tool-destroy-001 {Test that destroy auto-cleans up the event list} {
  info exists ::tool::object_subscribe(::BARNEY)
} 0

# Start over
array unset ::tool::object_subscribe


tool::class create OptionClass {
  property color green
  property mass  1200kg
  option bodystyle {default: sedan}
  option master {class organ default ::noop}
}

tool::class create OptionClass2 {
  superclass OptionClass
  property mass  1400kg
  option color {default: blue}
}

OptionClass create ObjectOptionTest1 
OptionClass create ObjectOptionTest2 bodystyle wagon transmission standard
OptionClass2 create ObjectOptionTest3
OptionClass2 create ObjectOptionTest4 bodystyle SUV transmission cvt color white

###
# Property ignores options
###
test tool-options-001 {Simple property queries} {
  ObjectOptionTest1 meta cget color
} green

test tool-options-002 {Simple property queries} {
  ObjectOptionTest2 meta cget color
} green

test tool-options-003 {Simple property queries} {
  ObjectOptionTest3 meta cget color
} green

test tool-options-004 {Simple property queries} {
  ObjectOptionTest4 meta cget color
} green

###
# Cget consults the options
###
test tool-options-005 {Simple property queries} {
  ObjectOptionTest1 cget color
} green

test tool-options-006 {Simple property queries} {
  ObjectOptionTest2 cget color
} green

test tool-options-007 {Simple property queries} {
  ObjectOptionTest3 cget color
} blue

test tool-options-008 {Simple property queries} {
  ObjectOptionTest4 cget color
} white

###
# Tests with options in an object changing class
###
test tool-options-009 {Simple property queries} {
  ObjectOptionTest3 meta cget mass
} 1400kg

ObjectOptionTest3 morph OptionClass
# The option for color was already set. It should remain
test tool-options-010 {Simple property queries} {
  ObjectOptionTest3 cget color
} blue
# The "color" property on the other hand should revert
test tool-options-011 {Simple property queries} {
  ObjectOptionTest3 meta cget color
} green
# The "mass" property on the other hand should revert
test tool-options-012 {Simple property queries} {
  ObjectOptionTest3 meta cget mass
} 1200kg

# Change a OptionClass to a OptionClass2

test tool-options-013 {Simple property queries} {
  ObjectOptionTest2 meta cget mass
} 1200kg

ObjectOptionTest2 morph OptionClass2
# When entering OptionClass2, the object will get any new options
test tool-options-014 {Simple property queries} {
  ObjectOptionTest2 cget color
} blue

test tool-options-015 {Simple property queries} {
  ObjectOptionTest2 meta cget mass
} 1400kg

# When changing back, the set option remains
ObjectOptionTest2 morph OptionClass
test tool-options-016 {Simple property queries} {
  ObjectOptionTest2 cget color
} blue

test tool-options-017 {Simple property queries} {
  ObjectOptionTest2 meta cget mass
} 1200kg


tool::class create ArrayEnsembleClass {
  # Burned in defaults
  meta branchset define {
    color: pink
  }

  array_ensemble define define {
    initialize {
      foo bar
    }
    custom {
      return custom
    }
    true {
      return true
    }
    false {
      return false
    }
  }
}

ArrayEnsembleClass create ArrayEnsembleObject

test tool-ensemble-001 {Test Array Ensemble} {
  ArrayEnsembleObject define true
} true
test tool-ensemble-002 {Test Array Ensemble} {
  ArrayEnsembleObject define false
} false
test tool-ensemble-003 {Test Array Ensemble retrieve initial value} {
  ArrayEnsembleObject define get foo
} bar
test tool-ensemble-004 {Test Array Ensemble Store a value} {
  ArrayEnsembleObject define set cc /usr/bin/cc
  ArrayEnsembleObject define get cc
} /usr/bin/cc

test tool-ensemble-005 {Test array add} {
  ArrayEnsembleObject define add path /bin
  ArrayEnsembleObject define get path
} /bin

test tool-ensemble-005 {Test array add} {
  ArrayEnsembleObject define add path /usr/bin
  ArrayEnsembleObject define get path
} {/bin /usr/bin}

test tool-ensemble-006 {Test array add (again)} {
  ArrayEnsembleObject define add path /usr/bin
  ArrayEnsembleObject define get path
} {/bin /usr/bin}


test tool-ensemble-007 {Test array lappend} {
  ArrayEnsembleObject define lappend path /usr/bin
  ArrayEnsembleObject define get path
} {/bin /usr/bin /usr/bin}

test tool-ensemble-008 {Test array remove} {
  ArrayEnsembleObject define remove path /usr/bin
  ArrayEnsembleObject define get path
} {/bin}

test tool-ensemble-009 {Test array exists} {
  ArrayEnsembleObject define exists counter
} 0

test tool-ensemble-010 {Test array incr} {
  ArrayEnsembleObject define incr counter
  ArrayEnsembleObject define get counter
} 1

test tool-ensemble-011 {Test array incr} {
  ArrayEnsembleObject define incr counter
  ArrayEnsembleObject define get counter
} 2

test tool-ensemble-012 {Test array exists} {
  ArrayEnsembleObject define exists counter
} 1

test tool-ensemble-013 {Test array reset} {
  ArrayEnsembleObject define reset
  lsort -stride 2 [ArrayEnsembleObject define dump]
} {color pink foo bar}

tool::class create DictEnsembleClass {
  # Burned in defaults
  meta branchset define {
    color: pink
  }

  dict_ensemble define define {
    initialize {
      foo bar
    }
    custom {
      return custom
    }
    true {
      return true
    }
    false {
      return false
    }
  }
}

DictEnsembleClass create DictEnsembleObject

test tool-ensemble-001 {Test Array Ensemble} {
  DictEnsembleObject define true
} true
test tool-ensemble-002 {Test Array Ensemble} {
  DictEnsembleObject define false
} false
test tool-ensemble-003 {Test Array Ensemble retrieve initial value} {
  DictEnsembleObject define get foo
} bar
test tool-ensemble-004 {Test Array Ensemble Store a value} {
  DictEnsembleObject define set cc /usr/bin/cc
  DictEnsembleObject define get cc
} /usr/bin/cc

test tool-ensemble-005 {Test array add} {
  DictEnsembleObject define add path /bin
  DictEnsembleObject define get path
} /bin

test tool-ensemble-005 {Test array add} {
  DictEnsembleObject define add path /usr/bin
  DictEnsembleObject define get path
} {/bin /usr/bin}

test tool-ensemble-006 {Test array add (again)} {
  DictEnsembleObject define add path /usr/bin
  DictEnsembleObject define get path
} {/bin /usr/bin}


test tool-ensemble-007 {Test array lappend} {
  DictEnsembleObject define lappend path /usr/bin
  DictEnsembleObject define get path
} {/bin /usr/bin /usr/bin}

test tool-ensemble-008 {Test array remove} {
  DictEnsembleObject define remove path /usr/bin
  DictEnsembleObject define get path
} {/bin}

test tool-ensemble-009 {Test array exists} {
  DictEnsembleObject define exists counter
} 0

test tool-ensemble-010 {Test array incr} {
  DictEnsembleObject define incr counter
  DictEnsembleObject define get counter
} 1

test tool-ensemble-011 {Test array incr} {
  DictEnsembleObject define incr counter
  DictEnsembleObject define get counter
} 2

test tool-ensemble-012 {Test array exists} {
  DictEnsembleObject define exists counter
} 1

test tool-ensemble-013 {Test array reset} {
  DictEnsembleObject define reset
  lsort -stride 2 [DictEnsembleObject define dump]
} {color pink foo bar}




test tool-option_class-001 {Test option class} {
  ObjectOptionTest1 meta get option master
} {default: ::noop class: organ widget: label set-command: {my graft %field% %value%} get-command: {my organ %field%}}

proc GNDN args {
  return $args
}

ObjectOptionTest1 configure master GNDN
test tool-option_class-002 {Test option class} {
  ObjectOptionTest1 organ master
} GNDN

test tool-option_class-003 {Test option class} {
  ObjectOptionTest1 <master> puts FOO
} {puts FOO}

OptionClass2 create ObjectOptionTest5 bodystyle SUV transmission cvt color white master GNDN

test tool-option_class-002 {Test option class} {
  ObjectOptionTest5 organ master
} GNDN

test tool-option_class-003 {Test option class} {
  ObjectOptionTest5 <master> puts FOO
} {puts FOO}

###
# Second round of testing
# Make sure the various and sundry ways to generate
# dynamic methods follow through morphs, mixins,
# and class method definitions
###

tool::class create WidgetClass {
  class_method unknown args {
    set tkpath [lindex $args 0]
    if {[string index $tkpath 0] eq "."} {
      set obj [my new $tkpath {*}[lrange $args 1 end]]
      $obj tkalias $tkpath
      return $tkpath
    }
    next {*}$args
  }
  
  constructor {TkPath args} {
    my variable hull
    set hull $TkPath
    my graft hull $TkPath
  }
    
  method tkalias tkname {
    set oldname $tkname
    my variable tkalias
    set tkalias $tkname
    set self [self]
    set hullwidget [::info object namespace $self]::tkwidget
    my graft tkwidget $hullwidget
    #rename ::$tkalias $hullwidget
    my graft hullwidget $hullwidget
    ::tool::object_rename [self] ::$tkalias
    #my Hull_Bind $tkname
    return $hullwidget
  }
}

test tool-class-method-001 {Test Tk style creator} {
  WidgetClass .foo
  .foo organ hull
} {.foo}

tool::class create WidgetNewClass {
  superclass WidgetClass
}

test tool-class-method-002 {Test Tk style creator inherited by morph} {
  WidgetNewClass .bar
  .bar organ hull
} {.bar}

tool::class create DummyClass {
  method i_am_here {} {
    return DummyClass
  }
}


tool::class create OrganClass {
  option db {class organ default ::noop}
  constructor args {
    my config set $args
  }
}
DummyClass create ::DbObj
OrganClass create OrganObject db ::DbObj
test tool-constructor-args-001 {Test that organs passed as options map correctly} {
  OrganObject organ db
} {::DbObj} 
test tool-constructor-args-002 {Test that organs passed as options map correctly} {
  OrganObject cget db
} {::DbObj}

tool::object create MorphOrganObject#1
tool::object create MorphOrganObject#2
MorphOrganObject#2 graft db ::DbObj

MorphOrganObject#1 morph OrganClass
test tool-constructor-args-003 {Test that a default for an organ option is applied after a morph} {
  MorphOrganObject#1  organ db
} {::noop}

MorphOrganObject#2 morph OrganClass
test tool-constructor-args-004 {Test that a default for an organ option is NOT applied if the graft exists following a morph} {
  MorphOrganObject#2  organ db
} {::DbObj}

tool::object create MorphOrganObject#3
tool::object create MorphOrganObject#4
MorphOrganObject#4 graft db ::DbObj
MorphOrganObject#3 mixin OrganClass
test tool-constructor-args-005 {Test that a default for an organ option is applied during a mixin} {
  MorphOrganObject#3  organ db
} {::noop}

MorphOrganObject#4 mixin OrganClass
test tool-constructor-args-006 {Test that a default for an organ option is NOT applied if the graft exists during a mixin} {
  MorphOrganObject#4  organ db
} {::DbObj}

###
# Test ensemble inheritence
###
tool::define NestedClassA {
  method do::family {
    return [self class]
  }
  method do::something {
    return A
  }
  method do::whop {
    return A
  }
}
tool::define NestedClassB {
  superclass NestedClassA
  method do::family {
    set r [next family]
    lappend r [self class]
    return $r
  }
  method do::whop {
    return B
  }
}
tool::define NestedClassC {
  superclass NestedClassB

  method do::somethingelse {
    return C
  }
}
tool::define NestedClassD {
  superclass NestedClassB

  method do::somethingelse {
    return D
  }
}

tool::define NestedClassE {
  superclass NestedClassD NestedClassC
}

tool::define NestedClassF {
  superclass NestedClassC NestedClassD
}

NestedClassC create NestedObjectC

test tool-ensemble-001 {Test that an ensemble can access [next] even if no object of the ancestor class have been instantiated} {
  NestedObjectC do family
} {::NestedClassA ::NestedClassB ::NestedClassC}

test tool-ensemble-002 {Test that a later ensemble definition trumps a more primitive one} {
  NestedObjectC do whop
} {B}
test tool-ensemble-003 {Test that an ensemble definitions in an ancestor carry over} {
  NestedObjectC do something
} {A}

NestedClassE create NestedObjectE
NestedClassF create NestedObjectF


test tool-ensemble-004 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectE do somethingelse
} {D}

test tool-ensemble-005 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectF do somethingelse
} {C}

###
# Set of tests to exercise the mixinmap system
###
tool::define MixinMainClass {
  variable mainvar unchanged
  
  method test::which {} {
    my variable mainvar
    return $mainvar
  }
  
  method test::main args {
    puts [list this is main $method $args]
  }

}

tool::define MixinTool {
  variable toolvar unchanged.mixin
  meta set mixin unmap-script: {
my test untool $class
  }
  meta set mixin map-script: {
my test tool $class
  }
  meta set mixin name: {Generic Tool}
  
  method test::untool class { 
    my variable toolvar mainvar
    set mainvar {}
    set toolvar {} 
  }
  
  method test::tool class {
    my variable toolvar mainvar
    set mainvar [$class meta get mixin name:] 
    set toolvar [$class meta get mixin name:] 
  }
}

tool::define MixinToolA {
  superclass MixinTool
  meta set mixin name: {Tool A}
}

tool::define MixinToolB {
  superclass MixinTool
  meta set mixin name: {Tool B}

  method test_newfunc {} {
    return "B"
  }
}

MixinMainClass create mixintest

test tool-mixinmap-001 {Test object prior to mixins} {
  mixintest test which
} {unchanged}

mixintest mixinmap tool MixinToolA
test tool-mixinmap-002 {Test mixin map script ran} {
  mixintest test which
} {Tool A}

mixintest mixinmap tool MixinToolB
test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test which
} {Tool B}

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test_newfunc
} {B}

mixintest mixinmap tool {}
test tool-mixinmap-001 {Test object prior to mixins} {
  mixintest test which
} {}

###
# Coroutine tests
###
tool::define coro_example {
  
  dict_ensemble coro_a_info coro_a_info {
    initialize {
      restart 0
      phase 0
      loop  0
      event 0
      idle  0
    }
  }
  
  coroutine coro_a {
    my coro_a_info merge {
      phase 0
      loop  0
      event 0
      idle  0
    }
    yield [info coroutine]
    while 1 {
      my coro_a_info incr phase
      my coro_a_info set  loop 0
      while 1 {
        if {[my $coro next event]} {
          my coro_a_info incr idle
          yield
          continue
        }
        my coro_a_info set last_event $event
        my coro_a_info incr loop
        my coro_a_info incr event
        switch [lindex $event 0] {
          phase {
            break
          }
          quit {
            return
          }
          b {
            my coro_b send [lrange $event 1 end]
          }
        }
      }
    }
  }
  
  dict_ensemble coro_b_info coro_b_info {
    initialize {
      restart 0
      phase 0
      loop  0
      event 0
      idle  0
    }
  }
  
  coroutine coro_b {
    my coro_b_info merge {
      phase 0
      loop  0
      event 0
      idle  0
    }
    yield [info coroutine]

    while 1 {
      my coro_b_info incr phase
      my coro_b_info set  loop 0
      while 1 {
        if {[my $coro next event]} {
          my coro_b_info incr idle
          yield
          continue
        }
        my coro_b_info incr loop
        my coro_b_info incr event
        switch [lindex $event 0] {
          phase break
          quit return
          a {
            my coro_a [lrange $event 1 end]
          }
        }
      }
    }
  }
  

  dict_ensemble coro_yodawg_info coro_yodawg_info {
    initialize {
      restart 0
      phase 0
      loop  0
      event 0
      idle  0
      yodawg  0
    }
  }
  
  coroutine coro_yodawg {
    my coro_yodawg_info merge {
      phase 0
      loop  0
      event 0
      idle  0
      yodawg  0
      iloop 0
    }
    yield [info coroutine]

    while 1 {
      my coro_yodawg_info incr phase
      my coro_yodawg_info set  loop 0
      while 1 {
        if {[my $coro next event]} {
          my coro_yodawg_info incr idle
          yield
          continue
        }
        my coro_yodawg_info set last_event $event
        my coro_yodawg_info incr loop
        my coro_yodawg_info incr event
        switch [lindex $event 0] {
          phase break
          quit {
            return
          }
          yodawg {
            my coro_yodawg_info incr yodawg
            if {[my coro_yodawg_info get yodawg] <32} {
              my coro_yodawg yodawg
              yield
            }
          }
          iloop {
            my coro_yodawg_info incr iloop
          }
        }
      }
    }
  }
}

set obj [coro_example new]
$obj coro_a none
test tool-coroutine-001-00 {Test coroutine } {
  $obj coro_a_info get restart
} 0
test tool-coroutine-001-01 {Test coroutine } {
  $obj coro_a_info get loop
} 1
$obj coro_a none
test tool-coroutine-001-02 {Test coroutine } {
  $obj coro_a_info get loop
} 2
$obj coro_a none
test tool-coroutine-001-03 {Test coroutine } {
  $obj coro_a_info get loop
} 3
$obj coro_a phase
test tool-coroutine-002-01 {Test coroutine } {
  $obj coro_a_info get loop
} 0
test tool-coroutine-002-02 {Test coroutine } {
  $obj coro_a_info get phase
} 2

###
# Start both coroutines over
$obj coro_a restart
$obj coro_b restart

test tool-coroutine-003-01-A {Test coroutine } {
  $obj coro_a_info get phase
} 0
test tool-coroutine-003-01-B {Test coroutine } {
  $obj coro_a_info get loop
} 0
test tool-coroutine-003-01-C {Test coroutine } {
  $obj coro_a_info get phase
} 0
test tool-coroutine-003-01-D {Test coroutine } {
  $obj coro_b_info get loop
} 0


$obj coro_a b
###
# Test coroutines calling coroutines
test tool-coroutine-003-02-A {Test coroutine } {
  $obj coro_a_info get loop
} 1
test tool-coroutine-003-02-B {Test coroutine } {
  $obj coro_b_info get loop
} 1

$obj coro_b a
###
# Test coroutines calling coroutines
# Note: Each call to each other coroutine can only happen
# once per "send"
###
test tool-coroutine-003-03-A {Test coroutine } {
  $obj coro_a_info get loop
} 1
test tool-coroutine-003-03-B {Test coroutine } {
  $obj coro_b_info get loop
} 2

###
# Rig the coroutine to call itself back from the other coroutine
###
$obj coro_b a b
###
# Test coroutines calling coroutines
test tool-coroutine-003-04-A {Test coroutine } {
  $obj coro_a_info get loop
} 2
test tool-coroutine-003-04-B {Test coroutine } {
  $obj coro_b_info get loop
} 3

# We should see A update in the background
$obj coro_b loop
test tool-coroutine-003-05-A {Test coroutine } {
  $obj coro_a_info get loop
} 3
test tool-coroutine-003-05-B {Test coroutine } {
  $obj coro_b_info get loop
} 5

# Now only B advances
$obj coro_b loop
test tool-coroutine-003-05-A {Test coroutine } {
  $obj coro_a_info get loop
} 3
test tool-coroutine-003-05-B {Test coroutine } {
  $obj coro_b_info get loop
} 6

# Now only A advances
$obj coro_a loop
test tool-coroutine-003-06-A {Test coroutine } {
  $obj coro_a_info get loop
} 4
test tool-coroutine-003-06-B {Test coroutine } {
  $obj coro_b_info get loop
} 6

###
# Test a malformed coroutine that calls itself
# The safety mechanism should allow the event to re-schedule itself
# but only once per call, and only execute once per call
###
test tool-coroutine-yodawg-00 {Test coroutine - yodawg } {
  $obj coro_yodawg running
} 0

$obj coro_yodawg yodawg
test tool-coroutine-yodawg-01 {Test coroutine - yodawg } {
  $obj coro_yodawg_info get yodawg
} 1
$obj coro_yodawg
test tool-coroutine-yodawg-02 {Test coroutine - yodawg } {
  $obj coro_yodawg_info get yodawg
} 2
$obj coro_yodawg yodawg
$obj coro_yodawg yodawg
test tool-coroutine-yodawg-03 {Test coroutine - yodawg } {
  $obj coro_yodawg_info get yodawg
} 4
for {set x 1} {$x < 32} {incr x} {
  $obj coro_yodawg iloop
  set a [$obj coro_yodawg_info get yodawg]
  set levent [$obj coro_yodawg_info get last_event]
  set iloop [$obj coro_yodawg_info get iloop]
  if {$a > 32} break
  test tool-coroutine-yodawg-03-yd-$x {Test coroutine - yodawg } {
    set a
  } [expr {4+$x}]
  test tool-coroutine-yodawg-03-le-$x {Test coroutine - yodawg } {
    set levent
  } yodawg
  # The iloop should *ALSO* be running side-by-side with the yodawg
  # However, not until the first three yodawg events are processed
  # in the queue
  if {$x > 3} {
    test tool-coroutine-yodawg-03-il-$x {Test coroutine - yodawg } {
      set iloop
    } [expr {$x-3}]
  }
}
###
# With the yodawgs resolved we should now
# be processing events in order once more
# Add one more event
#
# NOTE the lagging iloop events do catch up
###
$obj coro_yodawg end
test tool-coroutine-yodawg-03-iloop-count {Test coroutine - yodawg } {
  $obj coro_yodawg_info get iloop
} $x
test tool-coroutine-yodawg-03-endevent {Test coroutine - yodawg } {
  $obj coro_yodawg_info get last_event
} end

# -------------------------------------------------------------------------


testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End: