-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtest.pcl
executable file
·1559 lines (1450 loc) · 62.4 KB
/
test.pcl
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
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#! /usr/bin/env picolsh
# test.pcl - A test suite for the Picol interpreter
# with many extensions by suchenwi and dbohdan. Call with "-l" to display all
# test cases. Is this comment extended? \
Yes, it is.
set patchlevel 0.6.1
set thisfile [info script]
set tcl tclsh ;# The Tcl 8.x interpreter binary.
# lappend argv -l
set n 0; set r 0 ;# counters for tests, errors
set match *
set pos [lsearch $argv -m]
if {$pos >= 0} {set match [lindex $argv [incr pos]];puts match:$match}
unset pos
set test_config(picol) 0
if {[info exists tcl_platform(engine)] \
&& [expr {$tcl_platform(engine) eq {Picol}}]} {
set test_config(picol) 1
}
set test_config(tcl85) 0
if {[string match 8.5.* [info patchlevel]]} {
puts {Warning: It is recommended that you run the test suite with Tcl 8.6.}
puts { Some important tests will be skipped in Tcl 8.5.}
set test_config(tcl85) 1
}
set test_config(unix) [expr {$tcl_platform(platform) eq {unix}}]
set test_config(windows) [expr {$tcl_platform(platform) eq {windows}}]
if {$test_config(windows)} {
set test_config(hello_file_length) 7
set test_config(newline) \r\n
} else {
set test_config(hello_file_length) 6
set test_config(newline) \n
}
set test_config(arrays) [expr {[info commands array] eq {array}}]
set test_config(glob) [expr {[info commands glob] eq {glob}}]
set test_config(interp) [expr {[info commands interp] eq {interp}}]
set test_config(io) [expr {[info commands open] eq {open}}]
# The optional [regexp] extension. See the directory extensions/.
set test_config(regexp) [expr {[info commands regexp] eq {regexp}}]
# Do not check for [puts]. [puts] is mandatory to run the tests.
if {$test_config(picol) && $test_config(io)} {
source [file dirname [file join [pwd] [info script]]]/init.pcl
}
if !$test_config(picol) { #----------------------- compatibility mode for tclsh
foreach i {/ % == != > < >= <= << >>} {proc $i {a b} "expr {\$a $i \$b}"}
foreach i {+ * && || & | ^} {proc $i args "expr \[join \$args $i\]+0"}
foreach i {min max} {proc $i args "expr $i\(\[join \$args ,\])"}
proc - {a1 args} {
if {$args eq ""} {return [expr -$a1]}
foreach a $args {set a1 [expr $a1-$a]}
return $a1
}
proc ~ x {expr ~$x}
proc abs x {expr abs($x)}
catch {unset env(TZ)} ;# This is somehow (wrongly) set when running via system()
}
#--------------------------------------------- minimal testing "framework"
proc test {name cmd arrow expected} {
if {![string match $::match $name]} return
incr ::n
if {[lsearch $::argv -l] >= 0} {
puts " [list $name $cmd $arrow $expected]"
}
catch $cmd res
lassign [switch A$arrow A-> {
list [string equal $expected $res] exact
} A->* {
list [string match $expected $res] glob
} A->$ {
list [regexp $expected $res] regexp
} default {
error [list unknown arrow: $arrow]
}] match mode
if {!$match} {
puts "\n>>>>> $name failed: [list $cmd]"
puts " got: $res"
puts " expected: $expected"
puts " mode: $mode"
incr ::r
}
}
if $test_config(picol) {test version {info pa} -> $patchlevel}
puts "[info script] [info patchlevel], $argv0, argv:<$argv>,argc:$argc"
test parser.1 {set a 5} -> 5
test parser.2 {set a [} -> {missing close-bracket}
test parser.3 {set a [][} -> {missing close-bracket}
test parser.4 {set a [[} -> {missing close-bracket}
test parser.5 {set a [\{} -> {missing close-bracket}
test +.1 {+ 3 4} -> 7
test +.2 {+ 3 4 5} -> 12
test +.3 {+ 3} -> 3
test +.4 + -> 0
test *.1 {* 3 4} -> 12
test *.2 {* 3 4 5} -> 60
if {$test_config(picol)} {
test **.1 {** 2 4} -> 16
test **.2 {** 47 0} -> 1
}
test -.1 {- 42 20} -> 22
test -.2 {- 42 0} -> 42
test -.3 {set x 5; - $x} -> -5
if $test_config(picol) {test &&.1 {&&} -> 1}
test &&.2 {&& 1 1 1} -> 1
test &&.3 {&& 1 0 1 1} -> 0
test &&.4 {&& 0 0 0} -> 0
if $test_config(picol) {test ||.1 {||} -> 0}
test ||.2 {|| 1 1} -> 1
test ||.3 {|| 1 0} -> 1
test ||.4 {|| 0 0} -> 0
test % {% 47 2} -> 1
test <.1 {< 1 0} -> 0
test <.2 {< 1 1} -> 0
test <.3 {< 1 2} -> 1
test <=.1 {<= 1 2} -> 1
test <=.2 {<= 2 2} -> 1
test <=.3 {<= 3 2} -> 0
test &.1 {& 0 0} -> 0
test &.2 {& 0 1} -> 0
test &.3 {& 255 15} -> 15
test &.4 {& 255 15 3} -> 3
if {$test_config(picol)} {
test &.5 {&} -> 2147483647
}
test |.1 {| 0 0} -> 0
test |.2 {| 0 1} -> 1
test |.3 {| 255 15} -> 255
test |.4 {| 1 2 4} -> 7
if {$test_config(picol)} {
test |.5 {|} -> 0
}
test ^.1 {^ 0 0} -> 0
test ^.2 {^ 0 1} -> 1
test ^.3 {^ 255 15} -> 240
test ^.4 {^ 1 2 4} -> 7
if {$test_config(picol)} {
test ^.5 {^} -> 0
}
test <<.1 {<< 0 0} -> 0
test <<.2 {<< 0 1} -> 0
test <<.3 {<< 1 0} -> 1
test <<.4 {<< 1 1} -> 2
test <<.5 {<< 1 5} -> 32
if {$test_config(picol)} {
test <<.6 {
<< 1 99
} ->* {can't shift integer left by more than ?? bit(s) (99 given)}
}
test >>.1 {>> 0 0} -> 0
test >>.2 {>> 0 1} -> 0
test >>.3 {>> 1 0} -> 1
test >>.4 {>> 32 3} -> 4
test >>.5 {>> 65536 3} -> 8192
test ~.1 {~ 0} -> -1
test ~.2 {~ 1234} -> -1235
test ~.3 {~ -9876} -> 9875
test abs.1 {abs -47} -> 47
test abs.2 {abs 0} -> 0
test abs.3 {abs 48} -> 48
test after.1 {after 100} -> {}
test append.0 {catch append res; lrange $res 0 2} -> {wrong # args:}
test append.1 {set foo hello; append foo world} -> helloworld
test append.2 {set foo 47;append foo 11;set foo} -> 4711
test append.3 {append bar grill} -> grill
if $test_config(picol) {
test apply.1 {apply {{a b} {* $a $b}} 6 7} -> 42
test apply.2 {apply {{} {return hello}}} -> hello
test apply.3 {set sum {{a b} {+ $a $b}}; apply $sum 17 18} -> 35
}
test argv0.1 {
puts [list argv0 $::argv0 script [info script]]
string equal $::argv0 [info script]
} -> 1
if {$test_config(arrays)} {
test array.1 {array exists a} -> 0
test array.2 {array set a {foo 42}; array exists a} -> 1
test array.3 {array set a {foo 42 bar 11}; array size a} -> 2
test array.4 {array set a {foo 42 bar 11 fx 0}; lsort [array names a f*]} -> {foo fx}
test array.5 {array set a {foo 42 bar 11 grill 0}; lsort [array names a]} -> {bar foo grill}
test array.6 {array set a {foo 42 bar 11 grill 0}; set a(bar)} -> 11
test array.7 {array set a {foo 42 bar 11 grill 0}; catch {set a(bar)}} -> 0
test array.8 {array set a {foo 42 bar 11 grill 0}; catch {set a(baz)}} -> 1
test array.9 {array set a {foo 42 bar 11 grill 0}; set i $a(foo)} -> 42
test array.10 {array set a {foo 42 bar 11 grill 0}; set key foo; set a($key)} -> 42
test array.11 {set a(1) hello; set a(2) world; lsort [array get a]} -> {1 2 hello world}
test array.12 {set a(1) x;set a(2) y;set a(1) z;list $a(1) $a(2)} -> {z y}
test array.13 {set (foo) bar; array get ""} -> {foo bar}
test array.14 {set (1) a; set (2) $(1); set (2)} -> a
test array.15 {set (1) b; set k 1; set (2) [set ($k)]; set (2)} -> b
test array.16 {set a 12345678; array exists a} -> 0
test array.17 {set a 12345678; array get a} -> {}
test array.18 {set a 12345678; array set a {k v}} -> {can't set "a(k)": variable isn't array}
test array.19 {array statistics blah} -> {"blah" isn't an array}
test array.20 {set a 12345678; array statistics a} -> {"a" isn't an array}
test array.21 {lset a(5) 0 value} -> {can't read "a(5)": no such variable}
test array.22 {set a 12345678; lassign {a b c} a(foo) a(bar) a(baz)} -> {can't set "a(foo)": variable isn't array}
test array.23 {set a 12345678; lassign {} a(foo) a(bar) a(baz)} -> {can't set "a(foo)": variable isn't array}
test array.24 {set a 12345678; append a(foo) yo} -> {can't set "a(foo)": variable isn't array}
if {!$test_config(tcl85)} {
test array.25 {set a 12345678; try {error KABOOM} on error a(foo) {}} -> {can't set "a(foo)": variable isn't array}
test array.26 {set a 12345678; catch {error BLAM} a(foo)} -> {can't set "a(foo)": variable isn't array}
test array.27 {set a 12345678; lmap a(foo) a {}} -> {can't set "a(foo)": variable isn't array}
}
test array.28 {set a 12345678; lappend a(foo) a} -> {can't set "a(foo)": variable isn't array}
test array.29 {set a 12345678; set a(5) 99} -> {can't set "a(5)": variable isn't array}
test array.30 {set a(0)} -> {can't read "a(0)": no such variable}
test array.31 {set a(k1) v1; set a(k2) v2; unset a(k1); array get a} -> {k2 v2}
test array.32 {set a(k1) v1; set a(k2) v2; unset a(k2); array get a} -> {k1 v1}
test array.33 {set a(5) 0; unset a(5); array get a} -> {}
test array.34 {set a(5) 0; unset a(7)} -> {can't unset "a(7)": no such element in array}
test array.35 {unset a(5)} -> {can't unset "a(5)": no such variable}
test array.36 {array set a {k1 v1 k2 v2 k3 v3}; unset a; array statistics a} -> {"a" isn't an array}
test array.37 {set a(5) hello; set a(5) hi; set a(5)} -> {hi}
# A workaround for Tcl 8.6: throw a more specific error in this case
# ('can't read "a(0)": variable isn't array').
test array.37 {
set a 12345678
set a(0)
} ->* {can't read "a(0)":*}
test array.38 {
set a 12345678
lindex $a(5)
} ->* {can't read "a(5)":*}
test array.39 {
set a 12345678
lset a(5) 0 value
} ->* {can't read "a(5)":*}
test array.40 {
proc array.40 {} { set a(k) 5 }
array.40
rename array.40 {}
set a(k)
} -> {can't read "a(k)": no such variable}
test array.41 {
proc array.41.foo {} { set a(k) 5; array.41.bar }
proc array.41.bar {} { return $a(k) }
catch array.41.foo res
rename array.41.foo {}
rename array.41.bar {}
lindex $res
} -> {can't read "a(k)": no such variable}
test array.42 {
proc array.42.foo {} { set ::a42(k) 5; array.42.bar }
proc array.42.bar {} { return $::a42(k) }
set res [array.42.foo]
rename array.42.foo {}
rename array.42.bar {}
unset ::a42
lindex $res
} -> 5
test array.43 {
set n 100
for {set i 0} {$i < $n} {incr i} {
set arr(k$i) 1
}
for {set i 0} {$i < $n} {incr i} {
set arr(k$i) 2
}
lsort -unique [array get arr]
} ->* {2 k*}
test array.44 {
set n 100
for {set i 0} {$i < $n} {incr i} {
set arr($i) value
}
unset arr(xx)
} -> {can't unset "arr(xx)": no such element in array}
test array.45 {
set n 100
for {set i 0} {$i < $n} {incr i} {
set ::arr($i) value
}
for {set i [expr {$n - 1}]} {$i >= 0} {incr i -1} {
unset ::arr($i)
}
set res [array get ::arr]
unset ::arr
lindex $res
} -> {}
test array.46 {
set n 100
for {set i 0} {$i < $n} {incr i} {
set arr($i) value
}
for {set i 0} {$i < $n} {incr i} {
unset arr($i)
}
} -> {}
test array.47 {
set arr(k) v
set ::arr(k)
} -> {can't read "::arr(k)": no such variable}
test array.48 {
set arr(k) 1
set ::arr(k) 2
set res $arr(k)
unset ::arr
return $res
} -> 1
test array.49 {
info exists arr([string repeat 1 1000])
} -> 0
test array.50 {
set arr(x) y
info exists arr([string repeat 1 100])
} -> 0
# test array.xx {set ::a 12345678; proc f ::a(foo) {}; f x} -> {can't set "a(foo)": variable isn't array}
}
test catch.1 {catch {* 6 7}} -> 0
test catch.2 {catch {/ 1 0}} -> 1
test catch.3 {/ 1 0} -> "divide by zero"
if $test_config(picol) {
test catch.4 {catch {+ a b} res;set res} -> {expected integer but got "a"}
}
test catch.5 {% 1 0} -> "divide by zero"
if {$test_config(unix)} {
set hour [string range [clock format 0 -format %z] 1 2]
} else {
set hour [clock format 0 -format %H]
}
if $test_config(picol) {test clock.1 {clock format 0} -> "Thu Jan 01 $hour:00:00 1970"}
test clock.2 {clock format 0 -format %H:%M:%S} -> $hour:00:00
test clock.3 {
clock format
} ->* {*clock format clockval ?-format string?*}
unset hour
test concat.1 concat -> ""
test concat.2 {concat it} -> it
test concat.3 {concat one two three} -> {one two three}
test concat.4 {concat one {two three}} -> {one two three}
test concat.5 {concat {1 2} {3 4}} -> {1 2 3 4}
test concat.6 {concat {} {}} -> ""
test concat.7 {concat foo {} bar} -> {foo bar}
if {$test_config(picol)} {
test debug.1 {debug 0} -> 0
test debug.2 {debug} -> 0
test debug.3 {set res {}; lappend res [debug 1] [debug] [debug 0]; } -> {1 1 0}
}
if {$test_config(arrays)} {
test env.1 {catch {set ::env(PICOL)}} -> 1
test env.2 {set ::env(PICOL) world} -> world
test env.3 {set env(PICOL) blah} -> blah
test env.4 {set ::env(PICOL)} -> world
if {$test_config(picol)} {
test env.5 {array names ::env} -> PICOL
# Do not return the value of the corresponding environment variable
# when a key is missing in an array that is not ::env.
test env.6 {array set ::a {}; catch {set b $::a(PATH)}} -> 1
test env.7 {catch {set b $env(FOO))}} -> 1
# Do not populate ::env when other arrays are accessed.
test env.8 {array names ::env} -> PICOL
test env.9 {catch {set b $::env(FOO))}} -> 1
test env.10 {array names ::env} -> PICOL
}
test env.11.1 {info exists ::env(PATH)} -> 1 ;# should be there
test env.11.2 {uplevel #0 {info exists env(PATH)}} -> 1
test env.11.3 {apply {{} {info exists env(PATH)}}} -> 0
test env.12 {info exists ::env(HTAP)} -> 0
}
test errorinfo.1 {proc f x {/ $x 0}; catch {f 5} res; set res} -> {divide by zero}
test errorinfo.2 {proc f x {/ $x 0}; catch {f 5}; lrange $::errorInfo 0 2} -> {divide by zero}
if {!$test_config(tcl85)} {
test errorinfo.3 {proc f x {/ $x 0}; try {f 5}; lrange $::errorInfo 0 2} -> {divide by zero}
}
test escape.1 {set f hello\x41world} -> helloAworld
test escape.2 {set f {hello\x41world}} -> hello\\x41world
test eval.1 {set a {\t}; eval [list set b $a]} -> {\t}
test eval_mul.1 {eval * 8 7} -> 56
test eval_mul.2 {eval {* 4 5}} -> 20
if {$test_config(io)} {
test exec.1 {catch {exec ThisDoesNotExist}} -> 1
if {$test_config(unix)} {
test exec.2 {exec echo {Hello, World!}} -> {Hello, World!}
test exec.3 {exec echo {He said, "She said, 'Hello!'"}} -> {He said, "She said, 'Hello!'"}
}
if {$test_config(windows)} {
test exec.4 {exec cmd.exe /c echo Hello, World!} -> {Hello, World!}
test exec.5 {exec picolsh.exe qargv.pcl a b c} -> {{a b c}}
test exec.6 {exec picolsh.exe qargv.pcl {a b c}} -> {{{a b c}}}
test exec.7 {exec cmd.exe /c echo {Hello, World!}} -> {"Hello, World!"}
test exec.8 {exec picolsh.exe qargv.pcl {He said, "She said, 'Hello!'"}} -> \
{{{He said, "She said, 'Hello!'"}}}
test exec.9 {exec picolsh.exe qargv.pcl \
{They said, 'Hello!'} {"Hasta la vista, baby!"} Tab\ttab} -> \
[list [list {They said, 'Hello!'} {"Hasta la vista, baby!"} Tab\ttab]]
test exec.10 {exec picolsh.exe qargv.pcl &whoami} -> &whoami
test exec.11 {exec picolsh.exe qargv.pcl {\n} {\\\n} {\"}} -> {{{\n} {\\\n} {\"}}}
if {$test_config(picol)} {
test exec.12 {exec cmd.exe /c echo {\n} {\\\n} {\"}} -> {\n \\\n "\\\""}
}
}
if {$test_config(picol)} {
if {$test_config(unix)} {
test rawexec.1 {rawexec {echo "Hello, World!"}} -> {Hello, World!}
test rawexec.2 {rawexec echo {"Hello, World!"}} -> {Hello, World!}
} elseif {$test_config(windows)} {
test rawexec.3 {rawexec {echo "Hello, World!"}} -> {"Hello, World!"}
test rawexec.4 {rawexec echo {"Hello, World!"}} -> {"Hello, World!"}
}
}
}
test exit.1 {exit eh} -> {expected integer but got "eh"}
test expand.0 {{*}{}} -> {} ;# empty command
test expand.1 {list a {*}[list b c d] e} -> {a b c d e}
test expand.2 {list a {*}[list b c d]} -> {a b c d}
test expand.2a {list a {*}{b c d} e} -> {a b c d e}
test expand.3 {list {*}[list b c d] e} -> {b c d e}
test expand.4 {list a {*}[list b {c x y} d] e} -> {a b {c x y} d e}
test expand.5 {set x {f g h}; list a {*}$x i} -> {a f g h i}
test expand.6 {list a {*}{} b} -> {a b}
test expand.7 {list a {*}[list] b} -> {a b}
test expand.8 {list a {*}b c} -> {a b c}
test expand.9 {{*}{set x 45}} -> 45
test expand.10 {{*}[list set x 47]} -> 47
test expr.1 {expr 3 + 4} -> 7
test expr.2 {set x 5; expr $x * 4} -> 20
test expr.3 {expr 3 + 4 + 5} -> 12
test expr.4 {expr {3 + 4 + 7}} -> 14
test expr.5 {set x 8; expr {3 + 4 + $x}} -> 15
test expr.6 {expr 42} -> 42
test expr.7 {expr 0x00 + 0} -> 0
test expr.8 {expr 0xFF + 0} -> 255
test expr.9 {expr 0xab + 0} -> 171
test expr.10 {expr 0x01 + 0x02} -> 3
test expr.11 {expr 0x15 + 1} -> 22
test expr.12 {expr 0b1000 + 0b0111} -> 15
test expr.13 {expr 0o777 + 1} -> 512
test expr.14 {expr -0xFF + 0} -> -255
test expr.15 {expr -0xFF + 0} -> -255
test expr.16 {expr -0b1011 + 0} -> -11
test expr.17 {expr -0x122 + 0} -> -290
if {$test_config(picol)} {
test expr.18 {expr 0abcdef + 0} -> {expected integer but got "0abcdef"}
test expr.19 {expr 0xZZZ + 0} -> {expected integer but got "0xZZZ"}
test expr.20 {expr 0o9 + 0} -> {expected integer but got "0o9"}
test expr.21 {expr 0b00103 + 0} -> {expected integer but got "0b00103"}
test expr.22 {expr 0000255 + 0} -> 255
test expr.23 {expr -0000255 + 0} -> -255
}
test fac.1 {proc fac x {if [< $x 2] {return $x} else {* $x [fac [- $x 1]]}}; fac 5} -> 120
test fac.1a {proc fac x {if {$x < 2} {set x} else {* $x [fac [- $x 1]]}}; fac 6} -> 720
test fac.2 {fac 10} -> 3628800
if {$test_config(picol)} {
test fac.3 {
proc fac x {
try {
if {$x <= 1} {
return 1
} else {
apply {y {% [* $y [fac [- $y 1]]] 0xFFFF}} $x
}
}
}
fac 99
} -> {too many nested evaluations (infinite loop?)}
}
if {$test_config(io)} {
test file.ex.1 {file exists test.pcl} -> 1
test file.ex.2 {file exists does.not} -> 0
test file.ex.3 {file exists {globtest/test1}} -> 1
test file.ex.4 {file exists {globtest/foo bar}} -> 1
test file.ex.5 {file exists {./globtest/foo bar}} -> 1
if {$test_config(windows)} {
test file.ex.6 {file exists {globtest\test1}} -> 1
test file.ex.7 {file exists {globtest\foo bar}} -> 1
test file.ex.8 {file exists {.\globtest\foo bar}} -> 1
}
test file.isdir.1 {file isdirectory test.pcl} -> 0
test file.isdir.2 {file isdirectory globtest} -> 1
test file.isdir.3 {file isdirectory no_such_thing} -> 0
test file.isdir.4 {file isdir globtest} -> 1
test file.isdir.5 {file isdir no_such_thing} -> 0
test file.isfile.1 {file isfile test.pcl} -> 1
test file.isfile.2 {file isfile globtest} -> 0
test file.isfile.3 {file isfile no_such_thing} -> 0
if {[file isfile directory/file]} {
file delete directory/file
}
if {[file isdir directory]} {
file delete directory
}
test file.delete.1 {file delete no_such_thing} -> {} ;# No error.
test file.delete.2 {
close [open disposable w]
file delete disposable
} -> {}
if {$test_config(unix)} {
test file.delete.3 {
file delete /dev/null/blah
} ->* {error deleting "/dev/null/blah"*}
}
test file.delete.4 {
set exists [file isdir directory]
if {$::test_config(windows)} {
catch {exec cmd.exe /c mkdir directory}
} else {
catch {exec mkdir directory}
}
lappend exists [file isdir directory]
file delete directory
lappend exists [file isdir directory]
} -> {0 1 0}
test file.delete.5 {
set exists [file exists directory/file]
if {$::test_config(windows)} {
catch {exec cmd.exe /c mkdir directory}
} else {
catch {exec mkdir directory}
}
close [open directory/file w]
lappend exists [catch {file delete directory}]
lappend exists [file exists directory/file]
file delete directory/file
# The following works around a heisenbug on Windows.
for {set i 0} {[file exists directory/file]} {incr i} {
if {$i > 100} break
after 10
}
file delete directory
lappend exists [file exists directory/file]
set exists
} -> {0 1 1 0}
test file.1 {set f [open t.t w];puts $f hello;set x [tell $f];close $f; set x
} -> $test_config(hello_file_length)
test file.2 {set f [open t.t]; gets $f l; close $f; set l} -> hello
test file.3 {file size t.t} -> $test_config(hello_file_length)
test file.4 {
set f [open t.t]
set l [string trimright [read $f] \r\n]
close $f
set l
} -> hello
test file.5 {
read 12345678
} -> {can not find channel named "12345678"}
test file.6 {
gets 12345678
} -> {can not find channel named "12345678"}
test file.7 {
set f [open t.t]
close $f
catch {read $f} err
lrange $err 0 4
} -> {can not find channel named}
test file.8 {
set f [open t.t]
close $f
catch {close $f} err
lrange $err 0 4
} -> {can not find channel named}
if {$test_config(picol)} {
test file.9 {
set f [open picol.h rb]
set res [lindex [read $f $::tcl_platform(maxLength)] 1]
close $f
set res
} -> Tcl
test file.10 {
set f [open picol.h rb]
catch {read $f} res
close $f
set res
} -> {read contents too long}
test file.11 {
set f [open picol.h rb]
catch [list read $f [expr {$::tcl_platform(maxLength) + 1}]] res
close $f
set res
} -> [list size [expr {$::tcl_platform(maxLength) + 1}] too large]
}
}
test file.12.1 {file dirname /foo/bar/grill.txt} -> /foo/bar
test file.12.2 {file dirname /foo/bar/baz/} -> /foo/bar
test file.12.3 {file dirname /foo/bar/baz///} -> /foo/bar
test file.12.4 {file dirname /foo/bar/baz///qux} -> /foo/bar/baz
test file.12.5 {file dirname foo/bar/grill.txt} -> foo/bar
test file.12.6 {file dirname foo/bar/baz/} -> foo/bar
test file.12.7 {file dirname {}} -> .
test file.12.8 {file dirname /} -> /
test file.12.9 {file dirname ///} -> /
test file.13.1 {file tail /foo/bar/grill.txt} -> grill.txt
test file.13.2 {file tail /foo/bar/baz/} -> baz
test file.13.3 {file tail /foo/bar/baz///} -> baz
test file.13.4 {file dirname /foo/bar/baz///qux} -> /foo/bar/baz
test file.13.5 {file tail foo/bar/grill.txt} -> grill.txt
test file.13.6 {file tail foo/bar/baz/} -> baz
test file.13.7 {file tail {}} -> {}
test file.13.8 {file tail /} -> {}
test file.13.9 {file tail ///} -> {}
test file.14 {file join foo} -> foo
test file.15 {file join foo bar} -> foo/bar
test file.16 {file join foo /bar} -> /bar
if {$tcl_platform(platform) eq {windows}} {
test file.17 {file join foo C:/bar grill} -> C:/bar/grill
}
test file.18 {file split {/foo/space station/bar}} -> {/ foo {space station} bar}
test file.19 {file split {/foo/space station/bar/}} -> {/ foo {space station} bar}
test file.20 {file split {foo/space station/bar}} -> {foo {space station} bar}
test file.21 {file split foo///bar} -> {foo bar}
test file.22 {file split foo} -> foo
test file.23 {file split {/foo/bar///baz}} -> {/ foo bar baz}
test file.24 {file split {///foo/bar/baz}} -> {/ foo bar baz}
test file.25 {file split ~foo} -> ~foo
test file.26 {file split ~~~foo} -> ~~~foo
test file.27 {file split /foo/~bar/baz} -> {/ foo ./~bar baz}
test file.28 {file split /~foo/~bar/~baz} -> {/ ./~foo ./~bar ./~baz}
test file.29 {file split /foo/~~~bar/baz} -> {/ foo ./~~~bar baz}
test file.30 {file split ~foo/~bar/baz} -> {~foo ./~bar baz}
test for.1 {for {set i 0} {[< $i 4]} {incr i} {append r -$i}; set r
} -> -0-1-2-3
test for.2 {for {set i 0} {$i < 6} {incr i} {append r -$i}; set r} \
-> -0-1-2-3-4-5
test for.3 {for {set i 0} {[< $i 4]} {incr i} {append r -$i}; set r}\
-> -0-1-2-3
test for.4 {for {set i 0} {$i < 10} {incr i} {set i 99}; set i} -> 100
test for.5 {for {set i 0} {$i < 10} {incr i} {}} -> {}
test foreach.0 {set x ""; foreach i {} {append x ($i)}; set x} -> {}
test foreach.1 {set x ""; foreach i {a b c d e} {append x $i};set x} -> abcde
test foreach.2 {foreach i {a "b c" {d e} f} {append x $i};set x} -> {ab cd ef}
test foreach.3 {foreach i {a "b {} c" {d e} f} {append x $i};set x} -> {ab {} cd ef}
test foreach.4 {foreach i {a "b c" {d "x" e} f} {append x $i};set x} -> {ab cd "x" ef}
test foreach.5 {foreach {i j} {2 3 5 4 5 9} {append x $i/$j,};set x} -> 2/3,5/4,5/9,
test foreach.6 {foreach {i j} {2 3 5 4 5 9 0} {append x $i/$j,};set x} -> 2/3,5/4,5/9,0/,
test foreach.7 {foreach {i j k} {2 3 5 4 5 9 8} {append x $i+$j=$k,};set x} -> 2+3=5,4+5=9,8+=,
if {$test_config(picol)} {
test foreach.8 {catch {foreach a {1 2 3} b {x y z} {}}} -> 1
}
test foreach.9 {catch {foreach {}}} -> 1
test format.0 {format hello} -> hello
test format.1 {format %c 65} -> A
test format.2 {format %o 4711} -> 11147
test format.3 {format %X 255} -> FF
test format.4 {format %010d 255} -> 0000000255
test format.5 {format %-+-+-+d 127} -> +127
if {$test_config(picol)} {
test format.6 {format %#-010u 255} -> {255 }
test format.7 {format %n 0} -> {bad format string "%n"}
test format.8 {format %-0n 0} -> {bad format string "%-0n"}
test format.9 {format %0-n 0} -> {bad format string "%0-n"}
test format.10 {format {%s %s} hi} -> {bad format string "%s %s"}
}
if {$test_config(glob)} {
test glob.1 {lsort [glob globtest/*]} -> {globtest/Makefile {globtest/foo bar} globtest/test1 globtest/test2}
test glob.2 {lsort [glob -directory globtest *]} -> {globtest/Makefile {globtest/foo bar} globtest/test1 globtest/test2}
test glob.3 {lsort [glob -directory globtest test*]} -> {globtest/test1 globtest/test2}
test glob.4 {lsort [glob */test*]} -> {globtest/test1 globtest/test2}
test glob.5 {lsort [glob -directory globtest *foo*]} -> {{globtest/foo bar}}
test glob.6 {lsort [glob -dir globtest *foo*]} -> {{globtest/foo bar}}
}
set glo 42
test global.1 {proc f x {set ::glo}; f x} -> 42
test global.2 {proc f x {incr ::glo}; f x} -> 43
test global.2a {proc f x {global glo; incr glo}; f x} -> 44
test global.2b {variable x {1 2 3}; lset x 1 0} -> {1 0 3}
test global.3 {proc f x {global x}; f x} -> {variable "x" already exists}
test global.4 {proc f x {global glo; lsort [info vars]}; f x} -> {glo x}
test global.5 {proc f x {global glo; set glo}; f x} -> 44
test global.6 {proc f x {global glo; set glo $x}; f 56} -> 56
test global.7 {proc f x {global a b; set a 1; lsort [info vars]};f y} -> {a b x}
if {$test_config(picol)} {
set globals {
a x glo match r n tcl thisfile patchlevel _script_ auto_path \
argc argv argv0 errorInfo globals \
}
if {$test_config(arrays)} {
lappend globals env tcl_platform test_config
} else {
lappend globals \
tcl_platform(byteOrder) \
tcl_platform(engine) \
tcl_platform(maxLevel) \
tcl_platform(maxLength) \
tcl_platform(platform) \
tcl_platform(pointerSize) \
tcl_platform(wordSize) \
test_config(arrays) \
test_config(glob) \
test_config(hello_file_length) \
test_config(interp) \
test_config(io) \
test_config(newline) \
test_config(picol) \
test_config(regexp) \
test_config(tcl85) \
test_config(unix) \
test_config(windows)
}
test global.8 {proc g3 {} {lsort [info globals]}; g3} -> [lsort $globals]
unset globals
}
test global.9 {proc f x {global glo; return $glo}; f y} -> 56
test if.1 {set a no; if [> 1 0] {set a yes}; set a} -> yes
test if.2 {set a no; if [> 1 2] {set a yes}; set a} -> no
test if.3 {set a no; if {1 > 0} {set a yes}; set a} -> yes
test if.4 {set a no; if {1 > 2} {set a yes}; set a} -> no
test if.5 {set a no; if {$a eq "no"} {set a yes}; set a} -> yes
test if.6 {set a no; if {$a ne "no"} {set a yes}; set a} -> no
test if.7 {set a {a b c};if {[llength $a] == 3} {set a yes}; set a} -> yes
test if.8 {set a {a b};if {[llength $a] == 3} {set a yes}; set a} -> {a b}
test if.9 {if 1 {set a yes} else {set a no}} -> yes
test if.10 {if 0 {set a yes} else {set a no}} -> no
test if.11 {if 0 {set a yes}} -> ""
test if.12 {set a 1; if $a {set a 2}; set a} -> 2
test if.13 {set a 1; if !$a {set a 3}; set a} -> 1
test if.14 {set a 2; if !$a {set a 3}; set a} -> 2
test if.15 {set a 0; if !$a {set a 3}; set a} -> 3
test if.16 {if 0 {lindex foo}} -> {}
test if.17 {if 0 {lindex foo} else {lindex qux}} -> qux
test if.18 {
if 0 {lindex foo} elseif 1 {lindex bar} else {lindex qux}
} -> bar
test if.19 {
if 0 {lindex foo} elseif 0 {lindex bar} \
elseif 1 {lindex baz} else {lindex qux}
} -> baz
test if.20 {if 1 {lindex foo}} -> foo
test if.21 {if 1 {lindex foo} else {lindex qux}} -> foo
test if.22 {
if 1 {lindex foo} elseif 1 {lindex bar} else {lindex qux}
} -> foo
test if.23 {
if 0 {lindex foo} elseif 1 {lindex bar} \
elseif 0 {lindex baz} else {lindex qux}
} -> bar
test if.24 {
if 0 {lindex foo} elseif 0 {lindex bar}
} -> {}
test if.25 {
if 0 {lindex foo} elseif 0 {lindex bar} elseif 0 {lindex baz}
} -> {}
test if.26 {if 1 {} elseif} -> {wrong # args: no expression after "elseif" argument}
test if.27 {if 1 {} elseif 0} -> {wrong # args: no script following "0" argument}
test if.28 {if 1 {} elseif 0 {} else} -> {wrong # args: no script following "else" argument}
test if.29 {if 0 {} elseif} -> {wrong # args: no expression after "elseif" argument}
test if.30 {if 0 {} elseif 0} -> {wrong # args: no script following "0" argument}
test if.31 {if 0 {} elseif 1} -> {wrong # args: no script following "1" argument}
test if.32 {if 0 {} elseif 0 {} else} -> {wrong # args: no script following "else" argument}
test if.33 {if 0 {} elseif 1 {} else} -> {wrong # args: no script following "else" argument}
test if.34 {if 0 {} elseif 1 {} else {} x} -> {wrong # args: extra words after "else" clause in "if" command}
test if.35 {if 1 {} elseif 1 {} else {} x} -> {wrong # args: extra words after "else" clause in "if" command}
if $test_config(picol) {
test if.36 {if 0 {} nope} -> {expected "elseif" or "else"}
test if.37 {if 0 {} nope x} -> {expected "elseif" or "else"}
}
test if.38 {set x {}; if {$x eq {}} { return 1 }} -> 1
# test if.39 {set x \{; if {$x eq "\{"} { return 1 }} -> 1
# test if.40 {set x \}; if {$x eq "\}"} { return 1 }} -> 1
test if.41 {set x \[; if {$x eq "\["} { return 1 }} -> 1
test if.42 {set x \]; if {$x eq "\]"} { return 1 }} -> 1
test if.43 {set x \$; if {$x eq "$"} { return 1 }} -> 1
test if.44 {set x \"; if {$x eq "\""} { return 1 }} -> 1
test if.45 {set x {[exit]}; if {!$x} { return 1 }} ->* expected*
test if.46 {set x { }; if {$x} { return 1 }} ->* {*got " "*}
proc call {} {
incr ::calls
}
test if.38 {set ::calls 0; if {[call]} {}; return $::calls} -> 1
test if.39 {set ::calls 0; if {![call]} {}; return $::calls} -> 1
test if.40 {set ::calls 0; if {[call] > 108} {}; return $::calls} -> 1
catch {
unset calls
rename call {}
}
if $test_config(picol) {
test in.1 {set a 0; if {"c" in "a b c d"} {set a 1}} -> 1
test in.2 {expr {"x" in "a b c d"}} -> 0
test ni.1 {expr {"c" ni "a b c d"}} -> 0
test ni.2 {expr {"x" ni "a b c d"}} -> 1
}
test incr.1 {set i 0; incr i 3; set i} -> 3
test incr.2 {incr i x} -> {expected integer but got "x"}
test info.1 {catch info result; lrange $result 0 2} -> {wrong # args:}
proc f {a b} {+ $a $b}
test info.args.1 {info args f} -> {a b}
test info.body.1 {info body f} -> {+ $a $b}
if $test_config(picol) {
set result {abs after append apply}
if {$test_config(arrays)} {
lappend result array
}
test info.cmd.1 {lsort [info commands a*]} -> $result
unset result
}
set F [info level]
test info.level.0 {set ::F} -> 0
test info.level.1 {info level} -> 1
test info.level.2 {proc f {} {info level}; f} -> 2
test info.level.3 {proc f {x y} {info level 0}; f foo bar} -> {f foo bar}
test info.level.4 {uplevel 1 {info level 0}} -> {bad level "0"}
if $test_config(picol) {
set result {f g3 fac test}
if {$test_config(io)} {
lappend result unknown
}
test info.procs.1 {info procs} -> $result
unset result
}
test info.script.1 {info script} -> test.pcl
if {$test_config(interp)} {
test interp.1 {interp alias {} ll {} llength; ll {a b c}} -> 3
test interp.2 {set ::F [interp create]; list} -> ""
test interp.3 {interp eval $::F {llength {a b c d}}} -> 4
test interp.4 {interp alias $::F ll {} llength} -> ll
test interp.5 {interp eval $::F {ll {a b c d e}}} -> 5
test interp.6 {interp eval 12345678 {lindex BAM!}} -> {could not find interpreter "12345678"}
test interp.7 {catch interp} -> 1
test interp.8 {interp foo} ->* {bad option "foo"*}
test interp.9 {
proc foo {} {}
interp alias {} bar {} foo
interp alias {} baz {} foo
rename bar {}
rename baz {}
rename foo {}
} -> {}
test interp.10 {
interp alias {} bar {} set
interp alias {} baz {} set
rename bar {}
rename baz {}
} -> {}
test interp.11 {
proc foo {} {}
interp alias {} bar {} foo
interp alias {} baz {} foo
rename foo qux
rename bar {}
rename baz {}
rename qux {}
} -> {}
}
test join.1 {join {a b c d} ##} -> a##b##c##d
test join.2 {join {a b cx d} ""} -> abcxd
test join.3 {join {e f g h} ";"} -> "e;f;g;h"
test lappend.1 {set a w; lappend a x} -> {w x}
test lappend.2 {lappend a} -> {}
test lappend.3 {lappend a x y z; set a} -> {x y z}
test lappend.4 {lappend a x {y z}; set a} -> {x {y z}}
test lassign.1 {lassign {} a b c; list $a $b $c} -> {{} {} {}}
test lassign.2 {lassign {foo} a b c; list $a $b $c} -> {foo {} {}}
test lassign.3 {lassign {foo bar baz} a b c; list $a $b $c} -> {foo bar baz}
test lassign.4 {set rem [lassign {foo bar baz qux quux} a b c]; list $a $b $c $rem} -> {foo bar baz {qux quux}}
test line-continuation.1 {
lindex "foo\
bar"
} -> {foo bar}
test line-continuation.2 {
lindex {foo\
bar}
} -> {foo bar}
test line-continuation.3 {
list {*}"foo\
bar"
} -> {foo bar}
test line-continuation.4 {
# Tabs and spaces.
eval "list {*}\"foo\\\n\t \t \t bar\""
} -> {foo bar}
test line-continuation.5 {
list {*}{foo\
bar}
} -> {foo bar}
test line-continuation.6 {
# Tabs and spaces.
eval "list {*}{foo\\\n\t \t \t bar}"
} -> {foo bar}
test line-continuation.7 {
lindex "\
foo\
bar\
baz\
"
} -> { foo bar baz }
test line-continuation.8 {
lindex {\
foo\
bar\
baz\
}
} -> { foo bar baz }
test line-continuation.9 {
lindex {# comment \
line}
} -> {# comment line}
test line-continuation.10 {
eval {# comment \
line}
} -> {}
test line-continuation.11 {
set {a b} 5
set "a\
b"
} -> 5
test line-continuation.12 {
set {a b} 5
set {a\
b}
} -> 5
test line-continuation.13 {
set {a b} 5
lindex ${a\
b}
} -> 5
test line-continuation.14 {
lindex {a\\
b}
} -> "a\\\\\n b"
test lindex.1 {lindex {a b c} 1} -> b
test lindex.2 {lindex {a b c d e} 0} -> a
test lindex.3 {lindex " a " 0} -> a
test lindex.4 {lindex " \t \n a \t \n b " 0} -> a
test lindex.5 {lindex " \t \n a \t \n b " 1} -> b
test lindex.6 {lindex " \t \n a \t \n b " 2} -> {}
test lindex.7 {lindex " \t \n {hello world} \t \n " 0} -> {hello world}
test lindex.8 {lindex " \t \n {hello world} \t \n " 1} -> {}
test lindex.9 {lindex {{a} {b} {c}} 1} -> b
test lindex.10 {lindex {a b c} 1} -> b
test lindex.11 {lindex {a b c}} -> {a b c}
test lindex.12 {lindex {}} -> {}
test lindex.13 {lindex {a b "c"} 3} -> {}
test lindex.14 {lindex {a b"c"} 1} -> {b"c"}
test lindex.15 {lindex {a b"c"} 2} -> {}
if {$test_config(picol)} {
# In lindex.16-lindex.18 we expect Picol to do what Jim Tcl, not Tcl 8.x,
# does. In Tcl 8.x attempting to [lindex] this string would throw an error.
# If we chose to treat it the Jim way, we can keep the assumption that list
# parsing never fails.
test lindex.16 {lindex {a "b"c} 0} -> a
test lindex.17 {lindex {a "b"c} 1} -> b
test lindex.18 {lindex {a "b"c} 2} -> c
}
test lindex.19 {lindex {a"b"c} 0} -> {a"b"c}
test lindex.20 {lindex {0 1 2 3 4 5} end} -> 5
test lindex.20 {lindex 0 end} -> 0
test lindex.21 {lindex {} end} -> {}
test lindex.22 {lindex {} -42} -> {}
test lindex.23 {lindex {a b c} -1} -> {}
test lindex.24 {lindex {a b c} -2} -> {}