Trim bootstrap jimsh
[jimtcl.git] / tests / dict2.test
blob2e9bcd4e5916f8e0bb6b40e0e6d08d6fe2db1e76
1 # This test file covers the dictionary object type and the dict command used
2 # to work with values of that type.
4 # This file contains a collection of tests for one or more of the Tcl built-in
5 # commands. Sourcing this file into Tcl runs the tests and generates output
6 # for errors.  No output means no errors were found.
8 # Copyright (c) 2003-2009 Donal K. Fellows
9 # See the file "license.terms" for information on usage and redistribution of
10 # this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 source [file dirname [info script]]/testing.tcl
14 # jim dicts don't preserve order, so always sort
15 # before checking results
16 proc dict-sort {dict} {
17     set result {}
18     foreach k [lsort [dict keys $dict]] {
19         lappend result $k [dict get $dict $k]
20     }
21     return $result
24 test dict-1.1 {dict command basic syntax} -returnCodes error -body {
25     dict
26 }  -match glob -result {wrong # args: should be "dict subcommand ?arg* ...?"}
27 test dict-1.2 {dict command basic syntax} -returnCodes error -body {
28     dict ?
29 } -match glob -result *
31 test dict-2.1 {dict create command} {
32     dict create
33 } {}
34 test dict-2.2 {dict create command} {
35     dict create a b
36 } {a b}
37 test dict-2.3 {dict create command} -body {
38     set result {}
39     set dict [dict create a b c d]
40     # Can't compare directly as ordering of values is undefined
41     foreach key {a c} {
42         set idx [lsearch -exact $dict $key]
43         if {$idx & 1} {
44             error "found $key at odd index $idx in $dict"
45         }
46         lappend result [lindex $dict [expr {$idx+1}]]
47     }
48     return $result
49 } -cleanup {
50     unset result dict key idx
51 } -result {b d}
52 test dict-2.4 {dict create command} -returnCodes error -body {
53     dict create a
54 } -result {wrong # args: should be "dict create ?key value ...?"}
55 test dict-2.5 {dict create command} -returnCodes error -body {
56     dict create a b c
57 } -result {wrong # args: should be "dict create ?key value ...?"}
58 test dict-2.6 {dict create command - initialse refcount field!} -body {
59     # Bug 715751 will show up in memory debuggers like purify
60     for {set i 0} {$i<10} {incr i} {
61         set dictv [dict create a 0]
62         if {[catch {
63             set share [dict values $dictv]
64         }]} {
65             set share [array get dictv]
66         }
67         list [dict incr dictv a]
68     }
69 } -cleanup {
70     unset i dictv share
71 } -result {}
72 test dict-2.7 {dict create command - #-quoting in string rep} {
73     dict create # #comment
74 } {{#} #comment}
75 test dict-2.8 {dict create command - #-quoting in string rep} -body {
76     dict create #a x #b x
77 } -match glob -result {{#?} x #? x}
79 test dict-3.1 {dict get command} {dict get {a b} a} b
80 test dict-3.2 {dict get command} {dict get {a b c d} a} b
81 test dict-3.3 {dict get command} {dict get {a b c d} c} d
82 test dict-3.4 {dict get command} -returnCodes error -body {
83     dict get {a b c d} b
84 } -result {key "b" not known in dictionary}
85 test dict-3.5 {dict get command} {dict get {a {p q r s} b {u v x y}} a p} q
86 test dict-3.6 {dict get command} {dict get {a {p q r s} b {u v x y}} a r} s
87 test dict-3.7 {dict get command} {dict get {a {p q r s} b {u v x y}} b u} v
88 test dict-3.8 {dict get command} {dict get {a {p q r s} b {u v x y}} b x} y
89 test dict-3.9 {dict get command} -returnCodes error -body {
90     dict get {a {p q r s} b {u v x y}} a z
91 } -result {key "z" not known in dictionary}
92 test dict-3.10 {dict get command} -returnCodes error -body {
93     dict get {a {p q r s} b {u v x y}} c z
94 } -result {key "c" not known in dictionary}
95 test dict-3.11 {dict get command} {dict get [dict create a b c d] a} b
96 test dict-3.12 {dict get command} -returnCodes error -body {
97     dict get
98 } -result {wrong # args: should be "dict get dictionary ?key ...?"}
99 test dict-3.13 {dict get command} -body {
100     set dict [dict get {a b c d}]
101     if {$dict eq "a b c d"} {
102         return OK
103     } elseif {$dict eq "c d a b"} {
104         return reordered
105     } else {
106         return $dict
107     }
108 } -cleanup {
109     unset dict
110 } -result OK
111 test dict-3.14 {dict get command} -returnCodes error -body {
112     dict get {a b c d} a c
113 } -result {missing value to go with key}
114 test dict-3.15 {compiled dict get error cleanliness - Bug 2431847} -body {
115     proc x {} {
116         dict set a(z) b c
117         dict get $a(z) d
118     }
119     x
120 } -returnCodes error -result {key "d" not known in dictionary}
121 test dict-3.16 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3}
122 test dict-3.17 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
123 test dict-3.18 {array set non-dict get command} -constraints jim -returnCodes error -body {
124     set a one
125     array set a {a b c d}
126 } -result {missing value to go with key}
128 test dict-4.1 {dict replace command} {
129     dict replace {a b c d}
130 } {a b c d}
131 test dict-4.2 {dict replace command} {
132     dict-sort [dict replace {a b c d} e f]
133 } {a b c d e f}
134 test dict-4.3 {dict replace command} {
135     dict-sort [dict replace {a b c d} c f]
136 } {a b c f}
137 test dict-4.4 {dict replace command} {
138     dict-sort [dict replace {a b c d} c x a y]
139 } {a y c x}
140 test dict-4.5 {dict replace command} -returnCodes error -body {
141     dict replace
142 } -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
143 test dict-4.6 {dict replace command} -returnCodes error -body {
144     dict replace {a a} a
145 } -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
146 test dict-4.7 {dict replace command} -returnCodes error -body {
147     dict replace {a a a} a b
148 } -result {missing value to go with key}
149 test dict-4.8 {dict replace command} -returnCodes error -body {
150     dict replace [list a a a] a b
151 } -result {missing value to go with key}
152 test dict-4.9 {dict replace command} {dict replace [list a a] a b} {a b}
153 test dict-4.10 {dict replace command} {dict replace [list a a] a b a c} {a c}
155 test dict-5.1 {dict remove command} {dict remove {a b c d} a} {c d}
156 test dict-5.2 {dict remove command} {dict remove {a b c d} c} {a b}
157 test dict-5.3 {dict remove command} {dict remove {a b c d} a c} {}
158 test dict-5.4 {dict remove command} {dict remove {a b c d} c a} {}
159 test dict-5.5 {dict remove command} {
160     dict remove {a b c d}
161 } {a b c d}
162 test dict-5.6 {dict remove command} {dict remove {a b} c} {a b}
163 test dict-5.7 {dict remove command} -returnCodes error -body {
164     dict remove
165 } -result {wrong # args: should be "dict remove dictionary ?key ...?"}
167 test dict-6.1 {dict keys command} {dict keys {a b}} a
168 test dict-6.2 {dict keys command} {dict keys {c d}} c
169 test dict-6.3 {dict keys command} {lsort [dict keys {a b c d}]} {a c}
170 test dict-6.4 {dict keys command} {dict keys {a b c d} a} a
171 test dict-6.5 {dict keys command} {dict keys {a b c d} c} c
172 test dict-6.6 {dict keys command} {dict keys {a b c d} e} {}
173 test dict-6.7 {dict keys command} {lsort [dict keys {a b c d ca da} c*]} {c ca}
174 test dict-6.8 {dict keys command} -returnCodes error -body {
175     dict keys
176 } -result {wrong # args: should be "dict keys dictionary ?pattern?"}
177 test dict-6.9 {dict keys command} -returnCodes error -body {
178     dict keys {} a b
179 } -result {wrong # args: should be "dict keys dictionary ?pattern?"}
180 test dict-6.10 {dict keys command} -returnCodes error -body {
181     dict keys a
182 } -result {missing value to go with key}
184 test dict-7.1 {dict values command} {dict values {a b}} b
185 test dict-7.2 {dict values command} {dict values {c d}} d
186 test dict-7.3 {dict values command} {lsort [dict values {a b c d}]} {b d}
187 test dict-7.4 {dict values command} {dict values {a b c d} b} b
188 test dict-7.5 {dict values command} {dict values {a b c d} d} d
189 test dict-7.6 {dict values command} {dict values {a b c d} e} {}
190 test dict-7.7 {dict values command} {lsort [dict values {a b c d ca da} d*]} {d da}
191 test dict-7.8 {dict values command} -returnCodes error -body {
192     dict values
193 } -result {wrong # args: should be "dict values dictionary ?pattern?"}
194 test dict-7.9 {dict values command} -returnCodes error -body {
195     dict values {} a b
196 } -result {wrong # args: should be "dict values dictionary ?pattern?"}
197 test dict-7.10 {dict values command} -returnCodes error -body {
198     dict values a
199 } -result {missing value to go with key}
201 test dict-8.1 {dict size command} {dict size {}} 0
202 test dict-8.2 {dict size command} {dict size {a b}} 1
203 test dict-8.3 {dict size command} {dict size {a b c d}} 2
204 test dict-8.4 {dict size command} -returnCodes error -body {
205     dict size
206 } -result {wrong # args: should be "dict size dictionary"}
207 test dict-8.5 {dict size command} -returnCodes error -body {
208     dict size a b
209 } -result {wrong # args: should be "dict size dictionary"}
210 test dict-8.6 {dict size command} -returnCodes error -body {
211     dict size a
212 } -result {missing value to go with key}
214 test dict-9.1 {dict exists command} {dict exists {a b} a} 1
215 test dict-9.2 {dict exists command} {dict exists {a b} b} 0
216 test dict-9.3 {dict exists command} {dict exists {a {b c}} a b} 1
217 test dict-9.4 {dict exists command} {dict exists {a {b c}} a c} 0
218 test dict-9.5 {dict exists command} {dict exists {a {b c}} b c} 0
219 test dict-9.6 {dict exists command} -returnCodes error -body {
220     dict exists {a {b c d}} a c
221 } -result {missing value to go with key}
222 test dict-9.7 {dict exists command} -returnCodes error -body {
223     dict exists
224 } -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
225 test dict-9.8 {dict exists command} -returnCodes error -body {
226     dict exists {}
227 } -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
229 #test dict-10.1 {dict info command} -body {
230 #    # Actual string returned by this command is undefined; it is
231 #    # intended for human consumption and not for use by scripts.
232 #    dict info {}
233 #} -match glob -result *
234 #test dict-10.2 {dict info command} -returnCodes error -body {
235 #    dict info
236 #} -result {wrong # args: should be "dict info dictionary"}
237 #test dict-10.3 {dict info command} -returnCodes error -body {
238 #    dict info {} x
239 #} -result {wrong # args: should be "dict info dictionary"}
240 #test dict-10.4 {dict info command} -returnCodes error -body {
241 #    dict info x
242 #} -result {missing value to go with key}
244 test dict-11.1 {dict incr command: unshared value} -body {
245     set dictv [dict create \
246             a [string index "=0=" 1] \
247             b [expr {1+2}] \
248             c [expr {0x80000000+1}]]
249     dict incr dictv a
250         dict-sort $dictv
251 } -cleanup {
252     unset dictv
253 } -result {a 1 b 3 c 2147483649}
254 test dict-11.2 {dict incr command: unshared value} -body {
255     set dictv [dict create \
256             a [string index "=0=" 1] \
257             b [expr {1+2}] \
258             c [expr {0x80000000+1}]]
259     dict incr dictv b
260         dict-sort $dictv
261 } -cleanup {
262     unset dictv
263 } -result {a 0 b 4 c 2147483649}
264 test dict-11.3 {dict incr command: unshared value} -body {
265     set dictv [dict create \
266             a [string index "=0=" 1] \
267             b [expr {1+2}] \
268             c [expr {0x80000000+1}]]
269     dict incr dictv c
270         dict-sort $dictv
271 } -cleanup {
272     unset dictv
273 } -result {a 0 b 3 c 2147483650}
274 test dict-11.4 {dict incr command: shared value} -body {
275     set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
276     set sharing [dict values $dictv]
277     dict incr dictv a
278         dict-sort $dictv
279 } -cleanup {
280     unset dictv sharing
281 } -result {a 1 b 3 c 2147483649}
282 test dict-11.5 {dict incr command: shared value} -body {
283     set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
284     set sharing [dict values $dictv]
285     dict incr dictv b
286         dict-sort $dictv
287 } -cleanup {
288     unset dictv sharing
289 } -result {a 0 b 4 c 2147483649}
290 test dict-11.6 {dict incr command: shared value} -body {
291     set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
292     set sharing [dict values $dictv]
293     dict incr dictv c
294         dict-sort $dictv
295 } -cleanup {
296     unset dictv sharing
297 } -result {a 0 b 3 c 2147483650}
298 test dict-11.7 {dict incr command: unknown values} -body {
299     set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
300     dict incr dictv d
301         dict-sort $dictv
302 } -cleanup {
303     unset dictv
304 } -result {a 0 b 3 c 2147483649 d 1}
305 test dict-11.8 {dict incr command} -body {
306     set dictv {a 1}
307     dict incr dictv a 2
308         dict-sort $dictv
309 } -cleanup {
310     unset dictv
311 } -result {a 3}
312 test dict-11.9 {dict incr command} -returnCodes error -body {
313     set dictv {a dummy}
314     dict incr dictv a
315         dict-sort $dictv
316 } -cleanup {
317     unset dictv
318 } -result {expected integer but got "dummy"}
319 test dict-11.10 {dict incr command} -returnCodes error -body {
320     set dictv {a 1}
321     dict incr dictv a dummy
322         dict-sort $dictv
323 } -cleanup {
324     unset dictv
325 } -result {expected integer but got "dummy"}
326 test dict-11.11 {dict incr command} -setup {
327     unset -nocomplain dictv
328 } -body {
329     dict incr dictv a
330         dict-sort $dictv
331 } -cleanup {
332     unset dictv
333 } -result {a 1}
334 test dict-11.12 {dict incr command} -returnCodes error -body {
335     set dictv a
336     dict incr dictv a
337         dict-sort $dictv
338 } -cleanup {
339     unset dictv
340 } -result {missing value to go with key}
341 test dict-11.13 {dict incr command} -returnCodes error -body {
342     set dictv a
343     dict incr dictv a a a
344         dict-sort $dictv
345 } -cleanup {
346     unset dictv
347 } -result {wrong # args: should be "dict incr varName key ?increment?"}
348 test dict-11.14 {dict incr command} -returnCodes error -body {
349     set dictv a
350     dict incr dictv
351         dict-sort $dictv
352 } -cleanup {
353     unset dictv
354 } -result {wrong # args: should be "dict incr varName key ?increment?"}
355 test dict-11.15 {dict incr command: write failure} -setup {
356     unset -nocomplain dictVar
357 } -body {
358     set dictVar 1
359     dict incr dictVar a
360         dict-sort $dictv
361 } -returnCodes error -cleanup {
362     unset dictVar
363 } -result {missing value to go with key}
364 test dict-11.16 {dict incr command: compilation} {
365     apply {{} {
366         set v {a 0 b 0 c 0}
367         dict incr v a
368         dict incr v b 1
369         dict incr v c 2
370         dict incr v d 3
371         list [dict get $v a] [dict get $v b] [dict get $v c] [dict get $v d]
372     }}
373 } {1 1 2 3}
374 test dict-11.17 {dict incr command: compilation} {
375     apply {{} {
376         set dictv {a 1}
377         dict incr dictv a 2
378         dict-sort $dictv
379     }}
380 } {a 3}
382 test dict-12.1 {dict lappend command} -body {
383     set dictv {a a}
384     dict lappend dictv a
385 } -cleanup {
386     unset dictv
387 } -result {a a}
388 test dict-12.2 {dict lappend command} -body {
389     set dictv {a a}
390     set sharing [dict values $dictv]
391     dict lappend dictv a b
392         dict-sort $dictv
393 } -cleanup {
394     unset dictv sharing
395 } -result {a {a b}}
396 test dict-12.3 {dict lappend command} -body {
397     set dictv {a a}
398     dict lappend dictv a b c
399         dict-sort $dictv
400 } -cleanup {
401     unset dictv
402 } -result {a {a b c}}
403 test dict-12.2.1 {dict lappend command} -body {
404     set dictv [dict create a [string index =a= 1]]
405     dict lappend dictv a b
406         dict-sort $dictv
407 } -cleanup {
408     unset dictv
409 } -result {a {a b}}
410 test dict-12.4 {dict lappend command} -body {
411     set dictv {}
412     dict lappend dictv a x y z
413         dict-sort $dictv
414 } -cleanup {
415     unset dictv
416 } -result {a {x y z}}
417 test dict-12.5 {dict lappend command} -body {
418     unset -nocomplain dictv
419     dict lappend dictv a b
420         dict-sort $dictv
421 } -cleanup {
422     unset dictv
423 } -result {a b}
424 test dict-12.6 {dict lappend command} -returnCodes error -body {
425     set dictv a
426     dict lappend dictv a a
427         dict-sort $dictv
428 } -cleanup {
429     unset dictv
430 } -result {missing value to go with key}
431 test dict-12.7 {dict lappend command} -returnCodes error -body {
432     dict lappend
433 } -result {wrong # args: should be "dict lappend varName key ?value ...?"}
434 test dict-12.8 {dict lappend command} -returnCodes error -body {
435     dict lappend dictv
436 } -result {wrong # args: should be "dict lappend varName key ?value ...?"}
437 test dict-12.9 {dict lappend command} -returnCodes error -constraints tcl -body {
438     set dictv [dict create a "\{"]
439     dict lappend dictv a a
440 } -cleanup {
441     unset dictv
442 } -result {unmatched open brace in list}
443 test dict-12.10 {dict lappend command: write failure} -setup {
444     unset -nocomplain dictVar
445 } -body {
446     set dictVar 1
447     dict lappend dictVar a x
448 } -returnCodes error -cleanup {
449     unset dictVar
450 } -result {missing value to go with key}
451 test dict-12.11 {compiled dict append: invalidate string rep - Bug 3079830} {
452     dict-sort [apply {{} {set d {a 1 b 2 c 3}; dict lappend d b 22}}]
453 } {a 1 b {2 22} c 3}
455 test dict-13.1 {dict append command} -body {
456     set dictv {a a}
457     dict append dictv a
458 } -cleanup {
459     unset dictv
460 } -result {a a}
461 test dict-13.2 {dict append command} -body {
462     set dictv {a a}
463     set sharing [dict values $dictv]
464     dict append dictv a b
465 } -cleanup {
466     unset dictv sharing
467 } -result {a ab}
468 test dict-13.3 {dict append command} -body {
469     set dictv {a a}
470     dict append dictv a b c
471 } -cleanup {
472     unset dictv
473 } -result {a abc}
474 test dict-13.2.1 {dict append command} -body {
475     set dictv [dict create a [string index =a= 1]]
476     dict append dictv a b
477 } -cleanup {
478     unset dictv
479 } -result {a ab}
480 test dict-13.4 {dict append command} -body {
481     set dictv {}
482     dict append dictv a x y z
483 } -cleanup {
484     unset dictv
485 } -result {a xyz}
486 test dict-13.5 {dict append command} -body {
487     unset -nocomplain dictv
488     dict append dictv a b
489 } -cleanup {
490     unset dictv
491 } -result {a b}
492 test dict-13.6 {dict append command} -returnCodes error -body {
493     set dictv a
494     dict append dictv a a
495 } -cleanup {
496     unset dictv
497 } -result {missing value to go with key}
498 test dict-13.7 {dict append command} -returnCodes error -body {
499     dict append
500 } -result {wrong # args: should be "dict append varName key ?value ...?"}
501 test dict-13.8 {dict append command} -returnCodes error -body {
502     dict append dictv
503 } -result {wrong # args: should be "dict append varName key ?value ...?"}
504 test dict-13.9 {dict append command: write failure} -setup {
505     unset -nocomplain dictVar
506 } -body {
507     set dictVar 1
508     dict append dictVar a x
509 } -returnCodes error -cleanup {
510     unset dictVar
511 } -result {missing value to go with key}
512 test dict-13.10 {compiled dict append: crash case} {
513     apply {{} {dict append dictVar a o k}}
514 } {a ok}
515 test dict-13.11 {compiled dict append: invalidate string rep - Bug 3079830} {
516     dict-sort [apply {{} {set d {a 1 b 2 c 3}; dict append d b 22}}]
517 } {a 1 b 222 c 3}
519 test dict-14.1 {dict for command: syntax} -returnCodes error -body {
520     dict for
521 } -match glob -result {wrong # args: should be *}
522 test dict-14.2 {dict for command: syntax} -returnCodes error -body {
523     dict for x
524 } -match glob -result {wrong # args: should be *}
525 test dict-14.3 {dict for command: syntax} -returnCodes error -body {
526     dict for x x
527 } -match glob -result {wrong # args: should be *}
528 test dict-14.4 {dict for command: syntax} -returnCodes error -body {
529     dict for x x x x
530 } -match glob -result {wrong # args: should be *}
531 test dict-14.5 {dict for command: syntax} -returnCodes error -body {
532     dict for x x x
533 } -result {must have exactly two variable names}
534 test dict-14.6 {dict for command: syntax} -returnCodes error -body {
535     dict for {x x x} x x
536 } -result {must have exactly two variable names}
537 test dict-14.7 {dict for command: syntax} -returnCodes error -constraints tcl -body {
538     dict for "\{x" x x
539 } -result {unmatched open brace in list}
540 test dict-14.8 {dict for command} -constraints tcl -body {
541     # This test confirms that [dict keys], [dict values] and [dict for]
542     # all traverse a dictionary in the same order.
543         # Note that Jim Tcl does *not* preserver order
544     set dictv {a A b B c C}
545     set keys {}
546     set values {}
547     dict for {k v} $dictv {
548         lappend keys $k
549         lappend values $v
550     }
551     set result [expr {
552         $keys eq [dict keys $dictv] && $values eq [dict values $dictv]
553     }]
554     expr {$result ? "YES" : [list "NO" $dictv $keys $values]}
555 } -cleanup {
556     unset result keys values k v dictv
557 } -result YES
558 test dict-14.9 {dict for command} {
559     dict for {k v} {} {
560         error "unexpected execution of 'dict for' body"
561     }
562 } {}
563 test dict-14.10 {dict for command: script results} -body {
564     set times 0
565     dict for {k v} {a a b b} {
566         incr times
567         continue
568         error "shouldn't get here"
569     }
570     return $times
571 } -cleanup {
572     unset times k v
573 } -result 2
574 test dict-14.11 {dict for command: script results} -body {
575     set times 0
576     dict for {k v} {a a b b} {
577         incr times
578         break
579         error "shouldn't get here"
580     }
581     return $times
582 } -cleanup {
583     unset times k v
584 } -result 1
585 test dict-14.12 {dict for command: script results} -body {
586     set times 0
587     list [catch {
588         dict for {k v} {a a b b} {
589             incr times
590             error test
591         }
592     } msg] $msg $times
593 } -cleanup {
594     unset times k v msg
595 } -result {1 test 1}
596 test dict-14.13 {dict for command: script results} {
597     apply {{} {
598         dict for {k v} {a b} {
599             return ok,$k,$v
600             error "skipped return completely"
601         }
602         error "return didn't go far enough"
603     }}
604 } ok,a,b
605 test dict-14.14 {dict for command: handle representation loss} -body {
606     set dictVar {a b c d e f g h}
607     set keys {}
608     set values {}
609     dict for {k v} $dictVar {
610         if {[llength $dictVar]} {
611             lappend keys $k
612             lappend values $v
613         }
614     }
615     list [lsort $keys] [lsort $values]
616 } -cleanup {
617     unset dictVar keys values k v
618 } -result {{a c e g} {b d f h}}
619 test dict-14.15 {dict for command: keys are unique and iterated over once only} -setup {
620     unset -nocomplain accum
621     array set accum {}
622 } -body {
623     set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
624     dict for {k v} $dictVar {
625         append accum($k) $v,
626     }
627     set result [lsort [array names accum]]
628     lappend result :
629     foreach k $result {
630         catch {lappend result $accum($k)}
631     }
632     return $result
633 } -cleanup {
634     unset dictVar k v result accum
635 } -result {a1 a2 b1 b2 bar foo : a, b, c, d, foo, bar,}
636 test dict-14.16 {dict for command in compilation context} {
637     apply {{} {
638         set res {x x x x x x}
639         dict for {k v} {a 0 b 1 c 2 d 3 e 4 f 5} {
640             lset res $v $k
641             continue
642         }
643         return $res
644     }}
645 } {a b c d e f}
646 test dict-14.17 {dict for command in compilation context} {
647     # Bug 1379349
648     apply {{} {
649         set d [dict create a 1]         ;# Dict must be unshared!
650         dict for {k v} $d {
651             dict set d $k 0             ;# Any modification will do
652         }
653         return $d
654     }}
655 } {a 0}
656 test dict-14.18 {dict for command in compilation context} {
657     # Bug 1382528
658     apply {{} {
659         dict for {k v} {} {}            ;# Note empty dict
660         catch { error foo }             ;# Note compiled [catch]
661     }}
662 } 1
663 test dict-14.19 {dict for and invalid dicts: bug 1531184} -body {
664     di[list]ct for {k v} x {}
665 } -returnCodes 1 -result {missing value to go with key}
666 test dict-14.20 {dict for stack space compilation: bug 1903325} {
667     apply {{x y args} {
668         dict for {a b} $x {}
669         concat "c=$y,$args"
670     }} {} 1 2 3
671 } {c=1,2 3}
672 # There's probably a lot more tests to add here. Really ought to use a
673 # coverage tool for this job...
675 test dict-15.1 {dict set command} -body {
676     set dictVar {}
677     dict set dictVar a x
678 } -cleanup {
679     unset dictVar
680 } -result {a x}
681 test dict-15.2 {dict set command} -body {
682     set dictvar {a {}}
683     dict set dictvar a b x
684 } -cleanup {
685     unset dictvar
686 } -result {a {b x}}
687 test dict-15.3 {dict set command} -body {
688     set dictvar {a {b {}}}
689     dict set dictvar a b c x
690 } -cleanup {
691     unset dictvar
692 } -result {a {b {c x}}}
693 test dict-15.4 {dict set command} -body {
694     set dictVar {a y}
695     dict set dictVar a x
696 } -cleanup {
697     unset dictVar
698 } -result {a x}
699 test dict-15.5 {dict set command} -body {
700     set dictVar {a {b y}}
701     dict set dictVar a b x
702 } -cleanup {
703     unset dictVar
704 } -result {a {b x}}
705 test dict-15.6 {dict set command} -body {
706     set dictVar {a {b {c y}}}
707     dict set dictVar a b c x
708 } -cleanup {
709     unset dictVar
710 } -result {a {b {c x}}}
711 test dict-15.7 {dict set command: path creation} -body {
712     set dictVar {}
713     dict set dictVar a b x
714 } -cleanup {
715     unset dictVar
716 } -result {a {b x}}
717 test dict-15.8 {dict set command: creates variables} -setup {
718     unset -nocomplain dictVar
719 } -body {
720     dict set dictVar a x
721     return $dictVar
722 } -cleanup {
723     unset dictVar
724 } -result {a x}
725 test dict-15.9 {dict set command: write failure} -setup {
726     unset -nocomplain dictVar
727 } -body {
728     set dictVar 1
729     dict set dictVar a x
730 } -returnCodes error -cleanup {
731     unset dictVar
732 } -result {missing value to go with key}
733 test dict-15.10 {dict set command: syntax} -returnCodes error -body {
734     dict set
735 } -result {wrong # args: should be "dict set varName key ?key ...? value"}
736 test dict-15.11 {dict set command: syntax} -returnCodes error -body {
737     dict set a
738 } -result {wrong # args: should be "dict set varName key ?key ...? value"}
739 test dict-15.12 {dict set command: syntax} -returnCodes error -body {
740     dict set a a
741 } -result {wrong # args: should be "dict set varName key ?key ...? value"}
742 test dict-15.13 {dict set command} -returnCodes error -body {
743     set dictVar a
744     dict set dictVar b c
745 } -cleanup {
746     unset dictVar
747 } -result {missing value to go with key}
749 test dict-16.1 {dict unset command} -body {
750     set dictVar {a b c d}
751     dict unset dictVar a
752 } -cleanup {
753     unset dictVar
754 } -result {c d}
755 test dict-16.2 {dict unset command} -body {
756     set dictVar {a b c d}
757     dict unset dictVar c
758 } -cleanup {
759     unset dictVar
760 } -result {a b}
761 test dict-16.3 {dict unset command} -body {
762     set dictVar {a b}
763     dict unset dictVar c
764 } -cleanup {
765     unset dictVar
766 } -result {a b}
767 test dict-16.4 {dict unset command} -body {
768     set dictVar {a {b c d e}}
769     dict unset dictVar a b
770 } -cleanup {
771     unset dictVar
772 } -result {a {d e}}
773 test dict-16.5 {dict unset command} -returnCodes error -body {
774     set dictVar a
775     dict unset dictVar a
776 } -cleanup {
777     unset dictVar
778 } -result {missing value to go with key}
779 test dict-16.6 {dict unset command} -returnCodes error -body {
780     set dictVar {a b}
781     dict unset dictVar c d
782 } -cleanup {
783     unset dictVar
784 } -result {key "c" not known in dictionary}
785 test dict-16.7 {dict unset command} -setup {
786     unset -nocomplain dictVar
787 } -body {
788     list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]
789 } -cleanup {
790     unset dictVar
791 } -result {0 {} 1}
792 test dict-16.8 {dict unset command} -returnCodes error -body {
793     dict unset dictVar
794 } -result {wrong # args: should be "dict unset varName key ?key ...?"}
795 test dict-16.9 {dict unset command: write failure} -setup {
796     unset -nocomplain dictVar
797 } -body {
798     set dictVar 1
799     dict unset dictVar a
800 } -returnCodes error -cleanup {
801     unset dictVar
802 } -result {missing value to go with key}
804 #test dict-17.1 {dict filter command: key} -body {
805 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
806 #    dict filter $dictVar key a2
807 #} -cleanup {
808 #    unset dictVar
809 #} -result {a2 b}
810 #test dict-17.2 {dict filter command: key} -body {
811 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
812 #    dict size [dict filter $dictVar key *]
813 #} -cleanup {
814 #    unset dictVar
815 #} -result 6
816 #test dict-17.3 {dict filter command: key} -body {
817 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
818 #    dict filter $dictVar key ???
819 #} -cleanup {
820 #    unset dictVar
821 #} -result {foo bar bar foo}
822 #test dict-17.4 {dict filter command: key - no patterns} {
823 #    dict filter {a b c d} key
824 #} {}
825 #test dict-17.4.1 {dict filter command: key - many patterns} {
826 #    dict filter {a1 a a2 b b1 c b2 d foo bar bar foo} key a? b?
827 #} {a1 a a2 b b1 c b2 d}
828 #test dict-17.5 {dict filter command: key - bad dict} -returnCodes error -body {
829 #    dict filter {a b c} key
830 #} -result {missing value to go with key}
831 #test dict-17.6 {dict filter command: value} -body {
832 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
833 #    dict filter $dictVar value c
834 #} -cleanup {
835 #    unset dictVar
836 #} -result {b1 c}
837 #test dict-17.7 {dict filter command: value} -body {
838 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
839 #    dict size [dict filter $dictVar value *]
840 #} -cleanup {
841 #    unset dictVar
842 #} -result 6
843 #test dict-17.8 {dict filter command: value} -body {
844 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
845 #    dict filter $dictVar value ???
846 #} -cleanup {
847 #    unset dictVar
848 #} -result {foo bar bar foo}
849 #test dict-17.9 {dict filter command: value - no patterns} {
850 #    dict filter {a b c d} value
851 #} {}
852 #test dict-17.9.1 {dict filter command: value - many patterns} {
853 #    dict filter {a a1 b a2 c b1 foo bar bar foo d b2} value a? b?
854 #} {a a1 b a2 c b1 d b2}
855 #test dict-17.10 {dict filter command: value - bad dict} -body {
856 #    dict filter {a b c} value a
857 #} -returnCodes error -result {missing value to go with key}
858 #test dict-17.11 {dict filter command: script} -body {
859 #    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
860 #    set n 0
861 #    list [dict filter $dictVar script {k v} {
862 #       incr n
863 #       expr {[string length $k] == [string length $v]}
864 #    }] $n
865 #} -cleanup {
866 #    unset dictVar n k v
867 #} -result {{foo bar bar foo} 6}
868 #test dict-17.12 {dict filter command: script} -returnCodes error -body {
869 #    dict filter {a b} script {k v} {
870 #       concat $k $v
871 #    }
872 #} -cleanup {
873 #    unset k v
874 #} -result {expected boolean value but got "a b"}
875 #test dict-17.13 {dict filter command: script} -body {
876 #    list [catch {dict filter {a b} script {k v} {error x}} msg] $msg \
877 #           $::errorInfo
878 #} -cleanup {
879 #    unset k v msg
880 #} -result {1 x {x
881 #    while executing
882 #"error x"
883 #    ("dict filter" script line 1)
884 #    invoked from within
885 #"dict filter {a b} script {k v} {error x}"}}
886 #test dict-17.14 {dict filter command: script} -setup {
887 #    set n 0
888 #} -body {
889 #    list [dict filter {a b c d} script {k v} {
890 #       incr n
891 #       break
892 #       error boom!
893 #    }] $n
894 #} -cleanup {
895 #    unset n k v
896 #} -result {{} 1}
897 #test dict-17.15 {dict filter command: script} -setup {
898 #    set n 0
899 #} -body {
900 #    list [dict filter {a b c d} script {k v} {
901 #       incr n
902 #       continue
903 #       error boom!
904 #    }] $n
905 #} -cleanup {
906 #    unset n k v
907 #} -result {{} 2}
908 #test dict-17.16 {dict filter command: script} {
909 #    apply {{} {
910 #       dict filter {a b} script {k v} {
911 #           return ok,$k,$v
912 #           error "skipped return completely"
913 #       }
914 #       error "return didn't go far enough"
915 #    }}
916 #} ok,a,b
917 #test dict-17.17 {dict filter command: script} -body {
918 #    dict filter {a b} script {k k} {continue}
919 #    return $k
920 #} -cleanup {
921 #    unset k
922 #} -result b
923 #test dict-17.18 {dict filter command: script} -returnCodes error -body {
924 #    dict filter {a b} script {k k}
925 #} -result {wrong # args: should be "dict filter dictionary script {keyVar valueVar} filterScript"}
926 #test dict-17.19 {dict filter command: script} -returnCodes error -body {
927 #    dict filter {a b} script k {continue}
928 #} -result {must have exactly two variable names}
929 #test dict-17.20 {dict filter command: script} -returnCodes error -body {
930 #    dict filter {a b} script "\{k v" {continue}
931 #} -result {unmatched open brace in list}
932 #test dict-17.21 {dict filter command} -returnCodes error -body {
933 #    dict filter {a b}
934 #} -result {wrong # args: should be "dict filter dictionary filterType ?arg ...?"}
935 #test dict-17.22 {dict filter command} -returnCodes error -body {
936 #    dict filter {a b} JUNK
937 #} -result {bad filterType "JUNK": must be key, script, or value}
938 #test dict-17.23 {dict filter command} -returnCodes error -body {
939 #    dict filter a key *
940 #} -result {missing value to go with key}
942 test dict-18.1 {dict-list relationship} -body {
943     # Test that any internal conversion between list and dict does not change
944     # the object
945     set l [list 1 2 3 4 5 6 7 8 9 0 q w e r t y]
946     dict values $l
947     return $l
948 } -cleanup {
949     unset l
950 } -result {1 2 3 4 5 6 7 8 9 0 q w e r t y}
951 test dict-18.2 {dict-list relationship} -body {
952     # Test that the dictionary is a valid list
953     set d [dict create "abc def" 0 "a\{b" 1 "c\}d" 2]
954     for {set t 0} {$t < 5} {incr t} {
955         llength $d
956         dict lappend d "abc def" "\}\{"
957         dict append  d "a\{b" "\}"
958         dict incr    d "c\}d" 1
959     }
960     llength $d
961 } -cleanup {
962     unset d t
963 } -result 6
964 test dict-18.3 {dict-list relationship} -body {
965     set ld [list a b c d c e f g]
966     list [string length $ld] [dict size $ld] [llength $ld]
967 } -cleanup {
968     unset ld
969 } -result {15 3 8}
970 test dict-18.4 {dict-list relationship} -body {
971     set ld [list a b c d c e f g]
972     list [llength $ld] [dict size $ld] [llength $ld]
973 } -cleanup {
974     unset ld
975 } -result {8 3 8}
977 test dict-20.1 {dict merge command} {
978     dict merge
979 } {}
980 test dict-20.2 {dict merge command} {
981     dict-sort [dict merge {a b c d e f}]
982 } {a b c d e f}
983 test dict-20.3 {dict merge command} -body {
984     dict-sort [dict merge {a b c d e}]
985 } -result {missing value to go with key} -returnCodes error
986 test dict-20.4 {dict merge command} {
987     dict-sort [dict merge {a b c d} {e f g h}]
988 } {a b c d e f g h}
989 test dict-20.5 {dict merge command} -body {
990     dict-sort [dict merge {a b c d e} {e f g h}]
991 } -result {missing value to go with key} -returnCodes error
992 test dict-20.6 {dict merge command} -body {
993     dict-sort [dict merge {a b c d} {e f g h i}]
994 } -result {missing value to go with key} -returnCodes error
995 test dict-20.7 {dict merge command} {
996     dict-sort [dict merge {a b c d e f} {e x g h}]
997 } {a b c d e x g h}
998 test dict-20.8 {dict merge command} {
999     dict-sort [dict merge {a b c d} {a x c y}]
1000 } {a x c y}
1001 test dict-20.9 {dict merge command} {
1002     dict-sort [dict merge {a b c d} {c y a x}]
1003 } {a x c y}
1004 test dict-20.10 {dict merge command} {
1005     dict-sort [dict merge {a b c d e f} {a x 1 2 3 4} {a - 1 -}]
1006 } {1 - 3 4 a - c d e f}
1008 test dict-21.1 {dict update command} -returnCodes 1 -body {
1009     dict update
1010 } -match glob -result {wrong # args: should be "dict update varName * script"}
1011 test dict-21.2 {dict update command} -returnCodes 1 -body {
1012     dict update v
1013 } -match glob -result {wrong # args: should be "dict update varName * script"}
1014 test dict-21.3 {dict update command} -returnCodes 1 -body {
1015     dict update v k
1016 } -match glob -result {wrong # args: should be "dict update varName * script"}
1017 test dict-21.4 {dict update command} -returnCodes 1 -body {
1018     dict update v k v
1019 } -match glob -result {wrong # args: should be "dict update varName * script"}
1020 test dict-21.5 {dict update command} -body {
1021     set a {b c}
1022     set result {}
1023     set bb {}
1024     dict update a b bb {
1025         lappend result $a $bb
1026     }
1027     lappend result $a
1028 } -cleanup {
1029     unset a result bb
1030 } -result {{b c} c {b c}}
1031 test dict-21.6 {dict update command} -body {
1032     set a {b c}
1033     set result {}
1034     set bb {}
1035     dict update a b bb {
1036         lappend result $a $bb [set bb d]
1037     }
1038     lappend result $a
1039 } -cleanup {
1040     unset a result bb
1041 } -result {{b c} c d {b d}}
1042 test dict-21.7 {dict update command} -body {
1043     set a {b c}
1044     set result {}
1045     set bb {}
1046     dict update a b bb {
1047         lappend result $a $bb [unset bb]
1048     }
1049     lappend result $a
1050 } -cleanup {
1051     unset a result
1052 } -result {{b c} c {} {}}
1053 test dict-21.8 {dict update command} -body {
1054     set a {b c d e}
1055     dict update a b v1 d v2 {
1056         lassign "$v1 $v2" v2 v1
1057     }
1058     dict-sort $a
1059 } -cleanup {
1060     unset a v1 v2
1061 } -result {b e d c}
1062 test dict-21.9 {dict update command} -body {
1063     set a {b c d e}
1064     dict update a b v1 d v2 {unset a}
1065     info exist a
1066 } -cleanup {
1067     unset v1 v2
1068 } -result 0
1069 test dict-21.10 {dict update command} -body {
1070     set a {b {c d}}
1071     dict update a b v1 {
1072         dict update v1 c v2 {
1073             set v2 foo
1074         }
1075     }
1076     dict-sort $a
1077 } -cleanup {
1078     unset a v1 v2
1079 } -result {b {c foo}}
1080 test dict-21.11 {dict update command} -body {
1081     set a {b c d e}
1082     dict update a b v1 d v2 {
1083         dict set a f g
1084     }
1085     dict-sort $a
1086 } -cleanup {
1087     unset a v1 v2
1088 } -result {b c d e f g}
1089 test dict-21.12 {dict update command} -body {
1090     set a {b c d e}
1091     dict update a b v1 d v2 f v3 {
1092         set v3 g
1093     }
1094     dict-sort $a
1095 } -cleanup {
1096     unset a v1 v2 v3
1097 } -result {b c d e f g}
1098 test dict-21.13 {dict update command: compilation} {
1099     apply {d {
1100         while 1 {
1101             dict update d a alpha b beta {
1102                 set beta $alpha
1103                 unset alpha
1104                 break
1105             }
1106         }
1107         dict-sort $d
1108     }} {a 1 c 2}
1109 } {b 1 c 2}
1110 test dict-21.14 {dict update command: compilation} tcl {
1111     apply {x {
1112         set indices {2 3}
1113         trace add variable aa write "string length \$indices ;#"
1114         dict update x k aa l bb {}
1115     }} {k 1 l 2}
1116 } {}
1117 test dict-21.15 {dict update command: compilation} tcl {
1118     apply {x {
1119         set indices {2 3}
1120         trace add variable aa read "string length \$indices ;#"
1121         dict update x k aa l bb {}
1122     }} {k 1 l 2}
1123 } {}
1124 test dict-21.16 {dict update command: no recursive structures [Bug 1786481]} -body {
1125     set foo {a {b {c {d {e 1}}}}}
1126     dict update foo a t {
1127         dict update t b t {
1128             dict update t c t {
1129                 dict update t d t {
1130                     dict incr t e
1131                 }
1132             }
1133         }
1134     }
1135     string range [append foo OK] end-1 end
1136 } -cleanup {
1137     unset foo t
1138 } -result OK
1139 test dict-21.17 {dict update command: no recursive structures [Bug 1786481]} {
1140     apply {{} {
1141         set foo {a {b {c {d {e 1}}}}}
1142         dict update foo a t {
1143             dict update t b t {
1144                 dict update t c t {
1145                     dict update t d t {
1146                         dict incr t e
1147                     }
1148                 }
1149             }
1150         }
1151         string range [append foo OK] end-1 end
1152     }}
1153 } OK
1155 test dict-22.1 {dict with command} -body {
1156     dict with
1157 } -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
1158 test dict-22.2 {dict with command} -body {
1159     dict with v
1160 } -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
1161 test dict-22.3 {dict with command} -body {
1162     unset -nocomplain v
1163     dict with v {error "in body"}
1164 } -returnCodes 1 -result {can't read "v": no such variable}
1165 test dict-22.4 {dict with command} -body {
1166     set a {b c d e}
1167     unset -nocomplain b d
1168     set result [list [info exist b] [info exist d]]
1169     dict with a {
1170         lappend result [info exist b] [info exist d] $b $d
1171     }
1172     return $result
1173 } -cleanup {
1174     unset a b d result
1175 } -result {0 0 1 1 c e}
1176 test dict-22.5 {dict with command} -body {
1177     set a {b c d e}
1178     dict with a {
1179         lassign "$b $d" d b
1180     }
1181     dict-sort $a
1182 } -cleanup {
1183     unset a b d
1184 } -result {b e d c}
1185 test dict-22.6 {dict with command} -body {
1186     set a {b c d e}
1187     dict with a {
1188         unset b
1189         # This *won't* go into the dict...
1190         set f g
1191     }
1192     return $a
1193 } -cleanup {
1194     unset a d f
1195 } -result {d e}
1196 test dict-22.7 {dict with command} -body {
1197     set a {b c d e}
1198     dict with a {
1199         dict unset a b
1200     }
1201     return [dict-sort $a]
1202 } -cleanup {
1203     unset a
1204 } -result {b c d e}
1205 test dict-22.8 {dict with command} -body {
1206     set a [dict create b c]
1207     dict with a {
1208         set b $a
1209     }
1210     return $a
1211 } -cleanup {
1212     unset a b
1213 } -result {b {b c}}
1214 test dict-22.9 {dict with command} -body {
1215     set a {b {c d}}
1216     dict with a b {
1217         set c $c$c
1218     }
1219     return $a
1220 } -cleanup {
1221     unset a c
1222 } -result {b {c dd}}
1223 test dict-22.10 {dict with command: result handling tricky case} -body {
1224     set a {b {c d}}
1225     foreach i {0 1} {
1226         if {$i} break
1227         dict with a b {
1228             set a {}
1229             # We're checking to see if we lose this break
1230             break
1231         }
1232     }
1233     list $i $a
1234 } -cleanup {
1235     unset a i c
1236 } -result {0 {}}
1237 test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} -body {
1238     set foo {t {t {t {inner 1}}}}
1239     dict with foo {
1240         dict with t {
1241             dict with t {
1242                 dict with t {
1243                     incr inner
1244                 }
1245             }
1246         }
1247     }
1248     string range [append foo OK] end-1 end
1249 } -cleanup {
1250     unset foo t inner
1251 } -result OK
1253 testreport