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 © 1998 Mark Harrison.
6# Copyright © 1998-1999 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}
19if {[catch {package require msgcat 1.6}]} {
20    puts stderr "Skipping tests in [info script].  No msgcat 1.6 found to test."
21    return
22}
23
24namespace eval ::msgcat::test {
25    namespace import ::msgcat::*
26    namespace import ::tcltest::test
27    namespace import ::tcltest::cleanupTests
28    namespace import ::tcltest::temporaryDirectory
29    namespace import ::tcltest::make*
30    namespace import ::tcltest::remove*
31
32    # Tests msgcat-0.*: locale initialization
33
34    # Calculate set of all permutations of a list
35    # PowerSet {1 2 3} -> {1 2 3} {2 3} {1 3} 3 {1 2} 2 1 {}
36    proc PowerSet {l} {
37	if {[llength $l] == 0} {return [list [list]]}
38	set element [lindex $l 0]
39	set rest [lrange $l 1 end]
40	set result [list]
41	foreach x [PowerSet $rest] {
42	    lappend result [linsert $x 0 $element]
43	    lappend result $x
44	}
45	return $result
46    }
47
48    variable envVars {LC_ALL LC_MESSAGES LANG}
49    variable count 0
50    variable body
51    variable result
52    variable setVars
53    foreach setVars [PowerSet $envVars] {
54	set result [string tolower [lindex $setVars 0]]
55	if {[string length $result] == 0} {
56	    if {[info exists ::tcl::mac::locale]} {
57if {[package vsatisfies [package provide msgcat] 1.7]} {
58		set result [string tolower \
59			[msgcat::mcutil::ConvertLocale $::tcl::mac::locale]]
60} else {
61		set result [string tolower \
62			[msgcat::ConvertLocale $::tcl::mac::locale]]
63}
64	    } else {
65		if {([info sharedlibextension] eq ".dll")
66			&& ![catch {package require registry}]} {
67		    # Windows and Cygwin have other ways to determine the
68		    # locale when the environment variables are missing
69		    # and the registry package is present
70		    continue
71		}
72		set result c
73	    }
74	}
75
76	test msgcat-0.$count [list \
77	    locale initialization from environment variables $setVars \
78	] -setup {
79	    variable var
80	    foreach var $envVars {
81		catch {variable $var $::env($var)}
82		unset -nocomplain ::env($var)
83	    }
84	    foreach var $setVars {
85		set ::env($var) $var
86	    }
87	    interp create [namespace current]::i
88	    i eval [list package ifneeded msgcat [package provide msgcat] \
89		    [package ifneeded msgcat [package provide msgcat]]]
90	    i eval package require msgcat
91	} -cleanup {
92	    interp delete [namespace current]::i
93	    foreach var $envVars {
94		unset -nocomplain ::env($var)
95		catch {set ::env($var) [set [namespace current]::$var]}
96	    }
97	} -body {i eval msgcat::mclocale} -result $result
98	incr count
99    }
100    unset -nocomplain result
101
102    # Could add tests of initialization from Windows registry here.
103    # Use a fake registry package.
104
105    # Tests msgcat-1.*: [mclocale], [mcpreferences]
106
107    test msgcat-1.3 {mclocale set, single element} -setup {
108	variable locale [mclocale]
109    } -cleanup {
110	mclocale $locale
111    } -body {
112	mclocale en
113    } -result en
114
115    test msgcat-1.4 {mclocale get, single element} -setup {
116	variable locale [mclocale]
117	mclocale en
118    } -cleanup {
119	mclocale $locale
120    } -body {
121	mclocale
122    } -result en
123
124    test msgcat-1.5 {mcpreferences, single element} -setup {
125	variable locale [mclocale]
126	mclocale en
127    } -cleanup {
128	mclocale $locale
129    } -body {
130	mcpreferences
131    } -result {en {}}
132
133    test msgcat-1.6 {mclocale set, two elements} -setup {
134	variable locale [mclocale]
135    } -cleanup {
136	mclocale $locale
137    } -body {
138	mclocale en_US
139    } -result en_us
140
141    test msgcat-1.7 {mclocale get, two elements} -setup {
142	variable locale [mclocale]
143	mclocale en_US
144    } -cleanup {
145	mclocale $locale
146    } -body {
147	mclocale
148    } -result en_us
149
150    test msgcat-1.8 {mcpreferences, two elements} -setup {
151	variable locale [mclocale]
152	mclocale en_US
153    } -cleanup {
154	mclocale $locale
155    } -body {
156	mcpreferences
157    } -result {en_us en {}}
158
159    test msgcat-1.9 {mclocale set, three elements} -setup {
160	variable locale [mclocale]
161    } -cleanup {
162	mclocale $locale
163    } -body {
164	mclocale en_US_funky
165    } -result en_us_funky
166
167    test msgcat-1.10 {mclocale get, three elements} -setup {
168	variable locale [mclocale]
169	mclocale en_US_funky
170    } -cleanup {
171	mclocale $locale
172    } -body {
173	mclocale
174    } -result en_us_funky
175
176    test msgcat-1.11 {mcpreferences, three elements} -setup {
177	variable locale [mclocale]
178	mclocale en_US_funky
179    } -cleanup {
180	mclocale $locale
181    } -body {
182	mcpreferences
183    } -result {en_us_funky en_us en {}}
184
185    test msgcat-1.12 {mclocale set, reject evil input} -setup {
186	variable locale [mclocale]
187    } -cleanup {
188	mclocale $locale
189    } -body {
190	mclocale /path/to/evil/code
191    } -returnCodes error -match glob -result {invalid newLocale value *}
192
193    test msgcat-1.13 {mclocale set, reject evil input} -setup {
194	variable locale [mclocale]
195    } -cleanup {
196	mclocale $locale
197    } -body {
198	mclocale looks/ok/../../../../but/is/path/to/evil/code
199    } -returnCodes error -match glob -result {invalid newLocale value *}
200
201    test msgcat-1.14 {mcpreferences, custom locale preferences} -setup {
202	variable locale [mclocale]
203	mclocale en
204	mcpreferences fr en {}
205    } -cleanup {
206	mclocale $locale
207    } -body {
208	mcpreferences
209    } -result {fr en {}}
210
211    test msgcat-1.15 {mcpreferences, overwrite custom locale preferences}\
212    -setup {
213	variable locale [mclocale]
214	mcpreferences fr en {}
215	mclocale en
216    } -cleanup {
217	mclocale $locale
218    } -body {
219	mcpreferences
220    } -result {en {}}
221
222
223    # Tests msgcat-2.*: [mcset], [mcmset], namespace partitioning
224
225    test msgcat-2.1 {mcset, global scope} {
226	namespace eval :: ::msgcat::mcset  foo_BAR text1 text2
227    } {text2}
228
229    test msgcat-2.2 {mcset, global scope, default} {
230	namespace eval :: ::msgcat::mcset foo_BAR text3
231    } {text3}
232
233    test msgcat-2.2.1 {mcset, namespace overlap} {
234	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
235    } {con1baz}
236
237    test msgcat-2.3 {mcset, namespace overlap} -setup {
238	namespace eval bar {::msgcat::mcset  foo_BAR con1 con1bar}
239	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
240	variable locale [mclocale]
241	mclocale foo_BAR
242    } -cleanup {
243	mclocale $locale
244    } -body {
245	namespace eval bar {::msgcat::mc con1}
246    } -result con1bar
247
248    test msgcat-2.4 {mcset, namespace overlap} -setup {
249	namespace eval bar {::msgcat::mcset  foo_BAR con1 con1bar}
250	namespace eval baz {::msgcat::mcset  foo_BAR con1 con1baz}
251	variable locale [mclocale]
252	mclocale foo_BAR
253    } -cleanup {
254	mclocale $locale
255    } -body {
256	namespace eval baz {::msgcat::mc con1}
257    } -result con1baz
258
259    test msgcat-2.5 {mcmset, global scope} -setup {
260	namespace eval :: {
261	    ::msgcat::mcmset  foo_BAR {
262	        src1 trans1
263	        src2 trans2
264	    }
265	}
266	variable locale [mclocale]
267	mclocale foo_BAR
268    } -cleanup {
269	mclocale $locale
270    } -body {
271	namespace eval :: {
272	    ::msgcat::mc src1
273	}
274    } -result trans1
275
276    test msgcat-2.6 {mcmset, namespace overlap} -setup {
277	namespace eval bar {::msgcat::mcmset  foo_BAR {con2 con2bar}}
278	namespace eval baz {::msgcat::mcmset  foo_BAR {con2 con2baz}}
279	variable locale [mclocale]
280	mclocale foo_BAR
281    } -cleanup {
282	mclocale $locale
283    } -body {
284	namespace eval bar {::msgcat::mc con2}
285    } -result con2bar
286
287    test msgcat-2.7 {mcmset, namespace overlap} -setup {
288	namespace eval bar {::msgcat::mcmset  foo_BAR {con2 con2bar}}
289	namespace eval baz {::msgcat::mcmset  foo_BAR {con2 con2baz}}
290	variable locale [mclocale]
291	mclocale foo_BAR
292    } -cleanup {
293	mclocale $locale
294    } -body {
295	namespace eval baz {::msgcat::mc con2}
296    } -result con2baz
297
298    # Tests msgcat-3.*: [mcset], [mc], catalog "inheritance"
299    #
300    # Test mcset and mc, ensuring that more specific locales
301    # (e.g. en_UK) will search less specific locales
302    # (e.g. en) for translation strings.
303    #
304    # Do this for the 15 permutations of
305    #     locales: {foo foo_BAR foo_BAR_baz}
306    #     strings: {ov0 ov1 ov2 ov3 ov4}
307    #	  locale ROOT        defines ov0, ov1, ov2, ov3
308    #     locale foo         defines      ov1, ov2, ov3
309    #     locale foo_BAR     defines           ov2, ov3
310    #     locale foo_BAR_BAZ defines                ov3
311    #     (ov4 is defined in none)
312    # So,
313    #     ov3 should be resolved in foo, foo_BAR, foo_BAR_baz
314    #     ov2 should be resolved in foo, foo_BAR
315    #     ov2 should resolve to foo_BAR in foo_BAR_baz
316    #     ov1 should be resolved in foo
317    #     ov1 should resolve to foo in foo_BAR, foo_BAR_baz
318    #     ov4 should be resolved in none, and call mcunknown
319    #
320    variable count 2
321    variable result
322    array set result {
323	foo,ov0 ov0_ROOT foo,ov1 ov1_foo foo,ov2 ov2_foo
324        foo,ov3 ov3_foo foo,ov4 ov4
325	foo_BAR,ov0 ov0_ROOT foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR
326        foo_BAR,ov3 ov3_foo_BAR	foo_BAR,ov4 ov4
327        foo_BAR_baz,ov0 ov0_ROOT foo_BAR_baz,ov1 ov1_foo
328        foo_BAR_baz,ov2 ov2_foo_BAR
329	foo_BAR_baz,ov3 ov3_foo_BAR_baz foo_BAR_baz,ov4 ov4
330    }
331    variable loc
332    variable string
333    foreach loc {foo foo_BAR foo_BAR_baz} {
334	foreach string {ov0 ov1 ov2 ov3 ov4} {
335	    test msgcat-3.$count {mcset, overlap} -setup {
336		mcset {} ov0 ov0_ROOT
337		mcset {} ov1 ov1_ROOT
338		mcset {} ov2 ov2_ROOT
339		mcset {} ov3 ov3_ROOT
340		mcset foo ov1 ov1_foo
341		mcset foo ov2 ov2_foo
342		mcset foo ov3 ov3_foo
343		mcset foo_BAR ov2 ov2_foo_BAR
344		mcset foo_BAR ov3 ov3_foo_BAR
345		mcset foo_BAR_baz ov3 ov3_foo_BAR_baz
346		variable locale [mclocale]
347		mclocale $loc
348	    } -cleanup {
349		mclocale $locale
350	    } -body {
351		mc $string
352	    } -result $result($loc,$string)
353	    incr count
354	}
355    }
356    unset -nocomplain result
357
358    # Tests msgcat-4.*: [mcunknown]
359
360    test msgcat-4.2 {mcunknown, default} -setup {
361	mcset foo unk1 "unknown 1"
362	variable locale [mclocale]
363	mclocale foo
364    } -cleanup {
365	mclocale $locale
366    } -body {
367	mc unk1
368    } -result {unknown 1}
369
370    test msgcat-4.3 {mcunknown, default} -setup {
371	mcset foo unk1 "unknown 1"
372	variable locale [mclocale]
373	mclocale foo
374    } -cleanup {
375	mclocale $locale
376    } -body {
377	mc unk2
378    } -result unk2
379
380    test msgcat-4.4 {mcunknown, overridden} -setup {
381	rename ::msgcat::mcunknown SavedMcunknown
382	proc ::msgcat::mcunknown {dom s} {
383            return unknown:$dom:$s
384	}
385	mcset foo unk1 "unknown 1"
386	variable locale [mclocale]
387	mclocale foo
388    } -cleanup {
389	mclocale $locale
390	rename ::msgcat::mcunknown {}
391	rename SavedMcunknown ::msgcat::mcunknown
392    } -body {
393	mc unk1
394    } -result {unknown 1}
395
396    test msgcat-4.5 {mcunknown, overridden} -setup {
397	rename ::msgcat::mcunknown SavedMcunknown
398	proc ::msgcat::mcunknown {dom s} {
399            return unknown:$dom:$s
400	}
401	mcset foo unk1 "unknown 1"
402	variable locale [mclocale]
403	mclocale foo
404    } -cleanup {
405	mclocale $locale
406	rename ::msgcat::mcunknown {}
407	rename SavedMcunknown ::msgcat::mcunknown
408    } -body {
409	mc unk2
410    } -result {unknown:foo:unk2}
411
412    test msgcat-4.6 {mcunknown, uplevel context} -setup {
413	rename ::msgcat::mcunknown SavedMcunknown
414	proc ::msgcat::mcunknown {dom s} {
415            return "unknown:$dom:$s:[expr {[info level] - 1}]"
416	}
417	mcset foo unk1 "unknown 1"
418	variable locale [mclocale]
419	mclocale foo
420    } -cleanup {
421	mclocale $locale
422	rename ::msgcat::mcunknown {}
423	rename SavedMcunknown ::msgcat::mcunknown
424    } -body {
425	mc unk2
426    } -result unknown:foo:unk2:[info level]
427
428    # Tests msgcat-5.*: [mcload]
429
430    variable locales {{} foo foo_BAR foo_BAR_baz}
431    set msgdir [makeDirectory msgdir]
432    foreach loc $locales {
433	if { $loc eq {} } {
434	    set msg ROOT
435        } else {
436	    set msg [string tolower $loc]
437	}
438	makeFile [list ::msgcat::mcset $loc abc abc-$loc] $msg.msg $msgdir
439    }
440    variable count 1
441    foreach loc {foo foo_BAR foo_BAR_baz} {
442	test msgcat-5.$count {mcload} -setup {
443	    variable locale [mclocale]
444	    ::msgcat::mclocale ""
445	    ::msgcat::mcloadedlocales clear
446	    ::msgcat::mcpackageconfig unset mcfolder
447	    mclocale $loc
448	} -cleanup {
449	    mclocale $locale
450	    ::msgcat::mcloadedlocales clear
451	    ::msgcat::mcpackageconfig unset mcfolder
452	} -body {
453	    mcload $msgdir
454	} -result [expr { $count+1 }]
455	incr count
456    }
457
458    # Even though foo_BAR_notexist does not exist,
459    # foo_BAR, foo and the root should be loaded.
460	test msgcat-5.4 {mcload} -setup {
461	    variable locale [mclocale]
462	    mclocale foo_BAR_notexist
463	} -cleanup {
464	    mclocale $locale
465	    mcloadedlocales clear
466	    mcpackageconfig unset mcfolder
467	} -body {
468	    mcload $msgdir
469	} -result 3
470
471	test msgcat-5.5 {mcload} -setup {
472	    variable locale [mclocale]
473	    mclocale no_FI_notexist
474	} -cleanup {
475	    mclocale $locale
476	    mcloadedlocales clear
477	    mcpackageconfig unset mcfolder
478	} -body {
479	    mcload $msgdir
480	} -result 1
481
482	test msgcat-5.6 {mcload} -setup {
483	    variable locale [mclocale]
484	    mclocale foo
485	    mcload $msgdir
486	} -cleanup {
487	    mclocale $locale
488	} -body {
489	    mc abc
490	} -result abc-foo
491
492	test msgcat-5.7 {mcload} -setup {
493	    variable locale [mclocale]
494	    mclocale foo_BAR
495	    mcload $msgdir
496	} -cleanup {
497	    mclocale $locale
498	} -body {
499	    mc abc
500	} -result abc-foo_BAR
501
502	test msgcat-5.8 {mcload} -setup {
503	    variable locale [mclocale]
504	    mclocale foo_BAR_baz
505	    mcload $msgdir
506	} -cleanup {
507	    mclocale $locale
508	} -body {
509	    mc abc
510	} -result abc-foo_BAR_baz
511
512	test msgcat-5.9 {mcload} -setup {
513	    variable locale [mclocale]
514	    mclocale no_FI_notexist
515	    mcload $msgdir
516	} -cleanup {
517	    mclocale $locale
518	} -body {
519	    mc abc
520	} -result abc-
521
522	test msgcat-5.10 {mcload} -setup {
523	    rename ::msgcat::mcunknown SavedMcunknown
524	    proc ::msgcat::mcunknown {dom s} {
525		return unknown:$dom:$s
526	    }
527	    variable locale [mclocale]
528	    mclocale no_FI_notexist
529	    mcload $msgdir
530	} -cleanup {
531	    mclocale $locale
532	    rename ::msgcat::mcunknown {}
533	    rename SavedMcunknown ::msgcat::mcunknown
534	} -body {
535	    mc def
536	} -result unknown:no_fi_notexist:def
537
538	test msgcat-5.11 {mcpackageconfig mcfolder} -setup {
539	    variable locale [mclocale]
540	    mclocale ""
541	    mcloadedlocales clear
542	    mcpackageconfig unset mcfolder
543	} -cleanup {
544	    mclocale $locale
545	    mcloadedlocales clear
546	    mcpackageconfig unset mcfolder
547	} -body {
548	    mclocale foo
549	    mcpackageconfig set mcfolder $msgdir
550	} -result 2
551
552    foreach loc $locales {
553	if { $loc eq {} } {
554	    set msg ROOT
555        } else {
556	    set msg [string tolower $loc]
557	}
558	removeFile $msg.msg $msgdir
559    }
560    removeDirectory msgdir
561
562    # Tests msgcat-6.*: [mcset], [mc] namespace inheritance
563#
564# Test mcset and mc, ensuring that resolution for messages
565# proceeds from the current ns to its parent and so on to the
566# global ns.
567#
568# Do this for the 12 permutations of
569#     locales: foo
570#     namespaces: foo foo::bar foo::bar::baz
571#     strings: {ov1 ov2 ov3 ov4}
572#     namespace ::foo            defines ov1, ov2, ov3
573#     namespace ::foo::bar       defines      ov2, ov3
574#     namespace ::foo::bar::baz  defines           ov3
575#
576#     ov4 is not defined in any namespace.
577#
578# So,
579#     ov3 should be resolved in ::foo::bar::baz, ::foo::bar, ::foo;
580#     ov2 should be resolved in ::foo, ::foo::bar
581#     ov1 should be resolved in ::foo
582#     ov4 should be resolved in none, and call mcunknown
583#
584
585    variable result
586    array set result {
587	foo,ov1 ov1_foo foo,ov2 ov2_foo foo,ov3 ov3_foo foo,ov4 ov4
588	foo::bar,ov1 ov1_foo foo::bar,ov2 ov2_foo_bar
589	foo::bar,ov3 ov3_foo_bar foo::bar,ov4 ov4 foo::bar::baz,ov1 ov1_foo
590	foo::bar::baz,ov2 ov2_foo_bar foo::bar::baz,ov3 ov3_foo_bar_baz
591	foo::bar::baz,ov4 ov4
592    }
593    variable count 1
594    variable ns
595    foreach ns {foo foo::bar foo::bar::baz} {
596	foreach string {ov1 ov2 ov3 ov4} {
597	    test msgcat-6.$count {mcset, overlap} -setup {
598		namespace eval foo {
599		    ::msgcat::mcset foo ov1 ov1_foo
600		    ::msgcat::mcset foo ov2 ov2_foo
601		    ::msgcat::mcset foo ov3 ov3_foo
602		    namespace eval bar {
603			::msgcat::mcset foo ov2 ov2_foo_bar
604			::msgcat::mcset foo ov3 ov3_foo_bar
605			namespace eval baz {
606			    ::msgcat::mcset foo ov3 "ov3_foo_bar_baz"
607			}
608		    }
609
610		}
611		variable locale [mclocale]
612		mclocale foo
613	    } -cleanup {
614		mclocale $locale
615		namespace delete foo
616	    } -body {
617		namespace eval $ns [list ::msgcat::mc $string]
618	    } -result $result($ns,$string)
619	    incr count
620	}
621    }
622
623    # Tests msgcat-7.*: [mc] extra args processed by [format]
624
625    test msgcat-7.1 {mc extra args go through to format} -setup {
626	mcset foo format1 "this is a test"
627	mcset foo format2 "this is a %s"
628	mcset foo format3 "this is a %s %s"
629	variable locale [mclocale]
630	mclocale foo
631    } -cleanup {
632	mclocale $locale
633    } -body {
634	mc format1 "good test"
635    } -result "this is a test"
636
637    test msgcat-7.2 {mc extra args go through to format} -setup {
638	mcset foo format1 "this is a test"
639	mcset foo format2 "this is a %s"
640	mcset foo format3 "this is a %s %s"
641	variable locale [mclocale]
642	mclocale foo
643    } -cleanup {
644	mclocale $locale
645    } -body {
646	mc format2 "good test"
647    } -result "this is a good test"
648
649    test msgcat-7.3 {mc errors from format are propagated} -setup {
650	mcset foo format1 "this is a test"
651	mcset foo format2 "this is a %s"
652	mcset foo format3 "this is a %s %s"
653	variable locale [mclocale]
654	mclocale foo
655    } -cleanup {
656	mclocale $locale
657    } -body {
658	catch {mc format3 "good test"}
659    } -result 1
660
661    test msgcat-7.4 {mc, extra args are given to unknown} -setup {
662	mcset foo format1 "this is a test"
663	mcset foo format2 "this is a %s"
664	mcset foo format3 "this is a %s %s"
665	variable locale [mclocale]
666	mclocale foo
667    } -cleanup {
668	mclocale $locale
669    } -body {
670	mc "this is a %s" "good test"
671    } -result "this is a good test"
672
673    # Tests msgcat-8.*: [mcflset]
674
675    set msgdir1 [makeDirectory msgdir1]
676    makeFile {::msgcat::mcflset k1 v1} l1.msg $msgdir1
677
678	test msgcat-8.1 {mcflset} -setup {
679	    variable locale [mclocale]
680	    mclocale l1
681	    mcload $msgdir1
682	} -cleanup {
683	    mclocale $locale
684	} -body {
685	    mc k1
686	} -result v1
687
688    removeFile l1.msg $msgdir1
689    removeDirectory msgdir1
690
691    set msgdir2 [makeDirectory msgdir2]
692    set msgdir3 [makeDirectory msgdir3]
693    makeFile "::msgcat::mcflset k2 v2 ; ::msgcat::mcload [list $msgdir3]"\
694	    l2.msg $msgdir2
695    makeFile {::msgcat::mcflset k3 v3 ; ::msgcat::mcflmset {k4 v4 k5 v5}} l2.msg $msgdir3
696
697	# chained mcload
698	test msgcat-8.2 {mcflset/mcflmset} -setup {
699	    variable locale [mclocale]
700	    mclocale l2
701	    mcload $msgdir2
702	} -cleanup {
703	    mclocale $locale
704	} -body {
705	    return [mc k2][mc k3]--[mc k4][mc k5]
706	} -result v2v3--v4v5
707
708    removeFile l2.msg $msgdir2
709    removeDirectory msgdir2
710    removeDirectory msgdir3
711
712    # Tests msgcat-9.*: [mcexists]
713
714	test msgcat-9.1 {mcexists no parameter} -body {
715	    mcexists
716	} -returnCodes 1\
717	-result {wrong # args: should be "mcexists ?-exactnamespace? ?-exactlocale? ?-namespace ns? src"}
718
719	test msgcat-9.2 {mcexists unknown option} -body {
720	    mcexists -unknown src
721	} -returnCodes 1\
722	-result {unknown option "-unknown"}
723
724	test msgcat-9.3 {mcexists} -setup {
725	    mcforgetpackage
726	    variable locale [mclocale]
727	    mclocale foo
728	    mcset foo k1 v1
729	} -cleanup {
730	    mclocale $locale
731	} -body {
732	    list [mcexists k1] [mcexists k2]
733	} -result {1 0}
734
735	test msgcat-9.4 {mcexists descendent preference} -setup {
736	    mcforgetpackage
737	    variable locale [mclocale]
738	    mclocale foo_bar
739	    mcset foo k1 v1
740	} -cleanup {
741	    mclocale $locale
742	} -body {
743	    list [mcexists k1] [mcexists -exactlocale k1]
744	} -result {1 0}
745
746	test msgcat-9.5 {mcexists parent namespace} -setup {
747	    mcforgetpackage
748	    variable locale [mclocale]
749	    mclocale foo_bar
750	    mcset foo k1 v1
751	} -cleanup {
752	    mclocale $locale
753	    namespace delete ::foo
754	} -body {
755	    namespace eval ::foo {
756		list [::msgcat::mcexists k1]\
757			[::msgcat::mcexists -namespace ::msgcat::test k1]
758	    }
759	} -result {0 1}
760
761	test msgcat-9.6 {mcexists -namespace ns parameter} -setup {
762	    mcforgetpackage
763	    variable locale [mclocale]
764	    mclocale foo_bar
765	    mcset foo k1 v1
766	} -cleanup {
767	    mclocale $locale
768	    namespace delete ::foo
769	} -body {
770	    namespace eval ::foo {
771		list [::msgcat::mcexists k1]\
772			[::msgcat::mcexists -namespace ::msgcat::test k1]
773	    }
774	} -result {0 1}
775
776	test msgcat-9.7 {mcexists -namespace - ns argument missing} -body {
777	    mcexists -namespace src
778	} -returnCodes 1\
779	-result {Argument missing for switch "-namespace"}
780
781
782    # Tests msgcat-10.*: [mcloadedlocales]
783
784	test msgcat-10.1 {mcloadedlocales no arg} -body {
785	    mcloadedlocales
786	} -returnCodes 1\
787	-result {wrong # args: should be "mcloadedlocales subcommand"}
788
789	test msgcat-10.2 {mcloadedlocales wrong subcommand} -body {
790	    mcloadedlocales junk
791	} -returnCodes 1\
792	-result {unknown subcommand "junk": must be clear, or loaded}
793
794	test msgcat-10.3 {mcloadedlocales loaded} -setup {
795	    mcforgetpackage
796	    variable locale [mclocale]
797	    mclocale {}
798	    mcloadedlocales clear
799	} -cleanup {
800	    mclocale $locale
801	} -body {
802	    mclocale foo_bar
803	    # The result is position independent so sort
804	    set resultlist [lsort [mcloadedlocales loaded]]
805	} -result {{} foo foo_bar}
806
807	test msgcat-10.4 {mcloadedlocales clear} -setup {
808	    mcforgetpackage
809	    variable locale [mclocale]
810	    mclocale {}
811	    mcloadedlocales clear
812	} -cleanup {
813	    mclocale $locale
814	} -body {
815	    mclocale foo
816	    mcset foo k1 v1
817	    set res [mcexists k1]
818	    mclocale ""
819	    mcloadedlocales clear
820	    mclocale foo
821	    lappend res [mcexists k1]
822	} -result {1 0}
823
824    # Tests msgcat-11.*: [mcforgetpackage]
825
826	test msgcat-11.1 {mcforgetpackage translation} -setup {
827	    variable locale [mclocale]
828	} -cleanup {
829	    mclocale $locale
830	} -body {
831	    mclocale foo
832	    mcset foo k1 v1
833	    set res [mcexists k1]
834	    mcforgetpackage
835	    lappend res [mcexists k1]
836	} -result {1 0}
837
838	test msgcat-11.2 {mcforgetpackage locale} -setup {
839	    variable locale [mclocale]
840	} -cleanup {
841	    mclocale $locale
842	} -body {
843	    mclocale foo
844	    mcpackagelocale set bar
845	    set res [mcpackagelocale get]
846	    mcforgetpackage
847	    lappend res [mcpackagelocale get]
848	} -result {bar foo}
849
850	test msgcat-11.3 {mcforgetpackage options} -body {
851	    mcpackageconfig set loadcmd ""
852	    set res [mcpackageconfig isset loadcmd]
853	    mcforgetpackage
854	    lappend res [mcpackageconfig isset loadcmd]
855	} -result {1 0}
856
857    # Tests msgcat-12.*: [mcpackagelocale]
858
859	test msgcat-12.1 {mcpackagelocale no subcommand} -body {
860	    mcpackagelocale
861	} -returnCodes 1\
862	-result {wrong # args: should be "mcpackagelocale subcommand ?arg ...?"}
863
864	test msgcat-12.2 {mclpackagelocale wrong subcommand} -body {
865	    mcpackagelocale junk
866	} -returnCodes 1\
867	-result {unknown subcommand "junk": must be clear, get, isset, loaded, present, set, or unset}
868
869	test msgcat-12.2.1 {mclpackagelocale set multiple args} -body {
870	    mcpackagelocale set a b
871	} -returnCodes 1\
872	-result {wrong # args: should be "mcpackagelocale set ?locale?"}
873
874	test msgcat-12.3 {mcpackagelocale set} -setup {
875	    variable locale [mclocale]
876	} -cleanup {
877	    mclocale $locale
878	    mcforgetpackage
879	} -body {
880	    mclocale foo
881	    mcpackagelocale set bar
882	    list [mcpackagelocale get] [mclocale]
883	} -result {bar foo}
884
885	test msgcat-12.4 {mcpackagelocale get} -setup {
886	    variable locale [mclocale]
887	} -cleanup {
888	    mclocale $locale
889	    mcforgetpackage
890	} -body {
891	    mclocale foo
892	    set res [mcpackagelocale get]
893	    mcpackagelocale set bar
894	    lappend res [mcpackagelocale get]
895	} -result {foo bar}
896
897	test msgcat-12.5 {mcpackagelocale preferences} -setup {
898	    variable locale [mclocale]
899	} -cleanup {
900	    mclocale $locale
901	    mcforgetpackage
902	} -body {
903	    mclocale foo
904	    set res [list [mcpackagelocale preferences]]
905	    mcpackagelocale set bar
906	    lappend res [mcpackagelocale preferences]
907	} -result {{foo {}} {bar {}}}
908
909	test msgcat-12.6 {mcpackagelocale loaded} -setup {
910	    variable locale [mclocale]
911	} -cleanup {
912	    mclocale $locale
913	    mcforgetpackage
914	} -body {
915	    mclocale ""
916	    mcloadedlocales clear
917	    mclocale foo
918	    # The result is position independent so sort
919	    set res [list [lsort [mcpackagelocale loaded]]]
920	    mcpackagelocale set bar
921	    lappend res [lsort [mcpackagelocale loaded]]
922	} -result {{{} foo} {{} bar foo}}
923
924	test msgcat-12.7 {mcpackagelocale isset} -setup {
925	    variable locale [mclocale]
926	} -cleanup {
927	    mclocale $locale
928	    mcforgetpackage
929	} -body {
930	    mclocale foo
931	    set res [mcpackagelocale isset]
932	    mcpackagelocale set bar
933	    lappend res [mcpackagelocale isset]
934	} -result {0 1}
935
936	test msgcat-12.8 {mcpackagelocale unset} -setup {
937	    variable locale [mclocale]
938	} -cleanup {
939	    mclocale $locale
940	    mcforgetpackage
941	} -body {
942	    mcpackagelocale set bar
943	    set res [mcpackagelocale isset]
944	    mcpackagelocale unset
945	    lappend res [mcpackagelocale isset]
946	} -result {1 0}
947
948	test msgcat-12.9 {mcpackagelocale present} -setup {
949	    variable locale [mclocale]
950	} -cleanup {
951	    mclocale $locale
952	    mcforgetpackage
953	} -body {
954	    mclocale ""
955	    mcloadedlocales clear
956	    mclocale foo
957	    set res [mcpackagelocale present foo]
958	    lappend res [mcpackagelocale present bar]
959	    mcpackagelocale set bar
960	    lappend res [mcpackagelocale present foo]\
961		    [mcpackagelocale present bar]
962	} -result {1 0 1 1}
963
964	test msgcat-12.10 {mcpackagelocale clear} -setup {
965	    variable locale [mclocale]
966	} -cleanup {
967	    mclocale $locale
968	    mcforgetpackage
969	} -body {
970	    mclocale ""
971	    mcloadedlocales clear
972	    mclocale foo
973	    mcpackagelocale set bar
974	    mcpackagelocale clear
975	    list [mcpackagelocale present foo] [mcpackagelocale present bar]
976	} -result {0 1}
977
978	test msgcat-12.11 {mcpackagelocale custom preferences} -setup {
979	    variable locale [mclocale]
980	} -cleanup {
981	    mclocale $locale
982	    mcforgetpackage
983	} -body {
984	    mclocale foo
985	    set res [list [mcpackagelocale preferences]]
986	    mcpackagelocale preferences bar {}
987	    lappend res [mcpackagelocale preferences]
988	} -result {{foo {}} {bar {}}}
989
990	test msgcat-12.12 {mcpackagelocale preferences -> no isset} -setup {
991	    variable locale [mclocale]
992	} -cleanup {
993	    mclocale $locale
994	    mcforgetpackage
995	} -body {
996	    mclocale foo
997	    mcpackagelocale preferences
998	    mcpackagelocale isset
999	} -result {0}
1000
1001
1002    # Tests msgcat-13.*: [mcpackageconfig subcmds]
1003
1004	test msgcat-13.1 {mcpackageconfig no subcommand} -body {
1005	    mcpackageconfig
1006	} -returnCodes 1\
1007	-result {wrong # args: should be "mcpackageconfig subcommand option ?value?"}
1008
1009	test msgcat-13.2 {mclpackageconfig wrong subcommand} -body {
1010	    mcpackageconfig junk mcfolder
1011	} -returnCodes 1\
1012	-result {unknown subcommand "junk": must be get, isset, set, or unset}
1013
1014	test msgcat-13.3 {mclpackageconfig wrong option} -body {
1015	    mcpackageconfig get junk
1016	} -returnCodes 1\
1017	-result {bad option "junk": must be mcfolder, loadcmd, changecmd, or unknowncmd}
1018
1019	test msgcat-13.4 {mcpackageconfig get} -setup {
1020	    mcforgetpackage
1021	} -cleanup {
1022	    mcforgetpackage
1023	} -body {
1024	    mcpackageconfig set loadcmd ""
1025	    mcpackageconfig get loadcmd
1026	} -result {}
1027
1028	test msgcat-13.5 {mcpackageconfig (is/un)set} -setup {
1029	    mcforgetpackage
1030	} -cleanup {
1031	    mcforgetpackage
1032	} -body {
1033	    set res [mcpackageconfig isset loadcmd]
1034	    lappend res [mcpackageconfig set loadcmd ""]
1035	    lappend res [mcpackageconfig isset loadcmd]
1036	    mcpackageconfig unset loadcmd
1037	    lappend res [mcpackageconfig isset loadcmd]
1038	} -result {0 0 1 0}
1039
1040    # option mcfolder is already tested with 5.11
1041
1042    # Tests msgcat-14.*: callbacks: loadcmd, changecmd, unknowncmd
1043
1044    # This routine is used as bgerror and by direct callback invocation
1045    proc callbackproc args {
1046	variable resultvariable
1047	set resultvariable $args
1048    }
1049    proc callbackfailproc args {
1050	return -code error fail
1051    }
1052    set bgerrorsaved [interp bgerror {}]
1053    interp bgerror {} [namespace code callbackproc]
1054
1055    variable locale
1056    if {![info exist locale]} { set locale [mclocale] }
1057
1058	test msgcat-14.1 {invokation loadcmd} -setup {
1059	    mcforgetpackage
1060    	    mclocale $locale
1061	    mclocale ""
1062	    mcloadedlocales clear
1063	    set resultvariable ""
1064	} -cleanup {
1065	    mcforgetpackage
1066	} -body {
1067	    mcpackageconfig set loadcmd [namespace code callbackproc]
1068	    mclocale foo_bar
1069	    lsort $resultvariable
1070	} -result {foo foo_bar}
1071
1072	test msgcat-14.2 {invokation failed in loadcmd} -setup {
1073	    mcforgetpackage
1074    	    mclocale $locale
1075	    mclocale ""
1076	    mcloadedlocales clear
1077	} -cleanup {
1078	    mcforgetpackage
1079	    after cancel set [namespace current]::resultvariable timeout
1080	} -body {
1081	    mcpackageconfig set loadcmd [namespace code callbackfailproc]
1082	    mclocale foo_bar
1083	    # let the bgerror run
1084	    after 100 set [namespace current]::resultvariable timeout
1085	    vwait [namespace current]::resultvariable
1086	    lassign $resultvariable err errdict
1087	    list $err [dict get $errdict -code]
1088	} -result {fail 1}
1089
1090	test msgcat-14.3 {invokation changecmd} -setup {
1091	    mcforgetpackage
1092    	    mclocale $locale
1093	    mclocale ""
1094	    set resultvariable ""
1095	} -cleanup {
1096	    mcforgetpackage
1097	} -body {
1098	    mcpackageconfig set changecmd [namespace code callbackproc]
1099	    mclocale foo_bar
1100	    set resultvariable
1101	} -result {foo_bar foo {}}
1102
1103	test msgcat-14.4 {invokation unknowncmd} -setup {
1104	    mcforgetpackage
1105    	    mclocale $locale
1106	    mclocale ""
1107	    mcloadedlocales clear
1108	    set resultvariable ""
1109	} -cleanup {
1110	    mcforgetpackage
1111	} -body {
1112	    mcpackageconfig set unknowncmd [namespace code callbackproc]
1113	    mclocale foo_bar
1114	    mc k1 p1
1115	    set resultvariable
1116	} -result {foo_bar k1 p1}
1117
1118	test msgcat-14.5 {disable global unknowncmd} -setup {
1119	    mcforgetpackage
1120    	    mclocale $locale
1121	    mclocale ""
1122	    mcloadedlocales clear
1123	    set resultvariable ""
1124	    rename ::msgcat::mcunknown SavedMcunknown
1125	    proc ::msgcat::mcunknown {dom s} {
1126		return unknown:$dom:$s
1127	    }
1128	} -cleanup {
1129	    mcforgetpackage
1130	    rename ::msgcat::mcunknown {}
1131	    rename SavedMcunknown ::msgcat::mcunknown
1132	} -body {
1133	    mcpackageconfig set unknowncmd ""
1134	    mclocale foo_bar
1135	    mc k1%s p1
1136	} -result {k1p1}
1137
1138	test msgcat-14.6 {unknowncmd failing} -setup {
1139	    mcforgetpackage
1140    	    mclocale $locale
1141	    mclocale ""
1142	    mcloadedlocales clear
1143	    set resultvariable ""
1144	} -cleanup {
1145	    mcforgetpackage
1146	} -body {
1147	    mcpackageconfig set unknowncmd [namespace code callbackfailproc]
1148	    mclocale foo_bar
1149	    mc k1
1150	} -returnCodes 1\
1151	-result {fail}
1152
1153
1154    # Tests msgcat-15.*: tcloo coverage
1155
1156    # There are 4 use-cases, where 3 must be tested now:
1157    # - namespace defined, in class definition, class defined oo, classless
1158
1159    test msgcat-15.1 {mc in class setup} -setup {
1160	# full namespace is ::msgcat::test:bar
1161	namespace eval bar {
1162	    ::msgcat::mcset foo_BAR con2 con2bar
1163	    oo::class create ClassCur
1164	}
1165	variable locale [mclocale]
1166	mclocale foo_BAR
1167    } -cleanup {
1168	mclocale $locale
1169	namespace eval bar {::msgcat::mcforgetpackage}
1170	namespace delete bar
1171    } -body {
1172	oo::define bar::ClassCur msgcat::mc con2
1173    } -result con2bar
1174
1175    test msgcat-15.2 {mc in class} -setup {
1176	# full namespace is ::msgcat::test:bar
1177	namespace eval bar {
1178	    ::msgcat::mcset foo_BAR con2 con2bar
1179	    oo::class create ClassCur
1180	    oo::define ClassCur method method1 {} {::msgcat::mc con2}
1181	}
1182	# full namespace is ::msgcat::test:baz
1183	namespace eval baz {
1184            set ObjCur [::msgcat::test::bar::ClassCur new]
1185	}
1186	variable locale [mclocale]
1187	mclocale foo_BAR
1188    } -cleanup {
1189	mclocale $locale
1190	namespace eval bar {::msgcat::mcforgetpackage}
1191	namespace delete bar baz
1192    } -body {
1193	$baz::ObjCur method1
1194    } -result con2bar
1195
1196    test msgcat-15.3 {mc in classless object} -setup {
1197	# full namespace is ::msgcat::test:bar
1198	namespace eval bar {
1199	    ::msgcat::mcset foo_BAR con2 con2bar
1200	    oo::object create ObjCur
1201	    oo::objdefine ObjCur method method1 {} {::msgcat::mc con2}
1202	}
1203	variable locale [mclocale]
1204	mclocale foo_BAR
1205    } -cleanup {
1206	mclocale $locale
1207	namespace eval bar {::msgcat::mcforgetpackage}
1208	namespace delete bar
1209    } -body {
1210	bar::ObjCur method1
1211    } -result con2bar
1212
1213    test msgcat-15.4 {mc in classless object with explicite namespace eval}\
1214    -setup {
1215	# full namespace is ::msgcat::test:bar
1216	namespace eval bar {
1217	    ::msgcat::mcset foo_BAR con2 con2bar
1218	    oo::object create ObjCur
1219	    oo::objdefine ObjCur method method1 {} {
1220		namespace eval ::msgcat::test::baz {
1221		    ::msgcat::mc con2
1222		}
1223	    }
1224	}
1225	namespace eval baz {
1226	    ::msgcat::mcset foo_BAR con2 con2baz
1227	}
1228	variable locale [mclocale]
1229	mclocale foo_BAR
1230    } -cleanup {
1231	mclocale $locale
1232	namespace eval bar {::msgcat::mcforgetpackage}
1233	namespace eval baz {::msgcat::mcforgetpackage}
1234	namespace delete bar baz
1235    } -body {
1236	bar::ObjCur method1
1237    } -result con2baz
1238
1239    # Test msgcat-16.*: command mcpackagenamespaceget
1240
1241    test msgcat-16.1 {mcpackagenamespaceget in namespace procedure} -body {
1242	namespace eval baz {msgcat::mcpackagenamespaceget}
1243    } -result ::msgcat::test::baz
1244
1245    test msgcat-16.2 {mcpackagenamespaceget in class setup} -setup {
1246	namespace eval bar {
1247	    oo::class create ClassCur
1248	    oo::define ClassCur variable a
1249	}
1250    } -cleanup {
1251	namespace delete bar
1252    } -body {
1253	oo::define bar::ClassCur msgcat::mcpackagenamespaceget
1254    } -result ::msgcat::test::bar
1255
1256    test msgcat-16.3 {mcpackagenamespaceget in class} -setup {
1257	namespace eval bar {
1258	    oo::class create ClassCur
1259	    oo::define ClassCur method method1 {} {msgcat::mcpackagenamespaceget}
1260	}
1261	namespace eval baz {
1262            set ObjCur [::msgcat::test::bar::ClassCur new]
1263	}
1264    } -cleanup {
1265	namespace delete bar baz
1266    } -body {
1267	$baz::ObjCur method1
1268    } -result ::msgcat::test::bar
1269
1270    test msgcat-16.4 {mcpackagenamespaceget in classless object} -setup {
1271	namespace eval bar {
1272	    oo::object create ObjCur
1273	    oo::objdefine ObjCur method method1 {} {msgcat::mcpackagenamespaceget}
1274	}
1275    } -cleanup {
1276	namespace delete bar
1277    } -body {
1278	bar::ObjCur method1
1279    } -result ::msgcat::test::bar
1280
1281    test msgcat-16.5\
1282    {mcpackagenamespaceget in classless object with explicite namespace eval}\
1283    -setup {
1284	namespace eval bar {
1285	    oo::object create ObjCur
1286	    oo::objdefine ObjCur method method1 {} {
1287		namespace eval ::msgcat::test::baz {
1288		    msgcat::mcpackagenamespaceget
1289		}
1290	    }
1291	}
1292    } -cleanup {
1293	namespace delete bar baz
1294    } -body {
1295	bar::ObjCur method1
1296    } -result ::msgcat::test::baz
1297
1298
1299    # Test msgcat-17.*: mcn command
1300
1301    test msgcat-17.1 {mcn no parameters} -body {
1302	mcn
1303    } -returnCodes 1\
1304    -result {wrong # args: should be "mcn ns src ?arg ...?"}
1305
1306    test msgcat-17.2 {mcn} -setup {
1307	namespace eval bar {::msgcat::mcset foo_BAR con1 con1bar}
1308	variable locale [mclocale]
1309	mclocale foo_BAR
1310    } -cleanup {
1311	mclocale $locale
1312    } -body {
1313	::msgcat::mcn [namespace current]::bar con1
1314    } -result con1bar
1315
1316
1317    interp bgerror {} $bgerrorsaved
1318
1319    # Tests msgcat-18.*: [mcutil]
1320
1321    test msgcat-18.1 {mcutil - no argument} -body {
1322	mcutil
1323    } -returnCodes 1\
1324    -result {wrong # args: should be "mcutil subcommand ?arg ...?"}
1325
1326    test msgcat-18.2 {mcutil - wrong argument} -body {
1327	mcutil junk
1328    } -returnCodes 1\
1329    -result {unknown subcommand "junk": must be getpreferences, or getsystemlocale}
1330
1331    test msgcat-18.3 {mcutil - partial argument} -body {
1332	mcutil getsystem
1333    } -returnCodes 1\
1334    -result {unknown subcommand "getsystem": must be getpreferences, or getsystemlocale}
1335
1336    test msgcat-18.4 {mcutil getpreferences - no argument} -body {
1337	mcutil getpreferences
1338    } -returnCodes 1\
1339    -result {wrong # args: should be "mcutil getpreferences locale"}
1340
1341    test msgcat-18.5 {mcutil getpreferences - DE_de} -body {
1342	mcutil getpreferences DE_de
1343    } -result {de_de de {}}
1344
1345    test msgcat-18.6 {mcutil getsystemlocale - wrong argument} -body {
1346	mcutil getsystemlocale DE_de
1347    } -returnCodes 1\
1348    -result {wrong # args: should be "mcutil getsystemlocale"}
1349
1350    # The result is system dependent
1351    # So just test if it runs
1352    # The environment variable version was test with test 0.x
1353    test msgcat-18.7 {mcutil getsystemlocale} -body {
1354	mcutil getsystemlocale
1355	set ok ok
1356    } -result {ok}
1357
1358
1359    cleanupTests
1360}
1361namespace delete ::msgcat::test
1362return
1363
1364# Local Variables:
1365# mode: tcl
1366# End:
1367