1# This test file covers the dictionary object type and the dict command used
2# to work with values of that type.
3#
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.
7#
8# Copyright © 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.
11
12if {"::tcltest" ni [namespace children]} {
13    package require tcltest 2.5
14    namespace import -force ::tcltest::*
15}
16
17# Used for constraining memory leak tests
18testConstraint memory [llength [info commands memory]]
19if {[testConstraint memory]} {
20    proc memtest script {
21	set end [lindex [split [memory info] \n] 3 3]
22	for {set i 0} {$i < 5} {incr i} {
23	    uplevel 1 $script
24	    set tmp $end
25	    set end [lindex [split [memory info] \n] 3 3]
26	}
27	expr {$end - $tmp}
28    }
29}
30
31test dict-1.1 {dict command basic syntax} -returnCodes error -body {
32    dict
33} -result {wrong # args: should be "dict subcommand ?arg ...?"}
34test dict-1.2 {dict command basic syntax} -returnCodes error -body {
35    dict ?
36} -match glob -result {unknown or ambiguous subcommand "?": must be *}
37
38test dict-2.1 {dict create command} {
39    dict create
40} {}
41test dict-2.2 {dict create command} {
42    dict create a b
43} {a b}
44test dict-2.3 {dict create command} -body {
45    set result {}
46    set dict [dict create a b c d]
47    # Can't compare directly as ordering of values is undefined
48    foreach key {a c} {
49	set idx [lsearch -exact $dict $key]
50	if {$idx & 1} {
51	    error "found $key at odd index $idx in $dict"
52	}
53	lappend result [lindex $dict [expr {$idx+1}]]
54    }
55    return $result
56} -cleanup {
57    unset result dict key idx
58} -result {b d}
59test dict-2.4 {dict create command} -returnCodes error -body {
60    dict create a
61} -result {wrong # args: should be "dict create ?key value ...?"}
62test dict-2.5 {dict create command} -returnCodes error -body {
63    dict create a b c
64} -result {wrong # args: should be "dict create ?key value ...?"}
65test dict-2.6 {dict create command - initialse refcount field!} -body {
66    # Bug 715751 will show up in memory debuggers like purify
67    for {set i 0} {$i<10} {incr i} {
68	set dictv [dict create a 0]
69	set share [dict values $dictv]
70	list [dict incr dictv a]
71    }
72} -cleanup {
73    unset i dictv share
74} -result {}
75test dict-2.7 {dict create command - #-quoting in string rep} {
76    dict create # #comment
77} {{#} #comment}
78test dict-2.8 {dict create command - #-quoting in string rep} -body {
79    dict create #a x #b x
80} -match glob -result {{#?} x #? x}
81test dict-2.9 {dict create command: compilation} {
82    apply {{} {dict create [format a] b}}
83} {a b}
84test dict-2.10 {dict create command: compilation} {
85    apply {{} {dict create [format a] b c d}}
86} {a b c d}
87test dict-2.11 {dict create command: compilation} {
88    apply {{} {dict create [format a] b c d a x}}
89} {a x c d}
90test dict-2.12 {dict create command: non-compilation} {
91    dict create [format a] b
92} {a b}
93test dict-2.13 {dict create command: non-compilation} {
94    dict create [format a] b c d
95} {a b c d}
96test dict-2.14 {dict create command: non-compilation} {
97    dict create [format a] b c d a x
98} {a x c d}
99
100test dict-3.1 {dict get command} {dict get {a b} a} b
101test dict-3.2 {dict get command} {dict get {a b c d} a} b
102test dict-3.3 {dict get command} {dict get {a b c d} c} d
103test dict-3.4 {dict get command} -returnCodes error -body {
104    dict get {a b c d} b
105} -result {key "b" not known in dictionary}
106test dict-3.5 {dict get command} {dict get {a {p q r s} b {u v x y}} a p} q
107test dict-3.6 {dict get command} {dict get {a {p q r s} b {u v x y}} a r} s
108test dict-3.7 {dict get command} {dict get {a {p q r s} b {u v x y}} b u} v
109test dict-3.8 {dict get command} {dict get {a {p q r s} b {u v x y}} b x} y
110test dict-3.9 {dict get command} -returnCodes error -body {
111    dict get {a {p q r s} b {u v x y}} a z
112} -result {key "z" not known in dictionary}
113test dict-3.10 {dict get command} -returnCodes error -body {
114    dict get {a {p q r s} b {u v x y}} c z
115} -result {key "c" not known in dictionary}
116test dict-3.11 {dict get command} {dict get [dict create a b c d] a} b
117test dict-3.12 {dict get command} -returnCodes error -body {
118    dict get
119} -result {wrong # args: should be "dict get dictionary ?key ...?"}
120test dict-3.13 {dict get command} -body {
121    set dict [dict get {a b c d}]
122    if {$dict eq "a b c d"} {
123	return OK
124    } elseif {$dict eq "c d a b"} {
125	return reordered
126    } else {
127	return $dict
128    }
129} -cleanup {
130    unset dict
131} -result OK
132test dict-3.14 {dict get command} -returnCodes error -body {
133    dict get {a b c d} a c
134} -result {missing value to go with key}
135test dict-3.15 {compiled dict get error cleanliness - Bug 2431847} -body {
136    apply {{} {
137	dict set a(z) b c
138	dict get $a(z) d
139    }}
140} -returnCodes error -result {key "d" not known in dictionary}
141test 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}
142test dict-3.17 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
143
144test dict-4.1 {dict replace command} {
145    dict replace {a b c d}
146} {a b c d}
147test dict-4.2 {dict replace command} {
148    dict replace {a b c d} e f
149} {a b c d e f}
150test dict-4.3 {dict replace command} {
151    dict replace {a b c d} c f
152} {a b c f}
153test dict-4.4 {dict replace command} {
154    dict replace {a b c d} c x a y
155} {a y c x}
156test dict-4.5 {dict replace command} -returnCodes error -body {
157    dict replace
158} -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
159test dict-4.6 {dict replace command} -returnCodes error -body {
160    dict replace {a a} a
161} -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
162test dict-4.7 {dict replace command} -returnCodes error -body {
163    dict replace {a a a} a b
164} -result {missing value to go with key}
165test dict-4.8 {dict replace command} -returnCodes error -body {
166    dict replace [list a a a] a b
167} -result {missing value to go with key}
168test dict-4.9 {dict replace command} {dict replace [list a a] a b} {a b}
169test dict-4.10 {dict replace command} {dict replace [list a a] a b a c} {a c}
170test dict-4.11 {dict replace command: canonicality is forced} {
171    dict replace { a b  c d }
172} {a b c d}
173test dict-4.12 {dict replace command: canonicality is forced} {
174    dict replace {a b c d a e}
175} {a e c d}
176test dict-4.13 {dict replace command: type check is mandatory} -body {
177    dict replace { a b c d e }
178} -errorCode {TCL VALUE DICTIONARY} -result {missing value to go with key}
179test dict-4.14 {dict replace command: type check is mandatory} -body {
180    dict replace { a b {}c d }
181} -returnCodes error -result {dict element in braces followed by "c" instead of space}
182test dict-4.14a {dict replace command: type check is mandatory} {
183    catch {dict replace { a b {}c d }} -> opt
184    dict get $opt -errorcode
185} {TCL VALUE DICTIONARY JUNK}
186test dict-4.15 {dict replace command: type check is mandatory} -body {
187    dict replace { a b ""c d }
188} -returnCodes error -result {dict element in quotes followed by "c" instead of space}
189test dict-4.15a {dict replace command: type check is mandatory} {
190    catch {dict replace { a b ""c d }} -> opt
191    dict get $opt -errorcode
192} {TCL VALUE DICTIONARY JUNK}
193test dict-4.16 {dict replace command: type check is mandatory} -body {
194    dict replace " a b \"c d "
195} -returnCodes error -result {unmatched open quote in dict}
196test dict-4.16a {dict replace command: type check is mandatory} {
197    catch {dict replace " a b \"c d "} -> opt
198    dict get $opt -errorcode
199} {TCL VALUE DICTIONARY QUOTE}
200test dict-4.17 {dict replace command: type check is mandatory} -body {
201    dict replace " a b \{c d "
202} -errorCode {TCL VALUE DICTIONARY BRACE} -result {unmatched open brace in dict}
203test dict-4.18 {dict replace command: canonicality forcing doesn't leak} {
204    set example { a b  c d }
205    list $example [dict replace $example]
206} {{ a b  c d } {a b c d}}
207
208test dict-5.1 {dict remove command} {dict remove {a b c d} a} {c d}
209test dict-5.2 {dict remove command} {dict remove {a b c d} c} {a b}
210test dict-5.3 {dict remove command} {dict remove {a b c d} a c} {}
211test dict-5.4 {dict remove command} {dict remove {a b c d} c a} {}
212test dict-5.5 {dict remove command} {
213    dict remove {a b c d}
214} {a b c d}
215test dict-5.6 {dict remove command} {dict remove {a b} c} {a b}
216test dict-5.7 {dict remove command} -returnCodes error -body {
217    dict remove
218} -result {wrong # args: should be "dict remove dictionary ?key ...?"}
219test dict-5.8 {dict remove command: canonicality is forced} {
220    dict remove { a b  c d }
221} {a b c d}
222test dict-5.9 {dict remove command: canonicality is forced} {
223    dict remove {a b c d a e}
224} {a e c d}
225test dict-5.10 {dict remove command: canonicality forced by update} {
226    dict remove { a b c d } c
227} {a b}
228test dict-5.11 {dict remove command: type check is mandatory} -body {
229    dict remove { a b c d e }
230} -returnCodes error -result {missing value to go with key}
231test dict-5.12 {dict remove command: type check is mandatory} -body {
232    dict remove { a b {}c d }
233} -returnCodes error -result {dict element in braces followed by "c" instead of space}
234test dict-5.13 {dict remove command: canonicality forcing doesn't leak} {
235    set example { a b  c d }
236    list $example [dict remove $example]
237} {{ a b  c d } {a b c d}}
238
239test dict-6.1 {dict keys command} {dict keys {a b}} a
240test dict-6.2 {dict keys command} {dict keys {c d}} c
241test dict-6.3 {dict keys command} {lsort [dict keys {a b c d}]} {a c}
242test dict-6.4 {dict keys command} {dict keys {a b c d} a} a
243test dict-6.5 {dict keys command} {dict keys {a b c d} c} c
244test dict-6.6 {dict keys command} {dict keys {a b c d} e} {}
245test dict-6.7 {dict keys command} {lsort [dict keys {a b c d ca da} c*]} {c ca}
246test dict-6.8 {dict keys command} -returnCodes error -body {
247    dict keys
248} -result {wrong # args: should be "dict keys dictionary ?pattern?"}
249test dict-6.9 {dict keys command} -returnCodes error -body {
250    dict keys {} a b
251} -result {wrong # args: should be "dict keys dictionary ?pattern?"}
252test dict-6.10 {dict keys command} -returnCodes error -body {
253    dict keys a
254} -result {missing value to go with key}
255
256test dict-7.1 {dict values command} {dict values {a b}} b
257test dict-7.2 {dict values command} {dict values {c d}} d
258test dict-7.3 {dict values command} {lsort [dict values {a b c d}]} {b d}
259test dict-7.4 {dict values command} {dict values {a b c d} b} b
260test dict-7.5 {dict values command} {dict values {a b c d} d} d
261test dict-7.6 {dict values command} {dict values {a b c d} e} {}
262test dict-7.7 {dict values command} {lsort [dict values {a b c d ca da} d*]} {d da}
263test dict-7.8 {dict values command} -returnCodes error -body {
264    dict values
265} -result {wrong # args: should be "dict values dictionary ?pattern?"}
266test dict-7.9 {dict values command} -returnCodes error -body {
267    dict values {} a b
268} -result {wrong # args: should be "dict values dictionary ?pattern?"}
269test dict-7.10 {dict values command} -returnCodes error -body {
270    dict values a
271} -result {missing value to go with key}
272
273test dict-8.1 {dict size command} {dict size {}} 0
274test dict-8.2 {dict size command} {dict size {a b}} 1
275test dict-8.3 {dict size command} {dict size {a b c d}} 2
276test dict-8.4 {dict size command} -returnCodes error -body {
277    dict size
278} -result {wrong # args: should be "dict size dictionary"}
279test dict-8.5 {dict size command} -returnCodes error -body {
280    dict size a b
281} -result {wrong # args: should be "dict size dictionary"}
282test dict-8.6 {dict size command} -returnCodes error -body {
283    dict size a
284} -result {missing value to go with key}
285
286test dict-9.1 {dict exists command} {dict exists {a b} a} 1
287test dict-9.2 {dict exists command} {dict exists {a b} b} 0
288test dict-9.3 {dict exists command} {dict exists {a {b c}} a b} 1
289test dict-9.4 {dict exists command} {dict exists {a {b c}} a c} 0
290test dict-9.5 {dict exists command} {dict exists {a {b c}} b c} 0
291test dict-9.6 {dict exists command} {dict exists {a {b c d}} a c} 0
292test dict-9.7 {dict exists command} -returnCodes error -body {
293    dict exists
294} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
295test dict-9.8 {dict exists command} -returnCodes error -body {
296    dict exists {}
297} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
298
299test dict-10.1 {dict info command} -body {
300    # Actual string returned by this command is undefined; it is
301    # intended for human consumption and not for use by scripts.
302    dict info {}
303} -match glob -result *
304test dict-10.2 {dict info command} -returnCodes error -body {
305    dict info
306} -result {wrong # args: should be "dict info dictionary"}
307test dict-10.3 {dict info command} -returnCodes error -body {
308    dict info {} x
309} -result {wrong # args: should be "dict info dictionary"}
310test dict-10.4 {dict info command} -returnCodes error -body {
311    dict info x
312} -result {missing value to go with key}
313
314test dict-11.1 {dict incr command: unshared value} -body {
315    set dictv [dict create \
316	    a [string index "=0=" 1] \
317	    b [expr {1+2}] \
318	    c [expr {wide(0x80000000)+1}]]
319    dict incr dictv a
320} -cleanup {
321    unset dictv
322} -result {a 1 b 3 c 2147483649}
323test dict-11.2 {dict incr command: unshared value} -body {
324    set dictv [dict create \
325	    a [string index "=0=" 1] \
326	    b [expr {1+2}] \
327	    c [expr {wide(0x80000000)+1}]]
328    dict incr dictv b
329} -cleanup {
330    unset dictv
331} -result {a 0 b 4 c 2147483649}
332test dict-11.3 {dict incr command: unshared value} -body {
333    set dictv [dict create \
334	    a [string index "=0=" 1] \
335	    b [expr {1+2}] \
336	    c [expr {wide(0x80000000)+1}]]
337    dict incr dictv c
338} -cleanup {
339    unset dictv
340} -result {a 0 b 3 c 2147483650}
341test dict-11.4 {dict incr command: shared value} -body {
342    set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
343    set sharing [dict values $dictv]
344    dict incr dictv a
345} -cleanup {
346    unset dictv sharing
347} -result {a 1 b 3 c 2147483649}
348test dict-11.5 {dict incr command: shared value} -body {
349    set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
350    set sharing [dict values $dictv]
351    dict incr dictv b
352} -cleanup {
353    unset dictv sharing
354} -result {a 0 b 4 c 2147483649}
355test dict-11.6 {dict incr command: shared value} -body {
356    set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
357    set sharing [dict values $dictv]
358    dict incr dictv c
359} -cleanup {
360    unset dictv sharing
361} -result {a 0 b 3 c 2147483650}
362test dict-11.7 {dict incr command: unknown values} -body {
363    set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
364    dict incr dictv d
365} -cleanup {
366    unset dictv
367} -result {a 0 b 3 c 2147483649 d 1}
368test dict-11.8 {dict incr command} -body {
369    set dictv {a 1}
370    dict incr dictv a 2
371} -cleanup {
372    unset dictv
373} -result {a 3}
374test dict-11.9 {dict incr command} -returnCodes error -body {
375    set dictv {a dummy}
376    dict incr dictv a
377} -cleanup {
378    unset dictv
379} -result {expected integer but got "dummy"}
380test dict-11.10 {dict incr command} -returnCodes error -body {
381    set dictv {a 1}
382    dict incr dictv a dummy
383} -cleanup {
384    unset dictv
385} -result {expected integer but got "dummy"}
386test dict-11.11 {dict incr command} -setup {
387    unset -nocomplain dictv
388} -body {
389    dict incr dictv a
390} -cleanup {
391    unset dictv
392} -result {a 1}
393test dict-11.12 {dict incr command} -returnCodes error -body {
394    set dictv a
395    dict incr dictv a
396} -cleanup {
397    unset dictv
398} -result {missing value to go with key}
399test dict-11.13 {dict incr command} -returnCodes error -body {
400    set dictv a
401    dict incr dictv a a a
402} -cleanup {
403    unset dictv
404} -result {wrong # args: should be "dict incr dictVarName key ?increment?"}
405test dict-11.14 {dict incr command} -returnCodes error -body {
406    set dictv a
407    dict incr dictv
408} -cleanup {
409    unset dictv
410} -result {wrong # args: should be "dict incr dictVarName key ?increment?"}
411test dict-11.15 {dict incr command: write failure} -setup {
412    unset -nocomplain dictVar
413} -body {
414    set dictVar(block) {}
415    dict incr dictVar a
416} -returnCodes error -cleanup {
417    unset dictVar
418} -result {can't set "dictVar": variable is array}
419test dict-11.16 {dict incr command: compilation} {
420    apply {{} {
421	set v {a 0 b 0 c 0}
422	dict incr v a
423	dict incr v b 1
424	dict incr v c 2
425	dict incr v d 3
426	list [dict get $v a] [dict get $v b] [dict get $v c] [dict get $v d]
427    }}
428} {1 1 2 3}
429test dict-11.17 {dict incr command: compilation} {
430    apply {{} {
431	set dictv {a 1}
432	dict incr dictv a 2
433    }}
434} {a 3}
435
436test dict-12.1 {dict lappend command} -body {
437    set dictv {a a}
438    dict lappend dictv a
439} -cleanup {
440    unset dictv
441} -result {a a}
442test dict-12.2 {dict lappend command} -body {
443    set dictv {a a}
444    set sharing [dict values $dictv]
445    dict lappend dictv a b
446} -cleanup {
447    unset dictv sharing
448} -result {a {a b}}
449test dict-12.3 {dict lappend command} -body {
450    set dictv {a a}
451    dict lappend dictv a b c
452} -cleanup {
453    unset dictv
454} -result {a {a b c}}
455test dict-12.2.1 {dict lappend command} -body {
456    set dictv [dict create a [string index =a= 1]]
457    dict lappend dictv a b
458} -cleanup {
459    unset dictv
460} -result {a {a b}}
461test dict-12.4 {dict lappend command} -body {
462    set dictv {}
463    dict lappend dictv a x y z
464} -cleanup {
465    unset dictv
466} -result {a {x y z}}
467test dict-12.5 {dict lappend command} -body {
468    unset -nocomplain dictv
469    dict lappend dictv a b
470} -cleanup {
471    unset dictv
472} -result {a b}
473test dict-12.6 {dict lappend command} -returnCodes error -body {
474    set dictv a
475    dict lappend dictv a a
476} -cleanup {
477    unset dictv
478} -result {missing value to go with key}
479test dict-12.7 {dict lappend command} -returnCodes error -body {
480    dict lappend
481} -result {wrong # args: should be "dict lappend dictVarName key ?value ...?"}
482test dict-12.8 {dict lappend command} -returnCodes error -body {
483    dict lappend dictv
484} -result {wrong # args: should be "dict lappend dictVarName key ?value ...?"}
485test dict-12.9 {dict lappend command} -returnCodes error -body {
486    set dictv [dict create a "\{"]
487    dict lappend dictv a a
488} -cleanup {
489    unset dictv
490} -result {unmatched open brace in list}
491test dict-12.10 {dict lappend command: write failure} -setup {
492    unset -nocomplain dictVar
493} -body {
494    set dictVar(block) {}
495    dict lappend dictVar a x
496} -returnCodes error -cleanup {
497    unset dictVar
498} -result {can't set "dictVar": variable is array}
499test dict-12.11 {compiled dict append: invalidate string rep - Bug 3079830} {
500    apply {{} {set d {a 1 b 2 c 3}; dict lappend d b 22}}
501} {a 1 b {2 22} c 3}
502
503test dict-13.1 {dict append command} -body {
504    set dictv {a a}
505    dict append dictv a
506} -cleanup {
507    unset dictv
508} -result {a a}
509test dict-13.2 {dict append command} -body {
510    set dictv {a a}
511    set sharing [dict values $dictv]
512    dict append dictv a b
513} -cleanup {
514    unset dictv sharing
515} -result {a ab}
516test dict-13.3 {dict append command} -body {
517    set dictv {a a}
518    dict append dictv a b c
519} -cleanup {
520    unset dictv
521} -result {a abc}
522test dict-13.2.1 {dict append command} -body {
523    set dictv [dict create a [string index =a= 1]]
524    dict append dictv a b
525} -cleanup {
526    unset dictv
527} -result {a ab}
528test dict-13.4 {dict append command} -body {
529    set dictv {}
530    dict append dictv a x y z
531} -cleanup {
532    unset dictv
533} -result {a xyz}
534test dict-13.5 {dict append command} -body {
535    unset -nocomplain dictv
536    dict append dictv a b
537} -cleanup {
538    unset dictv
539} -result {a b}
540test dict-13.6 {dict append command} -returnCodes error -body {
541    set dictv a
542    dict append dictv a a
543} -cleanup {
544    unset dictv
545} -result {missing value to go with key}
546test dict-13.7 {dict append command} -returnCodes error -body {
547    dict append
548} -result {wrong # args: should be "dict append dictVarName key ?value ...?"}
549test dict-13.8 {dict append command} -returnCodes error -body {
550    dict append dictv
551} -result {wrong # args: should be "dict append dictVarName key ?value ...?"}
552test dict-13.9 {dict append command: write failure} -setup {
553    unset -nocomplain dictVar
554} -body {
555    set dictVar(block) {}
556    dict append dictVar a x
557} -returnCodes error -cleanup {
558    unset dictVar
559} -result {can't set "dictVar": variable is array}
560test dict-13.10 {compiled dict append: crash case} {
561    apply {{} {dict append dictVar a o k}}
562} {a ok}
563test dict-13.11 {compiled dict append: invalidate string rep - Bug 3079830} {
564    apply {{} {set d {a 1 b 2 c 3}; dict append d b 22}}
565} {a 1 b 222 c 3}
566
567test dict-14.1 {dict for command: syntax} -returnCodes error -body {
568    dict for
569} -result {wrong # args: should be "dict for {keyVarName valueVarName} dictionary script"}
570test dict-14.2 {dict for command: syntax} -returnCodes error -body {
571    dict for x
572} -result {wrong # args: should be "dict for {keyVarName valueVarName} dictionary script"}
573test dict-14.3 {dict for command: syntax} -returnCodes error -body {
574    dict for x x
575} -result {wrong # args: should be "dict for {keyVarName valueVarName} dictionary script"}
576test dict-14.4 {dict for command: syntax} -returnCodes error -body {
577    dict for x x x x
578} -result {wrong # args: should be "dict for {keyVarName valueVarName} dictionary script"}
579test dict-14.5 {dict for command: syntax} -returnCodes error -body {
580    dict for x x x
581} -result {must have exactly two variable names}
582test dict-14.6 {dict for command: syntax} -returnCodes error -body {
583    dict for {x x x} x x
584} -result {must have exactly two variable names}
585test dict-14.7 {dict for command: syntax} -returnCodes error -body {
586    dict for "\{x" x x
587} -result {unmatched open brace in list}
588test dict-14.8 {dict for command} -body {
589    # This test confirms that [dict keys], [dict values] and [dict for]
590    # all traverse a dictionary in the same order.
591    set dictv {a A b B c C}
592    set keys {}
593    set values {}
594    dict for {k v} $dictv {
595	lappend keys $k
596	lappend values $v
597    }
598    set result [expr {
599	$keys eq [dict keys $dictv] && $values eq [dict values $dictv]
600    }]
601    expr {$result ? "YES" : [list "NO" $dictv $keys $values]}
602} -cleanup {
603    unset result keys values k v dictv
604} -result YES
605test dict-14.9 {dict for command} {
606    dict for {k v} {} {
607	error "unexpected execution of 'dict for' body"
608    }
609} {}
610test dict-14.10 {dict for command: script results} -body {
611    set times 0
612    dict for {k v} {a a b b} {
613	incr times
614	continue
615	error "shouldn't get here"
616    }
617    return $times
618} -cleanup {
619    unset times k v
620} -result 2
621test dict-14.11 {dict for command: script results} -body {
622    set times 0
623    dict for {k v} {a a b b} {
624	incr times
625	break
626	error "shouldn't get here"
627    }
628    return $times
629} -cleanup {
630    unset times k v
631} -result 1
632test dict-14.12 {dict for command: script results} -body {
633    set times 0
634    list [catch {
635	dict for {k v} {a a b b} {
636	    incr times
637	    error test
638	}
639    } msg] $msg $times $::errorInfo
640} -cleanup {
641    unset times k v msg
642} -result {1 test 1 {test
643    while executing
644"error test"
645    ("dict for" body line 3)
646    invoked from within
647"dict for {k v} {a a b b} {
648	    incr times
649	    error test
650	}"}}
651test dict-14.13 {dict for command: script results} {
652    apply {{} {
653	dict for {k v} {a b} {
654	    return ok,$k,$v
655	    error "skipped return completely"
656	}
657	error "return didn't go far enough"
658    }}
659} ok,a,b
660test dict-14.14 {dict for command: handle representation loss} -body {
661    set dictVar {a b c d e f g h}
662    set keys {}
663    set values {}
664    dict for {k v} $dictVar {
665	if {[llength $dictVar]} {
666	    lappend keys $k
667	    lappend values $v
668	}
669    }
670    list [lsort $keys] [lsort $values]
671} -cleanup {
672    unset dictVar keys values k v
673} -result {{a c e g} {b d f h}}
674test dict-14.15 {dict for command: keys are unique and iterated over once only} -setup {
675    unset -nocomplain accum
676    array set accum {}
677} -body {
678    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
679    dict for {k v} $dictVar {
680	append accum($k) $v,
681    }
682    set result [lsort [array names accum]]
683    lappend result :
684    foreach k $result {
685	catch {lappend result $accum($k)}
686    }
687    return $result
688} -cleanup {
689    unset dictVar k v result accum
690} -result {a1 a2 b1 b2 bar foo : a, b, c, d, foo, bar,}
691test dict-14.16 {dict for command in compilation context} {
692    apply {{} {
693	set res {x x x x x x}
694	dict for {k v} {a 0 b 1 c 2 d 3 e 4 f 5} {
695	    lset res $v $k
696	    continue
697	}
698	return $res
699    }}
700} {a b c d e f}
701test dict-14.17 {dict for command in compilation context} {
702    # Bug 1379349
703    apply {{} {
704	set d [dict create a 1]		;# Dict must be unshared!
705	dict for {k v} $d {
706	    dict set d $k 0		;# Any modification will do
707	}
708	return $d
709    }}
710} {a 0}
711test dict-14.18 {dict for command in compilation context} {
712    # Bug 1382528
713    apply {{} {
714	dict for {k v} {} {}		;# Note empty dict
715	catch { error foo }		;# Note compiled [catch]
716    }}
717} 1
718test dict-14.19 {dict for and invalid dicts: bug 1531184} -body {
719    di[list]ct for {k v} x {}
720} -returnCodes 1 -result {missing value to go with key}
721test dict-14.20 {dict for stack space compilation: bug 1903325} {
722    apply {{x y args} {
723	dict for {a b} $x {}
724	concat "c=$y,$args"
725    }} {} 1 2 3
726} {c=1,2 3}
727test dict-14.21 {compiled dict for and break} {
728    apply {{} {
729	dict for {a b} {c d e f} {
730	    lappend result $a,$b
731	    break
732	}
733	return $result
734    }}
735} c,d
736test dict-14.22 {dict for and exception range depths: Bug 3614382} {
737    apply {{} {
738	dict for {a b} {c d} {
739	    dict for {e f} {g h} {
740		return 5
741	    }
742	}
743    }}
744} 5
745# There's probably a lot more tests to add here. Really ought to use a
746# coverage tool for this job...
747
748test dict-15.1 {dict set command} -body {
749    set dictVar {}
750    dict set dictVar a x
751} -cleanup {
752    unset dictVar
753} -result {a x}
754test dict-15.2 {dict set command} -body {
755    set dictvar {a {}}
756    dict set dictvar a b x
757} -cleanup {
758    unset dictvar
759} -result {a {b x}}
760test dict-15.3 {dict set command} -body {
761    set dictvar {a {b {}}}
762    dict set dictvar a b c x
763} -cleanup {
764    unset dictvar
765} -result {a {b {c x}}}
766test dict-15.4 {dict set command} -body {
767    set dictVar {a y}
768    dict set dictVar a x
769} -cleanup {
770    unset dictVar
771} -result {a x}
772test dict-15.5 {dict set command} -body {
773    set dictVar {a {b y}}
774    dict set dictVar a b x
775} -cleanup {
776    unset dictVar
777} -result {a {b x}}
778test dict-15.6 {dict set command} -body {
779    set dictVar {a {b {c y}}}
780    dict set dictVar a b c x
781} -cleanup {
782    unset dictVar
783} -result {a {b {c x}}}
784test dict-15.7 {dict set command: path creation} -body {
785    set dictVar {}
786    dict set dictVar a b x
787} -cleanup {
788    unset dictVar
789} -result {a {b x}}
790test dict-15.8 {dict set command: creates variables} -setup {
791    unset -nocomplain dictVar
792} -body {
793    dict set dictVar a x
794    return $dictVar
795} -cleanup {
796    unset dictVar
797} -result {a x}
798test dict-15.9 {dict set command: write failure} -setup {
799    unset -nocomplain dictVar
800} -body {
801    set dictVar(block) {}
802    dict set dictVar a x
803} -returnCodes error -cleanup {
804    unset dictVar
805} -result {can't set "dictVar": variable is array}
806test dict-15.10 {dict set command: syntax} -returnCodes error -body {
807    dict set
808} -result {wrong # args: should be "dict set dictVarName key ?key ...? value"}
809test dict-15.11 {dict set command: syntax} -returnCodes error -body {
810    dict set a
811} -result {wrong # args: should be "dict set dictVarName key ?key ...? value"}
812test dict-15.12 {dict set command: syntax} -returnCodes error -body {
813    dict set a a
814} -result {wrong # args: should be "dict set dictVarName key ?key ...? value"}
815test dict-15.13 {dict set command} -returnCodes error -body {
816    set dictVar a
817    dict set dictVar b c
818} -cleanup {
819    unset dictVar
820} -result {missing value to go with key}
821
822test dict-16.1 {dict unset command} -body {
823    set dictVar {a b c d}
824    dict unset dictVar a
825} -cleanup {
826    unset dictVar
827} -result {c d}
828test dict-16.2 {dict unset command} -body {
829    set dictVar {a b c d}
830    dict unset dictVar c
831} -cleanup {
832    unset dictVar
833} -result {a b}
834test dict-16.3 {dict unset command} -body {
835    set dictVar {a b}
836    dict unset dictVar c
837} -cleanup {
838    unset dictVar
839} -result {a b}
840test dict-16.4 {dict unset command} -body {
841    set dictVar {a {b c d e}}
842    dict unset dictVar a b
843} -cleanup {
844    unset dictVar
845} -result {a {d e}}
846test dict-16.5 {dict unset command} -returnCodes error -body {
847    set dictVar a
848    dict unset dictVar a
849} -cleanup {
850    unset dictVar
851} -result {missing value to go with key}
852test dict-16.6 {dict unset command} -returnCodes error -body {
853    set dictVar {a b}
854    dict unset dictVar c d
855} -cleanup {
856    unset dictVar
857} -result {key "c" not known in dictionary}
858test dict-16.7 {dict unset command} -setup {
859    unset -nocomplain dictVar
860} -body {
861    list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]
862} -cleanup {
863    unset dictVar
864} -result {0 {} 1}
865test dict-16.8 {dict unset command} -returnCodes error -body {
866    dict unset dictVar
867} -result {wrong # args: should be "dict unset dictVarName key ?key ...?"}
868test dict-16.9 {dict unset command: write failure} -setup {
869    unset -nocomplain dictVar
870} -body {
871    set dictVar(block) {}
872    dict unset dictVar a
873} -returnCodes error -cleanup {
874    unset dictVar
875} -result {can't set "dictVar": variable is array}
876# Now test with an LVT present (i.e., the bytecoded version).
877test dict-16.10 {dict unset command} -body {
878    apply {{} {
879	set dictVar {a b c d}
880	dict unset dictVar a
881    }}
882} -result {c d}
883test dict-16.11 {dict unset command} -body {
884    apply {{} {
885	set dictVar {a b c d}
886	dict unset dictVar c
887    }}
888} -result {a b}
889test dict-16.12 {dict unset command} -body {
890    apply {{} {
891	set dictVar {a b}
892	dict unset dictVar c
893    }}
894} -result {a b}
895test dict-16.13 {dict unset command} -body {
896    apply {{} {
897	set dictVar {a {b c d e}}
898	dict unset dictVar a b
899    }}
900} -result {a {d e}}
901test dict-16.14 {dict unset command} -returnCodes error -body {
902    apply {{} {
903	set dictVar a
904	dict unset dictVar a
905    }}
906} -result {missing value to go with key}
907test dict-16.15 {dict unset command} -returnCodes error -body {
908    apply {{} {
909	set dictVar {a b}
910	dict unset dictVar c d
911    }}
912} -result {key "c" not known in dictionary}
913test dict-16.16 {dict unset command} -body {
914    apply {{} {list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]}}
915} -result {0 {} 1}
916test dict-16.17 {dict unset command} -returnCodes error -body {
917    apply {{} {dict unset dictVar}}
918} -result {wrong # args: should be "dict unset dictVarName key ?key ...?"}
919test dict-16.18 {dict unset command: write failure} -body {
920    apply {{} {
921	set dictVar(block) {}
922	dict unset dictVar a
923    }}
924} -returnCodes error -result {can't set "dictVar": variable is array}
925
926test dict-17.1 {dict filter command: key} -body {
927    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
928    dict filter $dictVar key a2
929} -cleanup {
930    unset dictVar
931} -result {a2 b}
932test dict-17.2 {dict filter command: key} -body {
933    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
934    dict size [dict filter $dictVar key *]
935} -cleanup {
936    unset dictVar
937} -result 6
938test dict-17.3 {dict filter command: key} -body {
939    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
940    dict filter $dictVar key ???
941} -cleanup {
942    unset dictVar
943} -result {foo bar bar foo}
944test dict-17.4 {dict filter command: key - no patterns} {
945    dict filter {a b c d} key
946} {}
947test dict-17.4.1 {dict filter command: key - many patterns} {
948    dict filter {a1 a a2 b b1 c b2 d foo bar bar foo} key a? b?
949} {a1 a a2 b b1 c b2 d}
950test dict-17.5 {dict filter command: key - bad dict} -returnCodes error -body {
951    dict filter {a b c} key
952} -result {missing value to go with key}
953test dict-17.6 {dict filter command: value} -body {
954    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
955    dict filter $dictVar value c
956} -cleanup {
957    unset dictVar
958} -result {b1 c}
959test dict-17.7 {dict filter command: value} -body {
960    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
961    dict size [dict filter $dictVar value *]
962} -cleanup {
963    unset dictVar
964} -result 6
965test dict-17.8 {dict filter command: value} -body {
966    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
967    dict filter $dictVar value ???
968} -cleanup {
969    unset dictVar
970} -result {foo bar bar foo}
971test dict-17.9 {dict filter command: value - no patterns} {
972    dict filter {a b c d} value
973} {}
974test dict-17.9.1 {dict filter command: value - many patterns} {
975    dict filter {a a1 b a2 c b1 foo bar bar foo d b2} value a? b?
976} {a a1 b a2 c b1 d b2}
977test dict-17.10 {dict filter command: value - bad dict} -body {
978    dict filter {a b c} value a
979} -returnCodes error -result {missing value to go with key}
980test dict-17.11 {dict filter command: script} -body {
981    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
982    set n 0
983    list [dict filter $dictVar script {k v} {
984	incr n
985	expr {[string length $k] == [string length $v]}
986    }] $n
987} -cleanup {
988    unset dictVar n k v
989} -result {{foo bar bar foo} 6}
990test dict-17.12 {dict filter command: script} -returnCodes error -body {
991    dict filter {a b} script {k v} {
992	concat $k $v
993    }
994} -cleanup {
995    unset k v
996} -result {expected boolean value but got "a b"}
997test dict-17.13 {dict filter command: script} -body {
998    list [catch {dict filter {a b} script {k v} {error x}} msg] $msg \
999	    $::errorInfo
1000} -cleanup {
1001    unset k v msg
1002} -result {1 x {x
1003    while executing
1004"error x"
1005    ("dict filter" script line 1)
1006    invoked from within
1007"dict filter {a b} script {k v} {error x}"}}
1008test dict-17.14 {dict filter command: script} -setup {
1009    set n 0
1010} -body {
1011    list [dict filter {a b c d} script {k v} {
1012	incr n
1013	break
1014	error boom!
1015    }] $n
1016} -cleanup {
1017    unset n k v
1018} -result {{} 1}
1019test dict-17.15 {dict filter command: script} -setup {
1020    set n 0
1021} -body {
1022    list [dict filter {a b c d} script {k v} {
1023	incr n
1024	continue
1025	error boom!
1026    }] $n
1027} -cleanup {
1028    unset n k v
1029} -result {{} 2}
1030test dict-17.16 {dict filter command: script} {
1031    apply {{} {
1032	dict filter {a b} script {k v} {
1033	    return ok,$k,$v
1034	    error "skipped return completely"
1035	}
1036	error "return didn't go far enough"
1037    }}
1038} ok,a,b
1039test dict-17.17 {dict filter command: script} -body {
1040    dict filter {a b} script {k k} {continue}
1041    return $k
1042} -cleanup {
1043    unset k
1044} -result b
1045test dict-17.18 {dict filter command: script} -returnCodes error -body {
1046    dict filter {a b} script {k k}
1047} -result {wrong # args: should be "dict filter dictionary script {keyVarName valueVarName} filterScript"}
1048test dict-17.19 {dict filter command: script} -returnCodes error -body {
1049    dict filter {a b} script k {continue}
1050} -result {must have exactly two variable names}
1051test dict-17.20 {dict filter command: script} -returnCodes error -body {
1052    dict filter {a b} script "\{k v" {continue}
1053} -result {unmatched open brace in list}
1054test dict-17.21 {dict filter command} -returnCodes error -body {
1055    dict filter {a b}
1056} -result {wrong # args: should be "dict filter dictionary filterType ?arg ...?"}
1057test dict-17.22 {dict filter command} -returnCodes error -body {
1058    dict filter {a b} JUNK
1059} -result {bad filterType "JUNK": must be key, script, or value}
1060test dict-17.23 {dict filter command} -returnCodes error -body {
1061    dict filter a key *
1062} -result {missing value to go with key}
1063
1064test dict-18.1 {dict-list relationship} -body {
1065    # Test that any internal conversion between list and dict does not change
1066    # the object
1067    set l [list 1 2 3 4 5 6 7 8 9 0 q w e r t y]
1068    dict values $l
1069    return $l
1070} -cleanup {
1071    unset l
1072} -result {1 2 3 4 5 6 7 8 9 0 q w e r t y}
1073test dict-18.2 {dict-list relationship} -body {
1074    # Test that the dictionary is a valid list
1075    set d [dict create "abc def" 0 "a\{b" 1 "c\}d" 2]
1076    for {set t 0} {$t < 5} {incr t} {
1077	llength $d
1078	dict lappend d "abc def" "\}\{"
1079	dict append  d "a\{b" "\}"
1080	dict incr    d "c\}d" 1
1081    }
1082    llength $d
1083} -cleanup {
1084    unset d t
1085} -result 6
1086test dict-18.3 {dict-list relationship} -body {
1087    set ld [list a b c d c e f g]
1088    list [string length $ld] [dict size $ld] [llength $ld]
1089} -cleanup {
1090    unset ld
1091} -result {15 3 8}
1092test dict-18.4 {dict-list relationship} -body {
1093    set ld [list a b c d c e f g]
1094    list [llength $ld] [dict size $ld] [llength $ld]
1095} -cleanup {
1096    unset ld
1097} -result {8 3 8}
1098
1099# This is a test for a specific bug.
1100# It shows a bad ref counter when running with memdebug on.
1101test dict-19.1 {memory bug} {
1102    apply {{} {
1103        set successors [dict create x {c d}]
1104        dict set successors x a b
1105        dict get $successors x
1106    }}
1107} [dict create c d a b]
1108test dict-19.2 {dict: testing for leaks} -constraints memory -body {
1109    # This test is made to stress object reference management
1110    memtest {
1111	apply {{} {
1112	    # A shared invalid dictinary
1113	    set apa {a {}b c d}
1114	    set bepa $apa
1115	    catch {dict replace $apa e f}
1116	    catch {dict remove  $apa c d}
1117	    catch {dict incr    apa  a 5}
1118	    catch {dict lappend apa  a 5}
1119	    catch {dict append  apa  a 5}
1120	    catch {dict set     apa  a 5}
1121	    catch {dict unset   apa  a}
1122
1123	    # A shared valid dictionary, invalid incr
1124	    set apa {a b c d}
1125	    set bepa $apa
1126	    catch {dict incr bepa a 5}
1127
1128	    # An error during write to an unshared object, incr
1129	    set apa {a 1 b 2}
1130	    set bepa [lrange $apa 0 end]
1131	    trace add variable bepa write {error hej}
1132	    catch {dict incr bepa a 5}
1133	    trace remove variable bepa write {error hej}
1134	    unset bepa
1135
1136	    # An error during write to a shared object, incr
1137	    set apa {a 1 b 2}
1138	    set bepa $apa
1139	    trace add variable bepa write {error hej}
1140	    catch {dict incr bepa a 5}
1141	    trace remove variable bepa write {error hej}
1142	    unset bepa
1143
1144	    # A shared valid dictionary, invalid lappend
1145	    set apa [list a {{}b} c d]
1146	    set bepa $apa
1147	    catch {dict lappend bepa a 5}
1148
1149	    # An error during write to an unshared object, lappend
1150	    set apa {a 1 b 2}
1151	    set bepa [lrange $apa 0 end]
1152	    trace add variable bepa write {error hej}
1153	    catch {dict lappend bepa a 5}
1154	    trace remove variable bepa write {error hej}
1155	    unset bepa
1156
1157	    # An error during write to a shared object, lappend
1158	    set apa {a 1 b 2}
1159	    set bepa $apa
1160	    trace add variable bepa write {error hej}
1161	    catch {dict lappend bepa a 5}
1162	    trace remove variable bepa write {error hej}
1163	    unset bepa
1164
1165	    # An error during write to an unshared object, append
1166	    set apa {a 1 b 2}
1167	    set bepa [lrange $apa 0 end]
1168	    trace add variable bepa write {error hej}
1169	    catch {dict append bepa a 5}
1170	    trace remove variable bepa write {error hej}
1171	    unset bepa
1172
1173	    # An error during write to a shared object, append
1174	    set apa {a 1 b 2}
1175	    set bepa $apa
1176	    trace add variable bepa write {error hej}
1177	    catch {dict append bepa a 5}
1178	    trace remove variable bepa write {error hej}
1179	    unset bepa
1180
1181	    # An error during write to an unshared object, set
1182	    set apa {a 1 b 2}
1183	    set bepa [lrange $apa 0 end]
1184	    trace add variable bepa write {error hej}
1185	    catch {dict set bepa a 5}
1186	    trace remove variable bepa write {error hej}
1187	    unset bepa
1188
1189	    # An error during write to a shared object, set
1190	    set apa {a 1 b 2}
1191	    set bepa $apa
1192	    trace add variable bepa write {error hej}
1193	    catch {dict set bepa a 5}
1194	    trace remove variable bepa write {error hej}
1195	    unset bepa
1196
1197	    # An error during write to an unshared object, unset
1198	    set apa {a 1 b 2}
1199	    set bepa [lrange $apa 0 end]
1200	    trace add variable bepa write {error hej}
1201	    catch {dict unset bepa a}
1202	    trace remove variable bepa write {error hej}
1203	    unset bepa
1204
1205	    # An error during write to a shared object, unset
1206	    set apa {a 1 b 2}
1207	    set bepa $apa
1208	    trace add variable bepa write {error hej}
1209	    catch {dict unset bepa a}
1210	    trace remove variable bepa write {error hej}
1211	    unset bepa
1212	}}
1213    }
1214} -result 0
1215test dict-19.3 {testing for leaks - Bug 2874678} -constraints memory -body {
1216    set d aDictVar; # Force interpreted [dict incr]
1217    memtest {
1218	dict incr $d aKey 0
1219	unset $d
1220    }
1221} -cleanup {
1222    unset d
1223} -result 0
1224
1225test dict-20.1 {dict merge command} {
1226    dict merge
1227} {}
1228test dict-20.2 {dict merge command} {
1229    dict merge {a b c d e f}
1230} {a b c d e f}
1231test dict-20.3 {dict merge command} -body {
1232    dict merge {a b c d e}
1233} -result {missing value to go with key} -returnCodes error
1234test dict-20.4 {dict merge command} {
1235    dict merge {a b c d} {e f g h}
1236} {a b c d e f g h}
1237test dict-20.5 {dict merge command} -body {
1238    dict merge {a b c d e} {e f g h}
1239} -result {missing value to go with key} -returnCodes error
1240test dict-20.6 {dict merge command} -body {
1241    dict merge {a b c d} {e f g h i}
1242} -result {missing value to go with key} -returnCodes error
1243test dict-20.7 {dict merge command} {
1244    dict merge {a b c d e f} {e x g h}
1245} {a b c d e x g h}
1246test dict-20.8 {dict merge command} {
1247    dict merge {a b c d} {a x c y}
1248} {a x c y}
1249test dict-20.9 {dict merge command} {
1250    dict merge {a b c d} {c y a x}
1251} {a x c y}
1252test dict-20.10 {dict merge command} {
1253    dict merge {a b c d e f} {a x 1 2 3 4} {a - 1 -}
1254} {a - c d e f 1 - 3 4}
1255test dict-20.11 {dict merge command} {
1256    apply {{} {dict merge}}
1257} {}
1258test dict-20.12 {dict merge command} {
1259    apply {{} {dict merge {a b c d e f}}}
1260} {a b c d e f}
1261test dict-20.13 {dict merge command} -body {
1262    apply {{} {dict merge {a b c d e}}}
1263} -result {missing value to go with key} -returnCodes error
1264test dict-20.14 {dict merge command} {
1265    apply {{} {dict merge {a b c d} {e f g h}}}
1266} {a b c d e f g h}
1267test dict-20.15 {dict merge command} -body {
1268    apply {{} {dict merge {a b c d e} {e f g h}}}
1269} -result {missing value to go with key} -returnCodes error
1270test dict-20.16 {dict merge command} -body {
1271    apply {{} {dict merge {a b c d} {e f g h i}}}
1272} -result {missing value to go with key} -returnCodes error
1273test dict-20.17 {dict merge command} {
1274    apply {{} {dict merge {a b c d e f} {e x g h}}}
1275} {a b c d e x g h}
1276test dict-20.18 {dict merge command} {
1277    apply {{} {dict merge {a b c d} {a x c y}}}
1278} {a x c y}
1279test dict-20.19 {dict merge command} {
1280    apply {{} {dict merge {a b c d} {c y a x}}}
1281} {a x c y}
1282test dict-20.20 {dict merge command} {
1283    apply {{} {dict merge {a b c d e f} {a x 1 2 3 4} {a - 1 -}}}
1284} {a - c d e f 1 - 3 4}
1285test dict-20.21 {dict merge command: canonicality not forced} {
1286    dict merge { a b c d }
1287} { a b c d }
1288test dict-20.22 {dict merge command: canonicality not forced} {
1289    dict merge { a b c d } {}
1290} { a b c d }
1291test dict-20.23 {dict merge command: canonicality forced by update} {
1292    dict merge { a b c d } {a b}
1293} {a b c d}
1294test dict-20.24 {dict merge command: type check is mandatory} -body {
1295    dict merge { a b c d e }
1296} -returnCodes error -result {missing value to go with key}
1297test dict-20.25 {dict merge command: type check is mandatory} -body {
1298    dict merge { a b {}c d }
1299} -returnCodes error -result {dict element in braces followed by "c" instead of space}
1300
1301test dict-21.1 {dict update command} -returnCodes 1 -body {
1302    dict update
1303} -result {wrong # args: should be "dict update dictVarName key varName ?key varName ...? script"}
1304test dict-21.2 {dict update command} -returnCodes 1 -body {
1305    dict update v
1306} -result {wrong # args: should be "dict update dictVarName key varName ?key varName ...? script"}
1307test dict-21.3 {dict update command} -returnCodes 1 -body {
1308    dict update v k
1309} -result {wrong # args: should be "dict update dictVarName key varName ?key varName ...? script"}
1310test dict-21.4 {dict update command} -returnCodes 1 -body {
1311    dict update v k v
1312} -result {wrong # args: should be "dict update dictVarName key varName ?key varName ...? script"}
1313test dict-21.5 {dict update command} -body {
1314    set a {b c}
1315    set result {}
1316    set bb {}
1317    dict update a b bb {
1318	lappend result $a $bb
1319    }
1320    lappend result $a
1321} -cleanup {
1322    unset a result bb
1323} -result {{b c} c {b c}}
1324test dict-21.6 {dict update command} -body {
1325    set a {b c}
1326    set result {}
1327    set bb {}
1328    dict update a b bb {
1329	lappend result $a $bb [set bb d]
1330    }
1331    lappend result $a
1332} -cleanup {
1333    unset a result bb
1334} -result {{b c} c d {b d}}
1335test dict-21.7 {dict update command} -body {
1336    set a {b c}
1337    set result {}
1338    set bb {}
1339    dict update a b bb {
1340	lappend result $a $bb [unset bb]
1341    }
1342    lappend result $a
1343} -cleanup {
1344    unset a result
1345} -result {{b c} c {} {}}
1346test dict-21.8 {dict update command} -body {
1347    set a {b c d e}
1348    dict update a b v1 d v2 {
1349	lassign "$v1 $v2" v2 v1
1350    }
1351    return $a
1352} -cleanup {
1353    unset a v1 v2
1354} -result {b e d c}
1355test dict-21.9 {dict update command} -body {
1356    set a {b c d e}
1357    dict update a b v1 d v2 {unset a}
1358    info exist a
1359} -cleanup {
1360    unset v1 v2
1361} -result 0
1362test dict-21.10 {dict update command} -body {
1363    set a {b {c d}}
1364    dict update a b v1 {
1365	dict update v1 c v2 {
1366	    set v2 foo
1367	}
1368    }
1369    return $a
1370} -cleanup {
1371    unset a v1 v2
1372} -result {b {c foo}}
1373test dict-21.11 {dict update command} -body {
1374    set a {b c d e}
1375    dict update a b v1 d v2 {
1376	dict set a f g
1377    }
1378    return $a
1379} -cleanup {
1380    unset a v1 v2
1381} -result {b c d e f g}
1382test dict-21.12 {dict update command} -body {
1383    set a {b c d e}
1384    dict update a b v1 d v2 f v3 {
1385	set v3 g
1386    }
1387    return $a
1388} -cleanup {
1389    unset a v1 v2 v3
1390} -result {b c d e f g}
1391test dict-21.13 {dict update command: compilation} {
1392    apply {d {
1393	while 1 {
1394	    dict update d a alpha b beta {
1395		set beta $alpha
1396		unset alpha
1397		break
1398	    }
1399	}
1400	return $d
1401    }} {a 1 c 2}
1402} {c 2 b 1}
1403test dict-21.14 {dict update command: compilation} {
1404    apply {x {
1405	set indices {2 3}
1406	trace add variable aa write "string length \$indices ;#"
1407	dict update x k aa l bb {}
1408    }} {k 1 l 2}
1409} {}
1410test dict-21.15 {dict update command: compilation} {
1411    apply {x {
1412	set indices {2 3}
1413	trace add variable aa read "string length \$indices ;#"
1414	dict update x k aa l bb {}
1415    }} {k 1 l 2}
1416} {}
1417test dict-21.16 {dict update command: no recursive structures [Bug 1786481]} -body {
1418    set foo {a {b {c {d {e 1}}}}}
1419    dict update foo a t {
1420	dict update t b t {
1421	    dict update t c t {
1422		dict update t d t {
1423		    dict incr t e
1424		}
1425	    }
1426	}
1427    }
1428    string range [append foo OK] end-1 end
1429} -cleanup {
1430    unset foo t
1431} -result OK
1432test dict-21.17 {dict update command: no recursive structures [Bug 1786481]} {
1433    apply {{} {
1434	set foo {a {b {c {d {e 1}}}}}
1435	dict update foo a t {
1436	    dict update t b t {
1437		dict update t c t {
1438		    dict update t d t {
1439			dict incr t e
1440		    }
1441		}
1442	    }
1443	}
1444	string range [append foo OK] end-1 end
1445    }}
1446} OK
1447
1448test dict-22.1 {dict with command} -body {
1449    dict with
1450} -returnCodes 1 -result {wrong # args: should be "dict with dictVarName ?key ...? script"}
1451test dict-22.2 {dict with command} -body {
1452    dict with v
1453} -returnCodes 1 -result {wrong # args: should be "dict with dictVarName ?key ...? script"}
1454test dict-22.3 {dict with command} -body {
1455    unset -nocomplain v
1456    dict with v {error "in body"}
1457} -returnCodes 1 -result {can't read "v": no such variable}
1458test dict-22.4 {dict with command} -body {
1459    set a {b c d e}
1460    unset -nocomplain b d
1461    set result [list [info exist b] [info exist d]]
1462    dict with a {
1463	lappend result [info exist b] [info exist d] $b $d
1464    }
1465    return $result
1466} -cleanup {
1467    unset a b d result
1468} -result {0 0 1 1 c e}
1469test dict-22.5 {dict with command} -body {
1470    set a {b c d e}
1471    dict with a {
1472	lassign "$b $d" d b
1473    }
1474    return $a
1475} -cleanup {
1476    unset a b d
1477} -result {b e d c}
1478test dict-22.6 {dict with command} -body {
1479    set a {b c d e}
1480    dict with a {
1481	unset b
1482	# This *won't* go into the dict...
1483	set f g
1484    }
1485    return $a
1486} -cleanup {
1487    unset a d f
1488} -result {d e}
1489test dict-22.7 {dict with command} -body {
1490    set a {b c d e}
1491    dict with a {
1492	dict unset a b
1493    }
1494    return $a
1495} -cleanup {
1496    unset a
1497} -result {d e b c}
1498test dict-22.8 {dict with command} -body {
1499    set a [dict create b c]
1500    dict with a {
1501	set b $a
1502    }
1503    return $a
1504} -cleanup {
1505    unset a b
1506} -result {b {b c}}
1507test dict-22.9 {dict with command} -body {
1508    set a {b {c d}}
1509    dict with a b {
1510	set c $c$c
1511    }
1512    return $a
1513} -cleanup {
1514    unset a c
1515} -result {b {c dd}}
1516test dict-22.10 {dict with command: result handling tricky case} -body {
1517    set a {b {c d}}
1518    foreach i {0 1} {
1519	if {$i} break
1520	dict with a b {
1521	    set a {}
1522	    # We're checking to see if we lose this break
1523	    break
1524	}
1525    }
1526    list $i $a
1527} -cleanup {
1528    unset a i c
1529} -result {0 {}}
1530test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} -body {
1531    set foo {t {t {t {inner 1}}}}
1532    dict with foo {
1533	dict with t {
1534	    dict with t {
1535		dict with t {
1536		    incr inner
1537		}
1538	    }
1539	}
1540    }
1541    string range [append foo OK] end-1 end
1542} -cleanup {
1543    unset foo t inner
1544} -result OK
1545test dict-22.12 {dict with: compiled} {
1546    apply {{} {
1547	set d {a 1 b 2}
1548	list [dict with d {
1549	    set a $b
1550	    unset b
1551	    dict set d c 3
1552	    list ok
1553	}] $d
1554    }}
1555} {ok {a 2 c 3}}
1556test dict-22.13 {dict with: compiled} {
1557    apply {i {
1558	set d($i) {a 1 b 2}
1559	list [dict with d($i) {
1560	    set a $b
1561	    unset b
1562	    dict set d($i) c 3
1563	    list ok
1564	}] [array get d]
1565    }} e
1566} {ok {e {a 2 c 3}}}
1567test dict-22.14 {dict with: compiled} {
1568    apply {{} {
1569	set d {a 1 b 2}
1570	foreach x {1 2 3} {
1571	    dict with d {
1572		incr a $b
1573		if {$x == 2} break
1574	    }
1575	    unset a b
1576	}
1577	list $a $b $x $d
1578    }}
1579} {5 2 2 {a 5 b 2}}
1580test dict-22.15 {dict with: compiled} {
1581    apply {i {
1582	set d($i) {a 1 b 2}
1583	foreach x {1 2 3} {
1584	    dict with d($i) {
1585		incr a $b
1586		if {$x == 2} break
1587	    }
1588	    unset a b
1589	}
1590	list $a $b $x [array get d]
1591    }} e
1592} {5 2 2 {e {a 5 b 2}}}
1593test dict-22.16 {dict with: compiled} {
1594    apply {{} {
1595	set d {p {q {a 1 b 2}}}
1596	dict with d p q {
1597	    set a $b.$a
1598	}
1599	return $d
1600    }}
1601} {p {q {a 2.1 b 2}}}
1602test dict-22.17 {dict with: compiled} {
1603    apply {i {
1604	set d($i) {p {q {a 1 b 2}}}
1605	dict with d($i) p q {
1606	    set a $b.$a
1607	}
1608	array get d
1609    }} e
1610} {e {p {q {a 2.1 b 2}}}}
1611test dict-22.18 {dict with: compiled} {
1612    set ::d {a 1 b 2}
1613    apply {{} {
1614	dict with ::d {
1615	    set a $b.$a
1616	}
1617	return $::d
1618    }}
1619} {a 2.1 b 2}
1620test dict-22.19 {dict with: compiled} {
1621    set ::d {p {q {r {a 1 b 2}}}}
1622    apply {{} {
1623	dict with ::d p q r {
1624	    set a $b.$a
1625	}
1626	return $::d
1627    }}
1628} {p {q {r {a 2.1 b 2}}}}
1629test dict-22.20 {dict with: compiled} {
1630    apply {d {
1631	dict with d {
1632	}
1633	return $a,$b
1634    }} {a 1 b 2}
1635} 1,2
1636test dict-22.21 {dict with: compiled} {
1637    apply {d {
1638	dict with d p q {
1639	}
1640	return $a,$b
1641    }} {p {q {a 1 b 2}}}
1642} 1,2
1643test dict-22.22 {dict with: compiled} {
1644    set ::d {a 1 b 2}
1645    apply {{} {
1646	dict with ::d {
1647	}
1648	return $a,$b
1649    }}
1650} 1,2
1651test dict-22.23 {dict with: compiled} {
1652    set ::d {p {q {a 1 b 2}}}
1653    apply {{} {
1654	dict with ::d p q {
1655	}
1656	return $a,$b
1657    }}
1658} 1,2
1659
1660proc linenumber {} {
1661    dict get [info frame -1] line
1662}
1663test dict-23.1 {dict compilation crash: Bug 3487626} {
1664    apply {{} {apply {n {
1665	set e {}
1666	set k {}
1667	dict for {a b} {c {d {e {f g}}}} {
1668	    ::tcl::dict::for {h i} $b {
1669		dict update i e j {
1670		    ::tcl::dict::update j f k {
1671			return [expr {$n - [linenumber]}]
1672		    }
1673		}
1674	    }
1675	}
1676    }} [linenumber]}}
1677} 5
1678test dict-23.2 {dict compilation crash: Bug 3487626} {
1679    # Something isn't quite right in line number and continuation line
1680    # tracking; at time of writing, this test produces 7, not 5, which
1681    # indicates that the extra newlines in the non-script argument are
1682    # confusing things.
1683    apply {{} {apply {n {
1684	set e {}
1685	set k {}
1686	dict for {a {
1687b
1688}} {c {d {e {f g}}}} {
1689	    ::tcl::dict::for {h {
1690i
1691}} ${
1692b
1693} {
1694		dict update {
1695i
1696} e {
1697j
1698} {
1699		    ::tcl::dict::update {
1700j
1701} f k {
1702			return [expr {$n - [linenumber]}]
1703		    }
1704		}
1705	    }
1706	}
1707    }} [linenumber]}}
1708} 5
1709rename linenumber {}
1710
1711test dict-24.1 {dict map command: syntax} -returnCodes error -body {
1712    dict map
1713} -result {wrong # args: should be "dict map {keyVarName valueVarName} dictionary script"}
1714test dict-24.2 {dict map command: syntax} -returnCodes error -body {
1715    dict map x
1716} -result {wrong # args: should be "dict map {keyVarName valueVarName} dictionary script"}
1717test dict-24.3 {dict map command: syntax} -returnCodes error -body {
1718    dict map x x
1719} -result {wrong # args: should be "dict map {keyVarName valueVarName} dictionary script"}
1720test dict-24.4 {dict map command: syntax} -returnCodes error -body {
1721    dict map x x x x
1722} -result {wrong # args: should be "dict map {keyVarName valueVarName} dictionary script"}
1723test dict-24.5 {dict map command: syntax} -returnCodes error -body {
1724    dict map x x x
1725} -result {must have exactly two variable names}
1726test dict-24.6 {dict map command: syntax} -returnCodes error -body {
1727    dict map {x x x} x x
1728} -result {must have exactly two variable names}
1729test dict-24.7 {dict map command: syntax} -returnCodes error -body {
1730    dict map "\{x" x x
1731} -result {unmatched open brace in list}
1732test dict-24.8 {dict map command} -setup {
1733    set values {}
1734    set keys {}
1735} -body {
1736    # This test confirms that [dict keys], [dict values] and [dict map]
1737    # all traverse a dictionary in the same order.
1738    set dictv {a A b B c C}
1739    dict map {k v} $dictv {
1740	lappend keys $k
1741	lappend values $v
1742    }
1743    set result [expr {
1744	$keys eq [dict keys $dictv] && $values eq [dict values $dictv]
1745    }]
1746    expr {$result ? "YES" : [list "NO" $dictv $keys $values]}
1747} -cleanup {
1748    unset result keys values k v dictv
1749} -result YES
1750test dict-24.9 {dict map command} {
1751    dict map {k v} {} {
1752	error "unexpected execution of 'dict map' body"
1753    }
1754} {}
1755test dict-24.10 {dict map command: script results} -body {
1756    set times 0
1757    dict map {k v} {a a b b} {
1758	incr times
1759	continue
1760	error "shouldn't get here"
1761    }
1762    return $times
1763} -cleanup {
1764    unset times k v
1765} -result 2
1766test dict-24.11 {dict map command: script results} -body {
1767    set times 0
1768    dict map {k v} {a a b b} {
1769	incr times
1770	break
1771	error "shouldn't get here"
1772    }
1773    return $times
1774} -cleanup {
1775    unset times k v
1776} -result 1
1777test dict-24.12 {dict map command: script results} -body {
1778    set times 0
1779    list [catch {
1780	dict map {k v} {a a b b} {
1781	    incr times
1782	    error test
1783	}
1784    } msg] $msg $times $::errorInfo
1785} -cleanup {
1786    unset times k v msg
1787} -result {1 test 1 {test
1788    while executing
1789"error test"
1790    ("dict map" body line 3)
1791    invoked from within
1792"dict map {k v} {a a b b} {
1793	    incr times
1794	    error test
1795	}"}}
1796test dict-24.13 {dict map command: script results} {
1797    apply {{} {
1798	dict map {k v} {a b} {
1799	    return ok,$k,$v
1800	    error "skipped return completely"
1801	}
1802	error "return didn't go far enough"
1803    }}
1804} ok,a,b
1805test dict-24.14 {dict map command: handle representation loss} -setup {
1806    set keys {}
1807    set values {}
1808} -body {
1809    set dictVar {a b c d e f g h}
1810    list [dict size [dict map {k v} $dictVar {
1811	if {[llength $dictVar]} {
1812	    lappend keys $k
1813	    lappend values $v
1814	    return -level 0 $k
1815	}
1816    }]] [lsort $keys] [lsort $values]
1817} -cleanup {
1818    unset dictVar keys values k v
1819} -result {4 {a c e g} {b d f h}}
1820test dict-24.14a {dict map command: handle representation loss} -body {
1821    apply {{} {
1822	set dictVar {a b c d e f g h}
1823	list [dict size [dict map {k v} $dictVar {
1824	    if {[llength $dictVar]} {
1825		lappend keys $k
1826		lappend values $v
1827		return -level 0 $k
1828	    }
1829	}]] [lsort $keys] [lsort $values]
1830    }}
1831} -result {4 {a c e g} {b d f h}}
1832test dict-24.15 {dict map command: keys are unique and iterated over once only} -setup {
1833    unset -nocomplain accum
1834    array set accum {}
1835} -body {
1836    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
1837    dict map {k v} $dictVar {
1838	append accum($k) $v,
1839    }
1840    set result [lsort [array names accum]]
1841    lappend result :
1842    foreach k $result {
1843	catch {lappend result $accum($k)}
1844    }
1845    return $result
1846} -cleanup {
1847    unset dictVar k v result accum
1848} -result {a1 a2 b1 b2 bar foo : a, b, c, d, foo, bar,}
1849test dict-24.16 {dict map command in compilation context} {
1850    apply {{} {
1851	set res {x x x x x x}
1852	dict map {k v} {a 0 b 1 c 2 d 3 e 4 f 5} {
1853	    lset res $v $k
1854	    continue
1855	}
1856	return $res
1857    }}
1858} {a b c d e f}
1859test dict-24.17 {dict map command in compilation context} {
1860    # Bug 1379349 (dict for)
1861    apply {{} {
1862	set d [dict create a 1]		;# Dict must be unshared!
1863	dict map {k v} $d {
1864	    dict set d $k 0		;# Any modification will do
1865	}
1866	return $d
1867    }}
1868} {a 0}
1869test dict-24.17a {dict map command in compilation context} {
1870    # Bug 1379349 (dict for)
1871    apply {{} {
1872	set d [dict create a 1]		;# Dict must be unshared!
1873	dict map {k v} $d {
1874	    dict set d $k 0		;# Any modification will do
1875	}
1876    }}
1877} {a {a 0}}
1878test dict-24.18 {dict map command in compilation context} {
1879    # Bug 1382528 (dict for)
1880    apply {{} {
1881	dict map {k v} {} {}		;# Note empty dict
1882	catch { error foo }		;# Note compiled [catch]
1883    }}
1884} 1
1885test dict-24.19 {dict map and invalid dicts: 'dict for' bug 1531184} -body {
1886    di[list]ct map {k v} x {}
1887} -returnCodes 1 -result {missing value to go with key}
1888test dict-24.20 {dict map stack space compilation: 'dict for' bug 1903325} {
1889    apply {{x y args} {
1890	dict map {a b} $x {}
1891	concat "c=$y,$args"
1892    }} {} 1 2 3
1893} {c=1,2 3}
1894proc linenumber {} {
1895    dict get [info frame -1] line
1896}
1897test dict-24.20.1 {dict compilation crash: 'dict for' bug 3487626} {
1898    apply {{} {apply {n {
1899	set e {}
1900	set k {}
1901	dict map {a b} {c {d {e {f g}}}} {
1902	    ::tcl::dict::map {h i} $b {
1903		dict update i e j {
1904		    ::tcl::dict::update j f k {
1905			return [expr {$n - [linenumber]}]
1906		    }
1907		}
1908	    }
1909	}
1910    }} [linenumber]}}
1911} 5
1912test dict-24.21 {dict compilation crash: 'dict for' bug 3487626} {
1913    apply {{} {apply {n {
1914	set e {}
1915	set k {}
1916	dict map {a {
1917b
1918}} {c {d {e {f g}}}} {
1919	    ::tcl::dict::map {h {
1920i
1921}} ${
1922b
1923} {
1924		dict update {
1925i
1926} e {
1927j
1928} {
1929		    ::tcl::dict::update {
1930j
1931} f k {
1932			return [expr {$n - [linenumber]}]
1933		    }
1934		}
1935	    }
1936	}
1937    }} [linenumber]}}
1938} 5
1939test dict-23.3 {CompileWord OBOE} {
1940    # segfault when buggy
1941    apply {{} {tcl::dict::lappend foo bar \
1942	[format baz]}}
1943} {bar baz}
1944test dict-23.4 {CompileWord OBOE} {
1945    apply {n {
1946	dict set foo {*}{
1947	} [return [incr n -[linenumber]]] val
1948    }} [linenumber]
1949} 1
1950test dict-23.5 {CompileWord OBOE} {
1951    # segfault when buggy
1952    apply {{} {tcl::dict::incr foo \
1953	[format bar]}}
1954} {bar 1}
1955test dict-23.6 {CompileWord OBOE} {
1956    apply {n {
1957	dict get {a b} {*}{
1958	} [return [incr n -[linenumber]]]
1959    }} [linenumber]
1960} 1
1961test dict-23.7 {CompileWord OBOE} {
1962    apply {n {
1963	dict for {a b} [return [incr n -[linenumber]]] {*}{
1964	} {}
1965    }} [linenumber]
1966} 2
1967test dict-23.8 {CompileWord OBOE} {
1968    apply {n {
1969	dict update foo {*}{
1970	} [return [incr n -[linenumber]]] x {}
1971    }} [linenumber]
1972} 1
1973test dict-23.9 {CompileWord OBOE} {
1974    apply {n {
1975	dict exists {} {*}{
1976	} [return [incr n -[linenumber]]]
1977    }} [linenumber]
1978} 1
1979test dict-23.10 {CompileWord OBOE} {
1980    apply {n {
1981	dict with foo {*}{
1982	} [return [incr n -[linenumber]]] {}
1983    }} [linenumber]
1984} 1
1985test dict-23.11 {CompileWord OBOE} {
1986    apply {n {
1987	dict with ::foo {*}{
1988	} [return [incr n -[linenumber]]] {}
1989    }} [linenumber]
1990} 1
1991test dict-23.12 {CompileWord OBOE} {
1992    apply {n {
1993	dict with {*}{
1994	} [return [incr n -[linenumber]]] {}
1995    }} [linenumber]
1996} 1
1997test dict-23.13 {CompileWord OBOE} {
1998    apply {n {
1999	dict with {*}{
2000	} [return [incr n -[linenumber]]] {bar}
2001    }} [linenumber]
2002} 1
2003test dict-23.14 {CompileWord OBOE} {
2004    apply {n {
2005	dict with foo {*}{
2006	} [return [incr n -[linenumber]]] {bar}
2007    }} [linenumber]
2008} 1
2009
2010rename linenumber {}
2011test dict-24.22 {dict map results (non-compiled)} {
2012    dict map {k v} [dict map {k v} {a 1 b 2 c 3 d 4} { list $v $k }] {
2013	return -level 0 "$k,$v"
2014    }
2015} {a {a,1 a} b {b,2 b} c {c,3 c} d {d,4 d}}
2016test dict-24.23 {dict map results (compiled)} {
2017    apply {{} {
2018	dict map {k v} [dict map {k v} {a 1 b 2 c 3 d 4} { list $v $k }] {
2019	    return -level 0 "$k,$v"
2020	}
2021    }}
2022} {a {a,1 a} b {b,2 b} c {c,3 c} d {d,4 d}}
2023test dict-24.23a {dict map results (compiled)} {
2024    apply {{list} {
2025	dict map {k v} [dict map {k v} $list { list $v $k }] {
2026	    return -level 0 "$k,$v"
2027	}
2028    }} {a 1 b 2 c 3 d 4}
2029} {a {a,1 a} b {b,2 b} c {c,3 c} d {d,4 d}}
2030test dict-24.24 {dict map with huge dict (non-compiled)} {
2031    tcl::mathop::+ {*}[dict map {k v} [lsearch -all [lrepeat 100000 x] x] {
2032	expr { $k * $v }
2033    }]
2034} 166666666600000
2035test dict-24.25 {dict map with huge dict (compiled)} {
2036    apply {{n} {
2037	tcl::mathop::+ {*}[dict map {k v} [lsearch -all [lrepeat $n y] y] {
2038	    expr { $k * $v }
2039	}]
2040    }} 100000
2041} 166666666600000
2042
2043test dict-25.1 {compiled dict update with low-refcount values [Bug d553228d9f]} {
2044    # Test crashes on failure
2045    apply {{} {
2046	lassign {} item
2047	dict update item item item two two {}
2048    }}
2049} {}
2050
2051set dict dict;			# Used to force interpretation, not compilation
2052test dict-26.1 {dict getdef command} -body {
2053    dict getdef {a b} a c
2054} -result b
2055test dict-26.2 {dict getdef command} -body {
2056    dict getdef {a b} b c
2057} -result c
2058test dict-26.3 {dict getdef command} -body {
2059    dict getdef {a {b c}} a b d
2060} -result c
2061test dict-26.4 {dict getdef command} -body {
2062    dict getdef {a {b c}} a c d
2063} -result d
2064test dict-26.5 {dict getdef command} -body {
2065    dict getdef {a {b c}} b c d
2066} -result d
2067test dict-26.6 {dict getdef command} -returnCodes error -body {
2068    dict getdef {a {b c d}} a b d
2069} -result {missing value to go with key}
2070test dict-26.7 {dict getdef command} -returnCodes error -body {
2071    dict getdef
2072} -result {wrong # args: should be "dict getdef dictionary ?key ...? key default"}
2073test dict-26.8 {dict getdef command} -returnCodes error -body {
2074    dict getdef {}
2075} -result {wrong # args: should be "dict getdef dictionary ?key ...? key default"}
2076test dict-26.9 {dict getdef command} -returnCodes error -body {
2077    dict getdef {} {}
2078} -result {wrong # args: should be "dict getdef dictionary ?key ...? key default"}
2079test dict-26.10 {dict getdef command} -returnCodes error -body {
2080    dict getdef {a b c} d e
2081} -result {missing value to go with key}
2082test dict-26.11 {dict getdef command} -body {
2083    $dict getdef {a b} a c
2084} -result b
2085test dict-26.12 {dict getdef command} -body {
2086    $dict getdef {a b} b c
2087} -result c
2088test dict-26.13 {dict getdef command} -body {
2089    $dict getdef {a {b c}} a b d
2090} -result c
2091test dict-26.14 {dict getdef command} -body {
2092    $dict getdef {a {b c}} a c d
2093} -result d
2094test dict-26.15 {dict getdef command} -body {
2095    $dict getdef {a {b c}} b c d
2096} -result d
2097test dict-26.16 {dict getdef command} -returnCodes error -body {
2098    $dict getdef {a {b c d}} a b d
2099} -result {missing value to go with key}
2100test dict-26.17 {dict getdef command} -returnCodes error -body {
2101    $dict getdef {a b c} d e
2102} -result {missing value to go with key}
2103
2104test dict-27.1 {dict getwithdefault command} -body {
2105    dict getwithdefault {a b} a c
2106} -result b
2107test dict-27.2 {dict getwithdefault command} -body {
2108    dict getwithdefault {a b} b c
2109} -result c
2110test dict-27.3 {dict getwithdefault command} -body {
2111    dict getwithdefault {a {b c}} a b d
2112} -result c
2113test dict-27.4 {dict getwithdefault command} -body {
2114    dict getwithdefault {a {b c}} a c d
2115} -result d
2116test dict-27.5 {dict getwithdefault command} -body {
2117    dict getwithdefault {a {b c}} b c d
2118} -result d
2119test dict-27.6 {dict getwithdefault command} -returnCodes error -body {
2120    dict getwithdefault {a {b c d}} a b d
2121} -result {missing value to go with key}
2122test dict-27.7 {dict getwithdefault command} -returnCodes error -body {
2123    dict getwithdefault
2124} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"}
2125test dict-27.8 {dict getwithdefault command} -returnCodes error -body {
2126    dict getwithdefault {}
2127} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"}
2128test dict-27.9 {dict getwithdefault command} -returnCodes error -body {
2129    dict getwithdefault {} {}
2130} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"}
2131test dict-27.10 {dict getdef command} -returnCodes error -body {
2132    dict getwithdefault {a b c} d e
2133} -result {missing value to go with key}
2134test dict-27.11 {dict getwithdefault command} -body {
2135    $dict getwithdefault {a b} a c
2136} -result b
2137test dict-27.12 {dict getwithdefault command} -body {
2138    $dict getwithdefault {a b} b c
2139} -result c
2140test dict-27.13 {dict getwithdefault command} -body {
2141    $dict getwithdefault {a {b c}} a b d
2142} -result c
2143test dict-27.14 {dict getwithdefault command} -body {
2144    $dict getwithdefault {a {b c}} a c d
2145} -result d
2146test dict-27.15 {dict getwithdefault command} -body {
2147    $dict getwithdefault {a {b c}} b c d
2148} -result d
2149test dict-27.16 {dict getwithdefault command} -returnCodes error -body {
2150    $dict getwithdefault {a {b c d}} a b d
2151} -result {missing value to go with key}
2152test dict-27.17 {dict getdef command} -returnCodes error -body {
2153    $dict getwithdefault {a b c} d e
2154} -result {missing value to go with key}
2155
2156# cleanup
2157::tcltest::cleanupTests
2158return
2159
2160# Local Variables:
2161# mode: tcl
2162# End:
2163