1# This file contains a collection of tests for the msgcat package.
2# Sourcing this file into Tcl runs the tests and
3# generates output for errors.  No output means no errors were found.
4#
5# Copyright (c) 1998 Mark Harrison.
6# Copyright (c) 1998-1999 by Scriptics Corporation.
7# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
8#
9# See the file "license.terms" for information on usage and redistribution
10# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11#
12# Note that after running these tests, entries will be left behind in the
13# message catalogs for locales foo, foo_BAR, and foo_BAR_baz.
14
15if {"::tcltest" ni [namespace children]} {
16    package require tcltest 2.5
17    namespace import -force ::tcltest::*
18}
19
20if {[catch {package require msgcat 1.6}]} {
21    puts stderr "Skipping tests in [info script].  No msgcat 1.6 found to test."
22    return
23}
24
25namespace eval ::msgcat::test {
26    namespace import ::msgcat::*
27    namespace import ::tcltest::test
28    namespace import ::tcltest::cleanupTests
29    namespace import ::tcltest::temporaryDirectory
30    namespace import ::tcltest::make*
31    namespace import ::tcltest::remove*
32
33    # Tests msgcat-0.*: locale initialization
34
35    # Calculate set of all permutations of a list
36    # PowerSet {1 2 3} -> {1 2 3} {2 3} {1 3} 3 {1 2} 2 1 {}
37    proc PowerSet {l} {
38	if {[llength $l] == 0} {return [list [list]]}
39	set element [lindex $l 0]
40	set rest [lrange $l 1 end]
41	set result [list]
42	foreach x [PowerSet $rest] {
43	    lappend result [linsert $x 0 $element]
44	    lappend result $x
45	}
46	return $result
47    }
48
49    variable envVars {LC_ALL LC_MESSAGES LANG}
50    variable count 0
51    variable body
52    variable result
53    variable setVars
54    foreach setVars [PowerSet $envVars] {
55	set result [string tolower [lindex $setVars 0]]
56	if {[string length $result] == 0} {
57	    if {[info exists ::tcl::mac::locale]} {
58		set result [string tolower \
59			[msgcat::ConvertLocale $::tcl::mac::locale]]
60	    } else {
61		if {([info sharedlibextension] eq ".dll")
62			&& ![catch {package require registry}]} {
63		    # Windows and Cygwin have other ways to determine the
64		    # locale when the environment variables are missing
65		    # and the registry package is present
66		    continue
67		}
68		set result c
69	    }
70	}
71
72	test msgcat-0.$count [list \
73	    locale initialization from environment variables $setVars \
74	] -setup {
75	    variable var
76	    foreach var $envVars {
77		catch {variable $var $::env($var)}
78		unset -nocomplain ::env($var)
79	    }
80	    foreach var $setVars {
81		set ::env($var) $var
82	    }
83	    interp create [namespace current]::i
84	    i eval [list package ifneeded msgcat [package provide msgcat] \
85		    [package ifneeded msgcat [package provide msgcat]]]
86	    i eval package require msgcat
87	} -cleanup {
88	    interp delete [namespace current]::i
89	    foreach var $envVars {
90		unset -nocomplain ::env($var)
91		catch {set ::env($var) [set [namespace current]::$var]}
92	    }
93	} -body {i eval msgcat::mclocale} -result $result
94	incr count
95    }
96    unset -nocomplain result
97
98    # Could add tests of initialization from Windows registry here.
99    # Use a fake registry package.
100
101    # Tests msgcat-1.*: [mclocale], [mcpreferences]
102
103    test msgcat-1.3 {mclocale set, single element} -setup {
104	variable locale [mclocale]
105    } -cleanup {
106	mclocale $locale
107    } -body {
108	mclocale en
109    } -result en
110
111    test msgcat-1.4 {mclocale get, single element} -setup {
112	variable locale [mclocale]
113	mclocale en
114    } -cleanup {
115	mclocale $locale
116    } -body {
117	mclocale
118    } -result en
119
120    test msgcat-1.5 {mcpreferences, single element} -setup {
121	variable locale [mclocale]
122	mclocale en
123    } -cleanup {
124	mclocale $locale
125    } -body {
126	mcpreferences
127    } -result {en {}}
128
129    test msgcat-1.6 {mclocale set, two elements} -setup {
130	variable locale [mclocale]
131    } -cleanup {
132	mclocale $locale
133    } -body {
134	mclocale en_US
135    } -result en_us
136
137    test msgcat-1.7 {mclocale get, two elements} -setup {
138	variable locale [mclocale]
139	mclocale en_US
140    } -cleanup {
141	mclocale $locale
142    } -body {
143	mclocale
144    } -result en_us
145
146    test msgcat-1.8 {mcpreferences, two elements} -setup {
147	variable locale [mclocale]
148	mclocale en_US
149    } -cleanup {
150	mclocale $locale
151    } -body {
152	mcpreferences
153    } -result {en_us en {}}
154
155    test msgcat-1.9 {mclocale set, three elements} -setup {
156	variable locale [mclocale]
157    } -cleanup {
158	mclocale $locale
159    } -body {
160	mclocale en_US_funky
161    } -result en_us_funky
162
163    test msgcat-1.10 {mclocale get, three elements} -setup {
164	variable locale [mclocale]
165	mclocale en_US_funky
166    } -cleanup {
167	mclocale $locale
168    } -body {
169	mclocale
170    } -result en_us_funky
171
172    test msgcat-1.11 {mcpreferences, three elements} -setup {
173	variable locale [mclocale]
174	mclocale en_US_funky
175    } -cleanup {
176	mclocale $locale
177    } -body {
178	mcpreferences
179    } -result {en_us_funky en_us en {}}
180
181    test msgcat-1.12 {mclocale set, reject evil input} -setup {
182	variable locale [mclocale]
183    } -cleanup {
184	mclocale $locale
185    } -body {
186	mclocale /path/to/evil/code
187    } -returnCodes error -match glob -result {invalid newLocale value *}
188
189    test msgcat-1.13 {mclocale set, reject evil input} -setup {
190	variable locale [mclocale]
191    } -cleanup {
192	mclocale $locale
193    } -body {
194	mclocale looks/ok/../../../../but/is/path/to/evil/code
195    } -returnCodes error -match glob -result {invalid newLocale value *}
196
197    # Tests msgcat-2.*: [mcset], [mcmset], namespace partitioning
198
199    test msgcat-2.1 {mcset, global scope} {
200	namespace eval :: ::msgcat::mcset  foo_BAR text1 text2
201    } {text2}
202
203    test msgcat-2.2 {mcset, global scope, default} {
204	namespace eval :: ::msgcat::mcset foo_BAR text3
205    } {text3}
206
207    test msgcat-2.2.1 {mcset, namespace overlap} {
208	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
209    } {con1baz}
210
211    test msgcat-2.3 {mcset, namespace overlap} -setup {
212	namespace eval bar {::msgcat::mcset  foo_BAR con1 con1bar}
213	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
214	variable locale [mclocale]
215	mclocale foo_BAR
216    } -cleanup {
217	mclocale $locale
218    } -body {
219	namespace eval bar {::msgcat::mc con1}
220    } -result con1bar
221
222    test msgcat-2.4 {mcset, namespace overlap} -setup {
223	namespace eval bar {::msgcat::mcset  foo_BAR con1 con1bar}
224	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
225	variable locale [mclocale]
226	mclocale foo_BAR
227    } -cleanup {
228	mclocale $locale
229    } -body {
230	namespace eval baz {::msgcat::mc con1}
231    } -result con1baz
232
233    test msgcat-2.5 {mcmset, global scope} -setup {
234	namespace eval :: {
235	    ::msgcat::mcmset  foo_BAR {
236	        src1 trans1
237	        src2 trans2
238	    }
239	}
240	variable locale [mclocale]
241	mclocale foo_BAR
242    } -cleanup {
243	mclocale $locale
244    } -body {
245	namespace eval :: {
246	    ::msgcat::mc src1
247	}
248    } -result trans1
249
250    test msgcat-2.6 {mcmset, namespace overlap} -setup {
251	namespace eval bar {::msgcat::mcmset  foo_BAR {con2 con2bar}}
252	namespace eval baz {::msgcat::mcmset  foo_BAR {con2 con2baz}}
253	variable locale [mclocale]
254	mclocale foo_BAR
255    } -cleanup {
256	mclocale $locale
257    } -body {
258	namespace eval bar {::msgcat::mc con2}
259    } -result con2bar
260
261    test msgcat-2.7 {mcmset, namespace overlap} -setup {
262	namespace eval bar {::msgcat::mcmset  foo_BAR {con2 con2bar}}
263	namespace eval baz {::msgcat::mcmset  foo_BAR {con2 con2baz}}
264	variable locale [mclocale]
265	mclocale foo_BAR
266    } -cleanup {
267	mclocale $locale
268    } -body {
269	namespace eval baz {::msgcat::mc con2}
270    } -result con2baz
271
272    # Tests msgcat-3.*: [mcset], [mc], catalog "inheritance"
273    #
274    # Test mcset and mc, ensuring that more specific locales
275    # (e.g. en_UK) will search less specific locales
276    # (e.g. en) for translation strings.
277    #
278    # Do this for the 15 permutations of
279    #     locales: {foo foo_BAR foo_BAR_baz}
280    #     strings: {ov0 ov1 ov2 ov3 ov4}
281    #	  locale ROOT        defines ov0, ov1, ov2, ov3
282    #     locale foo         defines      ov1, ov2, ov3
283    #     locale foo_BAR     defines           ov2, ov3
284    #     locale foo_BAR_BAZ defines                ov3
285    #     (ov4 is defined in none)
286    # So,
287    #     ov3 should be resolved in foo, foo_BAR, foo_BAR_baz
288    #     ov2 should be resolved in foo, foo_BAR
289    #     ov2 should resolve to foo_BAR in foo_BAR_baz
290    #     ov1 should be resolved in foo
291    #     ov1 should resolve to foo in foo_BAR, foo_BAR_baz
292    #     ov4 should be resolved in none, and call mcunknown
293    #
294    variable count 2
295    variable result
296    array set result {
297	foo,ov0 ov0_ROOT foo,ov1 ov1_foo foo,ov2 ov2_foo
298        foo,ov3 ov3_foo foo,ov4 ov4
299	foo_BAR,ov0 ov0_ROOT foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR
300        foo_BAR,ov3 ov3_foo_BAR	foo_BAR,ov4 ov4
301        foo_BAR_baz,ov0 ov0_ROOT foo_BAR_baz,ov1 ov1_foo
302        foo_BAR_baz,ov2 ov2_foo_BAR
303	foo_BAR_baz,ov3 ov3_foo_BAR_baz foo_BAR_baz,ov4 ov4
304    }
305    variable loc
306    variable string
307    foreach loc {foo foo_BAR foo_BAR_baz} {
308	foreach string {ov0 ov1 ov2 ov3 ov4} {
309	    test msgcat-3.$count {mcset, overlap} -setup {
310		mcset {} ov0 ov0_ROOT
311		mcset {} ov1 ov1_ROOT
312		mcset {} ov2 ov2_ROOT
313		mcset {} ov3 ov3_ROOT
314		mcset foo ov1 ov1_foo
315		mcset foo ov2 ov2_foo
316		mcset foo ov3 ov3_foo
317		mcset foo_BAR ov2 ov2_foo_BAR
318		mcset foo_BAR ov3 ov3_foo_BAR
319		mcset foo_BAR_baz ov3 ov3_foo_BAR_baz
320		variable locale [mclocale]
321		mclocale $loc
322	    } -cleanup {
323		mclocale $locale
324	    } -body {
325		mc $string
326	    } -result $result($loc,$string)
327	    incr count
328	}
329    }
330    unset -nocomplain result
331
332    # Tests msgcat-4.*: [mcunknown]
333
334    test msgcat-4.2 {mcunknown, default} -setup {
335	mcset foo unk1 "unknown 1"
336	variable locale [mclocale]
337	mclocale foo
338    } -cleanup {
339	mclocale $locale
340    } -body {
341	mc unk1
342    } -result {unknown 1}
343
344    test msgcat-4.3 {mcunknown, default} -setup {
345	mcset foo unk1 "unknown 1"
346	variable locale [mclocale]
347	mclocale foo
348    } -cleanup {
349	mclocale $locale
350    } -body {
351	mc unk2
352    } -result unk2
353
354    test msgcat-4.4 {mcunknown, overridden} -setup {
355	rename ::msgcat::mcunknown SavedMcunknown
356	proc ::msgcat::mcunknown {dom s} {
357            return unknown:$dom:$s
358	}
359	mcset foo unk1 "unknown 1"
360	variable locale [mclocale]
361	mclocale foo
362    } -cleanup {
363	mclocale $locale
364	rename ::msgcat::mcunknown {}
365	rename SavedMcunknown ::msgcat::mcunknown
366    } -body {
367	mc unk1
368    } -result {unknown 1}
369
370    test msgcat-4.5 {mcunknown, overridden} -setup {
371	rename ::msgcat::mcunknown SavedMcunknown
372	proc ::msgcat::mcunknown {dom s} {
373            return unknown:$dom:$s
374	}
375	mcset foo unk1 "unknown 1"
376	variable locale [mclocale]
377	mclocale foo
378    } -cleanup {
379	mclocale $locale
380	rename ::msgcat::mcunknown {}
381	rename SavedMcunknown ::msgcat::mcunknown
382    } -body {
383	mc unk2
384    } -result {unknown:foo:unk2}
385
386    test msgcat-4.6 {mcunknown, uplevel context} -setup {
387	rename ::msgcat::mcunknown SavedMcunknown
388	proc ::msgcat::mcunknown {dom s} {
389            return "unknown:$dom:$s:[expr {[info level] - 1}]"
390	}
391	mcset foo unk1 "unknown 1"
392	variable locale [mclocale]
393	mclocale foo
394    } -cleanup {
395	mclocale $locale
396	rename ::msgcat::mcunknown {}
397	rename SavedMcunknown ::msgcat::mcunknown
398    } -body {
399	mc unk2
400    } -result unknown:foo:unk2:[info level]
401
402    # Tests msgcat-5.*: [mcload]
403
404    variable locales {{} foo foo_BAR foo_BAR_baz}
405    set msgdir [makeDirectory msgdir]
406    foreach loc $locales {
407	if { $loc eq {} } {
408	    set msg ROOT
409        } else {
410	    set msg [string tolower $loc]
411	}
412	makeFile [list ::msgcat::mcset $loc abc abc-$loc] $msg.msg $msgdir
413    }
414    variable count 1
415    foreach loc {foo foo_BAR foo_BAR_baz} {
416	test msgcat-5.$count {mcload} -setup {
417	    variable locale [mclocale]
418	    ::msgcat::mclocale ""
419	    ::msgcat::mcloadedlocales clear
420	    ::msgcat::mcpackageconfig unset mcfolder
421	    mclocale $loc
422	} -cleanup {
423	    mclocale $locale
424	    ::msgcat::mcloadedlocales clear
425	    ::msgcat::mcpackageconfig unset mcfolder
426	} -body {
427	    mcload $msgdir
428	} -result [expr { $count+1 }]
429	incr count
430    }
431
432    # Even though foo_BAR_notexist does not exist,
433    # foo_BAR, foo and the root should be loaded.
434	test msgcat-5.4 {mcload} -setup {
435	    variable locale [mclocale]
436	    mclocale foo_BAR_notexist
437	} -cleanup {
438	    mclocale $locale
439	    mcloadedlocales clear
440	    mcpackageconfig unset mcfolder
441	} -body {
442	    mcload $msgdir
443	} -result 3
444
445	test msgcat-5.5 {mcload} -setup {
446	    variable locale [mclocale]
447	    mclocale no_FI_notexist
448	} -cleanup {
449	    mclocale $locale
450	    mcloadedlocales clear
451	    mcpackageconfig unset mcfolder
452	} -body {
453	    mcload $msgdir
454	} -result 1
455
456	test msgcat-5.6 {mcload} -setup {
457	    variable locale [mclocale]
458	    mclocale foo
459	    mcload $msgdir
460	} -cleanup {
461	    mclocale $locale
462	} -body {
463	    mc abc
464	} -result abc-foo
465
466	test msgcat-5.7 {mcload} -setup {
467	    variable locale [mclocale]
468	    mclocale foo_BAR
469	    mcload $msgdir
470	} -cleanup {
471	    mclocale $locale
472	} -body {
473	    mc abc
474	} -result abc-foo_BAR
475
476	test msgcat-5.8 {mcload} -setup {
477	    variable locale [mclocale]
478	    mclocale foo_BAR_baz
479	    mcload $msgdir
480	} -cleanup {
481	    mclocale $locale
482	} -body {
483	    mc abc
484	} -result abc-foo_BAR_baz
485
486	test msgcat-5.9 {mcload} -setup {
487	    variable locale [mclocale]
488	    mclocale no_FI_notexist
489	    mcload $msgdir
490	} -cleanup {
491	    mclocale $locale
492	} -body {
493	    mc abc
494	} -result abc-
495
496	test msgcat-5.10 {mcload} -setup {
497	    rename ::msgcat::mcunknown SavedMcunknown
498	    proc ::msgcat::mcunknown {dom s} {
499		return unknown:$dom:$s
500	    }
501	    variable locale [mclocale]
502	    mclocale no_FI_notexist
503	    mcload $msgdir
504	} -cleanup {
505	    mclocale $locale
506	    rename ::msgcat::mcunknown {}
507	    rename SavedMcunknown ::msgcat::mcunknown
508	} -body {
509	    mc def
510	} -result unknown:no_fi_notexist:def
511
512	test msgcat-5.11 {mcpackageconfig mcfolder} -setup {
513	    variable locale [mclocale]
514	    mclocale ""
515	    mcloadedlocales clear
516	    mcpackageconfig unset mcfolder
517	} -cleanup {
518	    mclocale $locale
519	    mcloadedlocales clear
520	    mcpackageconfig unset mcfolder
521	} -body {
522	    mclocale foo
523	    mcpackageconfig set mcfolder $msgdir
524	} -result 2
525
526    foreach loc $locales {
527	if { $loc eq {} } {
528	    set msg ROOT
529        } else {
530	    set msg [string tolower $loc]
531	}
532	removeFile $msg.msg $msgdir
533    }
534    removeDirectory msgdir
535
536    # Tests msgcat-6.*: [mcset], [mc] namespace inheritance
537#
538# Test mcset and mc, ensuring that resolution for messages
539# proceeds from the current ns to its parent and so on to the
540# global ns.
541#
542# Do this for the 12 permutations of
543#     locales: foo
544#     namespaces: foo foo::bar foo::bar::baz
545#     strings: {ov1 ov2 ov3 ov4}
546#     namespace ::foo            defines ov1, ov2, ov3
547#     namespace ::foo::bar       defines      ov2, ov3
548#     namespace ::foo::bar::baz  defines           ov3
549#
550#     ov4 is not defined in any namespace.
551#
552# So,
553#     ov3 should be resolved in ::foo::bar::baz, ::foo::bar, ::foo;
554#     ov2 should be resolved in ::foo, ::foo::bar
555#     ov1 should be resolved in ::foo
556#     ov4 should be resolved in none, and call mcunknown
557#
558
559    variable result
560    array set result {
561	foo,ov1 ov1_foo foo,ov2 ov2_foo foo,ov3 ov3_foo foo,ov4 ov4
562	foo::bar,ov1 ov1_foo foo::bar,ov2 ov2_foo_bar
563	foo::bar,ov3 ov3_foo_bar foo::bar,ov4 ov4 foo::bar::baz,ov1 ov1_foo
564	foo::bar::baz,ov2 ov2_foo_bar foo::bar::baz,ov3 ov3_foo_bar_baz
565	foo::bar::baz,ov4 ov4
566    }
567    variable count 1
568    variable ns
569    foreach ns {foo foo::bar foo::bar::baz} {
570	foreach string {ov1 ov2 ov3 ov4} {
571	    test msgcat-6.$count {mcset, overlap} -setup {
572		namespace eval foo {
573		    ::msgcat::mcset foo ov1 ov1_foo
574		    ::msgcat::mcset foo ov2 ov2_foo
575		    ::msgcat::mcset foo ov3 ov3_foo
576		    namespace eval bar {
577			::msgcat::mcset foo ov2 ov2_foo_bar
578			::msgcat::mcset foo ov3 ov3_foo_bar
579			namespace eval baz {
580			    ::msgcat::mcset foo ov3 "ov3_foo_bar_baz"
581			}
582		    }
583
584		}
585		variable locale [mclocale]
586		mclocale foo
587	    } -cleanup {
588		mclocale $locale
589		namespace delete foo
590	    } -body {
591		namespace eval $ns [list ::msgcat::mc $string]
592	    } -result $result($ns,$string)
593	    incr count
594	}
595    }
596
597    # Tests msgcat-7.*: [mc] extra args processed by [format]
598
599    test msgcat-7.1 {mc extra args go through to format} -setup {
600	mcset foo format1 "this is a test"
601	mcset foo format2 "this is a %s"
602	mcset foo format3 "this is a %s %s"
603	variable locale [mclocale]
604	mclocale foo
605    } -cleanup {
606	mclocale $locale
607    } -body {
608	mc format1 "good test"
609    } -result "this is a test"
610
611    test msgcat-7.2 {mc extra args go through to format} -setup {
612	mcset foo format1 "this is a test"
613	mcset foo format2 "this is a %s"
614	mcset foo format3 "this is a %s %s"
615	variable locale [mclocale]
616	mclocale foo
617    } -cleanup {
618	mclocale $locale
619    } -body {
620	mc format2 "good test"
621    } -result "this is a good test"
622
623    test msgcat-7.3 {mc errors from format are propagated} -setup {
624	mcset foo format1 "this is a test"
625	mcset foo format2 "this is a %s"
626	mcset foo format3 "this is a %s %s"
627	variable locale [mclocale]
628	mclocale foo
629    } -cleanup {
630	mclocale $locale
631    } -body {
632	catch {mc format3 "good test"}
633    } -result 1
634
635    test msgcat-7.4 {mc, extra args are given to unknown} -setup {
636	mcset foo format1 "this is a test"
637	mcset foo format2 "this is a %s"
638	mcset foo format3 "this is a %s %s"
639	variable locale [mclocale]
640	mclocale foo
641    } -cleanup {
642	mclocale $locale
643    } -body {
644	mc "this is a %s" "good test"
645    } -result "this is a good test"
646
647    # Tests msgcat-8.*: [mcflset]
648
649    set msgdir1 [makeDirectory msgdir1]
650    makeFile {::msgcat::mcflset k1 v1} l1.msg $msgdir1
651
652	test msgcat-8.1 {mcflset} -setup {
653	    variable locale [mclocale]
654	    mclocale l1
655	    mcload $msgdir1
656	} -cleanup {
657	    mclocale $locale
658	} -body {
659	    mc k1
660	} -result v1
661
662    removeFile l1.msg $msgdir1
663    removeDirectory msgdir1
664
665    set msgdir2 [makeDirectory msgdir2]
666    set msgdir3 [makeDirectory msgdir3]
667    makeFile "::msgcat::mcflset k2 v2 ; ::msgcat::mcload [list $msgdir3]"\
668	    l2.msg $msgdir2
669    makeFile {::msgcat::mcflset k3 v3} l2.msg $msgdir3
670
671	# chained mcload
672	test msgcat-8.2 {mcflset} -setup {
673	    variable locale [mclocale]
674	    mclocale l2
675	    mcload $msgdir2
676	} -cleanup {
677	    mclocale $locale
678	} -body {
679	    return [mc k2][mc k3]
680	} -result v2v3
681
682    removeFile l2.msg $msgdir2
683    removeDirectory msgdir2
684    removeDirectory msgdir3
685
686    # Tests msgcat-9.*: [mcexists]
687
688	test msgcat-9.1 {mcexists no parameter} -body {
689	    mcexists
690	} -returnCodes 1\
691	-result {wrong # args: should be "mcexists ?-exactnamespace? ?-exactlocale? src"}
692
693	test msgcat-9.2 {mcexists unknown option} -body {
694	    mcexists -unknown src
695	} -returnCodes 1\
696	-result {unknown option "-unknown"}
697
698	test msgcat-9.3 {mcexists} -setup {
699	    mcforgetpackage
700	    variable locale [mclocale]
701	    mclocale foo
702	    mcset foo k1 v1
703	} -cleanup {
704	    mclocale $locale
705	} -body {
706	    list [mcexists k1] [mcexists k2]
707	} -result {1 0}
708
709	test msgcat-9.4 {mcexists descendent preference} -setup {
710	    mcforgetpackage
711	    variable locale [mclocale]
712	    mclocale foo_bar
713	    mcset foo k1 v1
714	} -cleanup {
715	    mclocale $locale
716	} -body {
717	    list [mcexists k1] [mcexists -exactlocale k1]
718	} -result {1 0}
719
720	test msgcat-9.5 {mcexists parent namespace} -setup {
721	    mcforgetpackage
722	    variable locale [mclocale]
723	    mclocale foo_bar
724	    mcset foo k1 v1
725	} -cleanup {
726	    mclocale $locale
727	} -body {
728	    namespace eval ::msgcat::test::sub {
729		list [::msgcat::mcexists k1]\
730			[::msgcat::mcexists -exactnamespace k1]
731	    }
732	} -result {1 0}
733
734    # Tests msgcat-10.*: [mcloadedlocales]
735
736	test msgcat-10.1 {mcloadedlocales no arg} -body {
737	    mcloadedlocales
738	} -returnCodes 1\
739	-result {wrong # args: should be "mcloadedlocales subcommand"}
740
741	test msgcat-10.2 {mcloadedlocales wrong subcommand} -body {
742	    mcloadedlocales junk
743	} -returnCodes 1\
744	-result {unknown subcommand "junk": must be clear, or loaded}
745
746	test msgcat-10.3 {mcloadedlocales loaded} -setup {
747	    mcforgetpackage
748	    variable locale [mclocale]
749	    mclocale {}
750	    mcloadedlocales clear
751	} -cleanup {
752	    mclocale $locale
753	} -body {
754	    mclocale foo_bar
755	    # The result is position independent so sort
756	    set resultlist [lsort [mcloadedlocales loaded]]
757	} -result {{} foo foo_bar}
758
759	test msgcat-10.4 {mcloadedlocales clear} -setup {
760	    mcforgetpackage
761	    variable locale [mclocale]
762	    mclocale {}
763	    mcloadedlocales clear
764	} -cleanup {
765	    mclocale $locale
766	} -body {
767	    mclocale foo
768	    mcset foo k1 v1
769	    set res [mcexists k1]
770	    mclocale ""
771	    mcloadedlocales clear
772	    mclocale foo
773	    lappend res [mcexists k1]
774	} -result {1 0}
775
776    # Tests msgcat-11.*: [mcforgetpackage]
777
778	test msgcat-11.1 {mcforgetpackage translation} -setup {
779	    variable locale [mclocale]
780	} -cleanup {
781	    mclocale $locale
782	} -body {
783	    mclocale foo
784	    mcset foo k1 v1
785	    set res [mcexists k1]
786	    mcforgetpackage
787	    lappend res [mcexists k1]
788	} -result {1 0}
789
790	test msgcat-11.2 {mcforgetpackage locale} -setup {
791	    variable locale [mclocale]
792	} -cleanup {
793	    mclocale $locale
794	} -body {
795	    mclocale foo
796	    mcpackagelocale set bar
797	    set res [mcpackagelocale get]
798	    mcforgetpackage
799	    lappend res [mcpackagelocale get]
800	} -result {bar foo}
801
802	test msgcat-11.3 {mcforgetpackage options} -body {
803	    mcpackageconfig set loadcmd ""
804	    set res [mcpackageconfig isset loadcmd]
805	    mcforgetpackage
806	    lappend res [mcpackageconfig isset loadcmd]
807	} -result {1 0}
808
809    # Tests msgcat-12.*: [mcpackagelocale]
810
811	test msgcat-12.1 {mcpackagelocale no subcommand} -body {
812	    mcpackagelocale
813	} -returnCodes 1\
814	-result {wrong # args: should be "mcpackagelocale subcommand ?locale?"}
815
816	test msgcat-12.2 {mclpackagelocale wrong subcommand} -body {
817	    mcpackagelocale junk
818	} -returnCodes 1\
819	-result {unknown subcommand "junk": must be clear, get, isset, loaded, present, set, or unset}
820
821	test msgcat-12.3 {mcpackagelocale set} -setup {
822	    variable locale [mclocale]
823	} -cleanup {
824	    mclocale $locale
825	    mcforgetpackage
826	} -body {
827	    mclocale foo
828	    mcpackagelocale set bar
829	    list [mcpackagelocale get] [mclocale]
830	} -result {bar foo}
831
832	test msgcat-12.4 {mcpackagelocale get} -setup {
833	    variable locale [mclocale]
834	} -cleanup {
835	    mclocale $locale
836	    mcforgetpackage
837	} -body {
838	    mclocale foo
839	    set res [mcpackagelocale get]
840	    mcpackagelocale set bar
841	    lappend res [mcpackagelocale get]
842	} -result {foo bar}
843
844	test msgcat-12.5 {mcpackagelocale preferences} -setup {
845	    variable locale [mclocale]
846	} -cleanup {
847	    mclocale $locale
848	    mcforgetpackage
849	} -body {
850	    mclocale foo
851	    set res [list [mcpackagelocale preferences]]
852	    mcpackagelocale set bar
853	    lappend res [mcpackagelocale preferences]
854	} -result {{foo {}} {bar {}}}
855
856	test msgcat-12.6 {mcpackagelocale loaded} -setup {
857	    variable locale [mclocale]
858	} -cleanup {
859	    mclocale $locale
860	    mcforgetpackage
861	} -body {
862	    mclocale ""
863	    mcloadedlocales clear
864	    mclocale foo
865	    # The result is position independent so sort
866	    set res [list [lsort [mcpackagelocale loaded]]]
867	    mcpackagelocale set bar
868	    lappend res [lsort [mcpackagelocale loaded]]
869	} -result {{{} foo} {{} bar foo}}
870
871	test msgcat-12.7 {mcpackagelocale isset} -setup {
872	    variable locale [mclocale]
873	} -cleanup {
874	    mclocale $locale
875	    mcforgetpackage
876	} -body {
877	    mclocale foo
878	    set res [mcpackagelocale isset]
879	    mcpackagelocale set bar
880	    lappend res [mcpackagelocale isset]
881	} -result {0 1}
882
883	test msgcat-12.8 {mcpackagelocale unset} -setup {
884	    variable locale [mclocale]
885	} -cleanup {
886	    mclocale $locale
887	    mcforgetpackage
888	} -body {
889	    mcpackagelocale set bar
890	    set res [mcpackagelocale isset]
891	    mcpackagelocale unset
892	    lappend res [mcpackagelocale isset]
893	} -result {1 0}
894
895	test msgcat-12.9 {mcpackagelocale present} -setup {
896	    variable locale [mclocale]
897	} -cleanup {
898	    mclocale $locale
899	    mcforgetpackage
900	} -body {
901	    mclocale ""
902	    mcloadedlocales clear
903	    mclocale foo
904	    set res [mcpackagelocale present foo]
905	    lappend res [mcpackagelocale present bar]
906	    mcpackagelocale set bar
907	    lappend res [mcpackagelocale present foo]\
908		    [mcpackagelocale present bar]
909	} -result {1 0 1 1}
910
911	test msgcat-12.10 {mcpackagelocale clear} -setup {
912	    variable locale [mclocale]
913	} -cleanup {
914	    mclocale $locale
915	    mcforgetpackage
916	} -body {
917	    mclocale ""
918	    mcloadedlocales clear
919	    mclocale foo
920	    mcpackagelocale set bar
921	    mcpackagelocale clear
922	    list [mcpackagelocale present foo] [mcpackagelocale present bar]
923	} -result {0 1}
924
925    # Tests msgcat-13.*: [mcpackageconfig subcmds]
926
927	test msgcat-13.1 {mcpackageconfig no subcommand} -body {
928	    mcpackageconfig
929	} -returnCodes 1\
930	-result {wrong # args: should be "mcpackageconfig subcommand option ?value?"}
931
932	test msgcat-13.2 {mclpackageconfig wrong subcommand} -body {
933	    mcpackageconfig junk mcfolder
934	} -returnCodes 1\
935	-result {unknown subcommand "junk": must be get, isset, set, or unset}
936
937	test msgcat-13.3 {mclpackageconfig wrong option} -body {
938	    mcpackageconfig get junk
939	} -returnCodes 1\
940	-result {bad option "junk": must be mcfolder, loadcmd, changecmd, or unknowncmd}
941
942	test msgcat-13.4 {mcpackageconfig get} -setup {
943	    mcforgetpackage
944	} -cleanup {
945	    mcforgetpackage
946	} -body {
947	    mcpackageconfig set loadcmd ""
948	    mcpackageconfig get loadcmd
949	} -result {}
950
951	test msgcat-13.5 {mcpackageconfig (is/un)set} -setup {
952	    mcforgetpackage
953	} -cleanup {
954	    mcforgetpackage
955	} -body {
956	    set res [mcpackageconfig isset loadcmd]
957	    lappend res [mcpackageconfig set loadcmd ""]
958	    lappend res [mcpackageconfig isset loadcmd]
959	    mcpackageconfig unset loadcmd
960	    lappend res [mcpackageconfig isset loadcmd]
961	} -result {0 0 1 0}
962
963    # option mcfolder is already tested with 5.11
964
965    # Tests msgcat-14.*: callbacks: loadcmd, changecmd, unknowncmd
966
967    # This routine is used as bgerror and by direct callback invocation
968    proc callbackproc args {
969	variable resultvariable
970	set resultvariable $args
971    }
972    proc callbackfailproc args {
973	return -code error fail
974    }
975    set bgerrorsaved [interp bgerror {}]
976    interp bgerror {} [namespace code callbackproc]
977
978    variable locale
979    if {![info exist locale]} { set locale [mclocale] }
980
981	test msgcat-14.1 {invokation loadcmd} -setup {
982	    mcforgetpackage
983    	    mclocale $locale
984	    mclocale ""
985	    mcloadedlocales clear
986	    set resultvariable ""
987	} -cleanup {
988	    mcforgetpackage
989	} -body {
990	    mcpackageconfig set loadcmd [namespace code callbackproc]
991	    mclocale foo_bar
992	    lsort $resultvariable
993	} -result {foo foo_bar}
994
995	test msgcat-14.2 {invokation failed in loadcmd} -setup {
996	    mcforgetpackage
997    	    mclocale $locale
998	    mclocale ""
999	    mcloadedlocales clear
1000	} -cleanup {
1001	    mcforgetpackage
1002	    after cancel set [namespace current]::resultvariable timeout
1003	} -body {
1004	    mcpackageconfig set loadcmd [namespace code callbackfailproc]
1005	    mclocale foo_bar
1006	    # let the bgerror run
1007	    after 100 set [namespace current]::resultvariable timeout
1008	    vwait [namespace current]::resultvariable
1009	    lassign $resultvariable err errdict
1010	    list $err [dict get $errdict -code]
1011	} -result {fail 1}
1012
1013	test msgcat-14.3 {invokation changecmd} -setup {
1014	    mcforgetpackage
1015    	    mclocale $locale
1016	    mclocale ""
1017	    set resultvariable ""
1018	} -cleanup {
1019	    mcforgetpackage
1020	} -body {
1021	    mcpackageconfig set changecmd [namespace code callbackproc]
1022	    mclocale foo_bar
1023	    set resultvariable
1024	} -result {foo_bar foo {}}
1025
1026	test msgcat-14.4 {invokation unknowncmd} -setup {
1027	    mcforgetpackage
1028    	    mclocale $locale
1029	    mclocale ""
1030	    mcloadedlocales clear
1031	    set resultvariable ""
1032	} -cleanup {
1033	    mcforgetpackage
1034	} -body {
1035	    mcpackageconfig set unknowncmd [namespace code callbackproc]
1036	    mclocale foo_bar
1037	    mc k1 p1
1038	    set resultvariable
1039	} -result {foo_bar k1 p1}
1040
1041	test msgcat-14.5 {disable global unknowncmd} -setup {
1042	    mcforgetpackage
1043    	    mclocale $locale
1044	    mclocale ""
1045	    mcloadedlocales clear
1046	    set resultvariable ""
1047	    rename ::msgcat::mcunknown SavedMcunknown
1048	    proc ::msgcat::mcunknown {dom s} {
1049		return unknown:$dom:$s
1050	    }
1051	} -cleanup {
1052	    mcforgetpackage
1053	    rename ::msgcat::mcunknown {}
1054	    rename SavedMcunknown ::msgcat::mcunknown
1055	} -body {
1056	    mcpackageconfig set unknowncmd ""
1057	    mclocale foo_bar
1058	    mc k1%s p1
1059	} -result {k1p1}
1060
1061	test msgcat-14.6 {unknowncmd failing} -setup {
1062	    mcforgetpackage
1063    	    mclocale $locale
1064	    mclocale ""
1065	    mcloadedlocales clear
1066	    set resultvariable ""
1067	} -cleanup {
1068	    mcforgetpackage
1069	} -body {
1070	    mcpackageconfig set unknowncmd [namespace code callbackfailproc]
1071	    mclocale foo_bar
1072	    mc k1
1073	} -returnCodes 1\
1074	-result {fail}
1075
1076    interp bgerror {} $bgerrorsaved
1077
1078    cleanupTests
1079}
1080namespace delete ::msgcat::test
1081return
1082
1083# Local Variables:
1084# mode: tcl
1085# End:
1086