github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/language/display/display_test.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package display
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"testing"
    11  	"unicode"
    12  
    13  	"golang.org/x/text/language"
    14  )
    15  
    16  // TODO: test that tables are properly dropped by the linker for various use
    17  // cases.
    18  
    19  var (
    20  	firstLang2aa  = language.MustParseBase("aa")
    21  	lastLang2zu   = language.MustParseBase("zu")
    22  	firstLang3ace = language.MustParseBase("ace")
    23  	lastLang3zza  = language.MustParseBase("zza")
    24  	firstTagAr001 = language.MustParse("ar-001")
    25  	lastTagZhHant = language.MustParse("zh-Hant")
    26  )
    27  
    28  // TestValues tests that for all languages, regions, and scripts in Values, at
    29  // least one language has a name defined for it by checking it exists in
    30  // English, which is assumed to be the most comprehensive. It is also tested
    31  // that a Namer returns "" for unsupported values.
    32  func TestValues(t *testing.T) {
    33  	type testcase struct {
    34  		kind string
    35  		n    Namer
    36  	}
    37  	// checkDefined checks that a value exists in a Namer.
    38  	checkDefined := func(x interface{}, namers []testcase) {
    39  		for _, n := range namers {
    40  			if n.n.Name(x) == "" {
    41  				// As of version 28 there is no data for az-Arab in English,
    42  				// although there is useful data in other languages.
    43  				if x.(fmt.Stringer).String() == "az-Arab" {
    44  					continue
    45  				}
    46  				t.Errorf("%s.Name(%s): supported but no result", n.kind, x)
    47  			}
    48  		}
    49  	}
    50  	// checkUnsupported checks that a value does not exist in a Namer.
    51  	checkUnsupported := func(x interface{}, namers []testcase) {
    52  		for _, n := range namers {
    53  			if got := n.n.Name(x); got != "" {
    54  				t.Fatalf("%s.Name(%s): unsupported tag gave non-empty result: %q", n.kind, x, got)
    55  			}
    56  		}
    57  	}
    58  
    59  	tags := map[language.Tag]bool{}
    60  	namers := []testcase{
    61  		{"Languages(en)", Languages(language.English)},
    62  		{"Tags(en)", Tags(language.English)},
    63  		{"English.Languages()", English.Languages()},
    64  		{"English.Tags()", English.Tags()},
    65  	}
    66  	for _, tag := range Values.Tags() {
    67  		checkDefined(tag, namers)
    68  		tags[tag] = true
    69  	}
    70  	for _, base := range language.Supported.BaseLanguages() {
    71  		tag, _ := language.All.Compose(base)
    72  		if !tags[tag] {
    73  			checkUnsupported(tag, namers)
    74  		}
    75  	}
    76  
    77  	regions := map[language.Region]bool{}
    78  	namers = []testcase{
    79  		{"Regions(en)", Regions(language.English)},
    80  		{"English.Regions()", English.Regions()},
    81  	}
    82  	for _, r := range Values.Regions() {
    83  		checkDefined(r, namers)
    84  		regions[r] = true
    85  	}
    86  	for _, r := range language.Supported.Regions() {
    87  		if r = r.Canonicalize(); !regions[r] {
    88  			checkUnsupported(r, namers)
    89  		}
    90  	}
    91  
    92  	scripts := map[language.Script]bool{}
    93  	namers = []testcase{
    94  		{"Scripts(en)", Scripts(language.English)},
    95  		{"English.Scripts()", English.Scripts()},
    96  	}
    97  	for _, s := range Values.Scripts() {
    98  		checkDefined(s, namers)
    99  		scripts[s] = true
   100  	}
   101  	for _, s := range language.Supported.Scripts() {
   102  		// Canonicalize the script.
   103  		tag, _ := language.DeprecatedScript.Compose(s)
   104  		if _, s, _ = tag.Raw(); !scripts[s] {
   105  			checkUnsupported(s, namers)
   106  		}
   107  	}
   108  }
   109  
   110  // TestSupported tests that we have at least some Namers for languages that we
   111  // claim to support. To test the claims in the documentation, it also verifies
   112  // that if a Namer is returned, it will have at least some data.
   113  func TestSupported(t *testing.T) {
   114  	supportedTags := Supported.Tags()
   115  	if len(supportedTags) != numSupported {
   116  		t.Errorf("number of supported was %d; want %d", len(supportedTags), numSupported)
   117  	}
   118  
   119  	namerFuncs := []struct {
   120  		kind string
   121  		fn   func(language.Tag) Namer
   122  	}{
   123  		{"Tags", Tags},
   124  		{"Languages", Languages},
   125  		{"Regions", Regions},
   126  		{"Scripts", Scripts},
   127  	}
   128  
   129  	// Verify that we have at least one Namer for all tags we claim to support.
   130  	tags := make(map[language.Tag]bool)
   131  	for _, tag := range supportedTags {
   132  		// Test we have at least one Namer for this supported Tag.
   133  		found := false
   134  		for _, kind := range namerFuncs {
   135  			if defined(t, kind.kind, kind.fn(tag), tag) {
   136  				found = true
   137  			}
   138  		}
   139  		if !found {
   140  			t.Errorf("%s: supported, but no data available", tag)
   141  		}
   142  		if tags[tag] {
   143  			t.Errorf("%s: included in Supported.Tags more than once", tag)
   144  		}
   145  		tags[tag] = true
   146  	}
   147  
   148  	// Verify that we have no Namers for tags we don't claim to support.
   149  	for _, base := range language.Supported.BaseLanguages() {
   150  		tag, _ := language.All.Compose(base)
   151  		// Skip tags that are supported after matching.
   152  		if _, _, conf := matcher.Match(tag); conf != language.No {
   153  			continue
   154  		}
   155  		// Test there are no Namers for this tag.
   156  		for _, kind := range namerFuncs {
   157  			if defined(t, kind.kind, kind.fn(tag), tag) {
   158  				t.Errorf("%[1]s(%[2]s) returns a Namer, but %[2]s is not in the set of supported Tags.", kind.kind, tag)
   159  			}
   160  		}
   161  	}
   162  }
   163  
   164  // defined reports whether n is a proper Namer, which means it is non-nil and
   165  // must have at least one non-empty value.
   166  func defined(t *testing.T, kind string, n Namer, tag language.Tag) bool {
   167  	if n == nil {
   168  		return false
   169  	}
   170  	switch kind {
   171  	case "Tags":
   172  		for _, t := range Values.Tags() {
   173  			if n.Name(t) != "" {
   174  				return true
   175  			}
   176  		}
   177  	case "Languages":
   178  		for _, t := range Values.BaseLanguages() {
   179  			if n.Name(t) != "" {
   180  				return true
   181  			}
   182  		}
   183  	case "Regions":
   184  		for _, t := range Values.Regions() {
   185  			if n.Name(t) != "" {
   186  				return true
   187  			}
   188  		}
   189  	case "Scripts":
   190  		for _, t := range Values.Scripts() {
   191  			if n.Name(t) != "" {
   192  				return true
   193  			}
   194  		}
   195  	}
   196  	t.Errorf("%s(%s) returns non-nil Namer without content", kind, tag)
   197  	return false
   198  }
   199  
   200  func TestCoverage(t *testing.T) {
   201  	en := language.English
   202  	tests := []struct {
   203  		n Namer
   204  		x interface{}
   205  	}{
   206  		{Languages(en), Values.Tags()},
   207  		{Scripts(en), Values.Scripts()},
   208  		{Regions(en), Values.Regions()},
   209  	}
   210  	for i, tt := range tests {
   211  		uniq := make(map[string]interface{})
   212  
   213  		v := reflect.ValueOf(tt.x)
   214  		for j := 0; j < v.Len(); j++ {
   215  			x := v.Index(j).Interface()
   216  			// As of version 28 there is no data for az-Arab in English,
   217  			// although there is useful data in other languages.
   218  			if x.(fmt.Stringer).String() == "az-Arab" {
   219  				continue
   220  			}
   221  			s := tt.n.Name(x)
   222  			if s == "" {
   223  				t.Errorf("%d:%d:%s: missing content", i, j, x)
   224  			} else if uniq[s] != nil {
   225  				t.Errorf("%d:%d:%s: identical return value %q for %v and %v", i, j, x, s, x, uniq[s])
   226  			}
   227  			uniq[s] = x
   228  		}
   229  	}
   230  }
   231  
   232  // TestUpdate tests whether dictionary entries for certain languages need to be
   233  // updated. For some languages, some of the headers may be empty or they may be
   234  // identical to the parent. This code detects if such entries need to be updated
   235  // after a table update.
   236  func TestUpdate(t *testing.T) {
   237  	tests := []struct {
   238  		d   *Dictionary
   239  		tag string
   240  	}{
   241  		{ModernStandardArabic, "ar-001"},
   242  		{AmericanEnglish, "en-US"},
   243  		{EuropeanSpanish, "es-ES"},
   244  		{BrazilianPortuguese, "pt-BR"},
   245  		{SimplifiedChinese, "zh-Hans"},
   246  	}
   247  
   248  	for _, tt := range tests {
   249  		_, i, _ := matcher.Match(language.MustParse(tt.tag))
   250  		if !reflect.DeepEqual(tt.d.lang, langHeaders[i]) {
   251  			t.Errorf("%s: lang table update needed", tt.tag)
   252  		}
   253  		if !reflect.DeepEqual(tt.d.script, scriptHeaders[i]) {
   254  			t.Errorf("%s: script table update needed", tt.tag)
   255  		}
   256  		if !reflect.DeepEqual(tt.d.region, regionHeaders[i]) {
   257  			t.Errorf("%s: region table update needed", tt.tag)
   258  		}
   259  	}
   260  }
   261  
   262  func TestIndex(t *testing.T) {
   263  	notIn := []string{"aa", "xx", "zz", "aaa", "xxx", "zzz", "Aaaa", "Xxxx", "Zzzz"}
   264  	tests := []tagIndex{
   265  		{
   266  			"",
   267  			"",
   268  			"",
   269  		},
   270  		{
   271  			"bb",
   272  			"",
   273  			"",
   274  		},
   275  		{
   276  			"",
   277  			"bbb",
   278  			"",
   279  		},
   280  		{
   281  			"",
   282  			"",
   283  			"Bbbb",
   284  		},
   285  		{
   286  			"bb",
   287  			"bbb",
   288  			"Bbbb",
   289  		},
   290  		{
   291  			"bbccddyy",
   292  			"bbbcccdddyyy",
   293  			"BbbbCcccDdddYyyy",
   294  		},
   295  	}
   296  	for i, tt := range tests {
   297  		// Create the test set from the tagIndex.
   298  		cnt := 0
   299  		for sz := 2; sz <= 4; sz++ {
   300  			a := tt[sz-2]
   301  			for j := 0; j < len(a); j += sz {
   302  				s := a[j : j+sz]
   303  				if idx := tt.index(s); idx != cnt {
   304  					t.Errorf("%d:%s: index was %d; want %d", i, s, idx, cnt)
   305  				}
   306  				cnt++
   307  			}
   308  		}
   309  		if n := tt.len(); n != cnt {
   310  			t.Errorf("%d: len was %d; want %d", i, n, cnt)
   311  		}
   312  		for _, x := range notIn {
   313  			if idx := tt.index(x); idx != -1 {
   314  				t.Errorf("%d:%s: index was %d; want -1", i, x, idx)
   315  			}
   316  		}
   317  	}
   318  }
   319  
   320  func TestTag(t *testing.T) {
   321  	tests := []struct {
   322  		dict string
   323  		tag  string
   324  		name string
   325  	}{
   326  		{"agq", "sr", ""}, // sr is in Value.Languages(), but is not supported by agq.
   327  		{"nl", "nl", "Nederlands"},
   328  		{"nl", "nl-BE", "Vlaams"},
   329  		{"en", "en", "English"},
   330  		{"en", "en-GB", "British English"},
   331  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   332  		{"ru", "ru", "русский"},
   333  		{"ru", "ru-RU", "русский (Россия)"},
   334  		{"ru", "ru-Cyrl", "русский (кириллица)"},
   335  		{"en", lastLang2zu.String(), "Zulu"},
   336  		{"en", firstLang2aa.String(), "Afar"},
   337  		{"en", lastLang3zza.String(), "Zaza"},
   338  		{"en", firstLang3ace.String(), "Achinese"},
   339  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   340  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   341  		{"en", "aaa", ""},
   342  		{"en", "zzj", ""},
   343  		// If full tag doesn't match, try without script or region.
   344  		{"en", "aa-Hans", "Afar (Simplified Han)"},
   345  		{"en", "af-Arab", "Afrikaans (Arabic)"},
   346  		{"en", "zu-Cyrl", "Zulu (Cyrillic)"},
   347  		{"en", "aa-GB", "Afar (United Kingdom)"},
   348  		{"en", "af-NA", "Afrikaans (Namibia)"},
   349  		{"en", "zu-BR", "Zulu (Brazil)"},
   350  		// Correct inheritance and language selection.
   351  		{"zh", "zh-TW", "中文 (台湾)"},
   352  		{"zh", "zh-Hant-TW", "繁体中文 (台湾)"},
   353  		{"zh-Hant", "zh-TW", "中文 (台灣)"},
   354  		{"zh-Hant", "zh-Hant-TW", "繁體中文 (台灣)"},
   355  		// Some rather arbitrary interpretations for Serbian. This is arguably
   356  		// correct and consistent with the way zh-[Hant-]TW is handled. It will
   357  		// also give results more in line with the expectations if users
   358  		// explicitly use "sh".
   359  		{"sr-Latn", "sr-ME", "srpski (Crna Gora)"},
   360  		{"sr-Latn", "sr-Latn-ME", "Srpskohrvatski (Crna Gora)"},
   361  		// Double script and region
   362  		{"nl", "en-Cyrl-BE", "Engels (Cyrillisch, België)"},
   363  		// Canonical equivalents.
   364  		{"ro", "ro-MD", "moldovenească"},
   365  		{"ro", "mo", "moldovenească"},
   366  	}
   367  	for i, tt := range tests {
   368  		d := Tags(language.MustParse(tt.dict))
   369  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   370  			// There are inconsistencies w.r.t. capitalization in the tests
   371  			// due to CLDR's update procedure which treats modern and other
   372  			// languages differently.
   373  			// See http://unicode.org/cldr/trac/ticket/8051.
   374  			// TODO: use language capitalization to sanitize the strings.
   375  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   376  		}
   377  	}
   378  }
   379  
   380  func TestLanguage(t *testing.T) {
   381  	tests := []struct {
   382  		dict string
   383  		tag  string
   384  		name string
   385  	}{
   386  		{"agq", "sr", ""}, // sr is in Value.Languages(), but is not supported by agq.
   387  		{"nl", "nl", "Nederlands"},
   388  		{"nl", "nl-BE", "Vlaams"},
   389  		{"en", "pt", "Portuguese"},
   390  		{"en", "pt-PT", "European Portuguese"},
   391  		{"en", "pt-BR", "Brazilian Portuguese"},
   392  		{"en", "en", "English"},
   393  		{"en", "en-GB", "British English"},
   394  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   395  		{"en", lastLang2zu.String(), "Zulu"},
   396  		{"en", firstLang2aa.String(), "Afar"},
   397  		{"en", lastLang3zza.String(), "Zaza"},
   398  		{"en", firstLang3ace.String(), "Achinese"},
   399  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   400  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   401  		{"en", "aaa", ""},
   402  		{"en", "zzj", ""},
   403  		// If full tag doesn't match, try without script or region.
   404  		{"en", "aa-Hans", "Afar"},
   405  		{"en", "af-Arab", "Afrikaans"},
   406  		{"en", "zu-Cyrl", "Zulu"},
   407  		{"en", "aa-GB", "Afar"},
   408  		{"en", "af-NA", "Afrikaans"},
   409  		{"en", "zu-BR", "Zulu"},
   410  		{"agq", "zh-Hant", ""},
   411  		// Canonical equivalents.
   412  		{"ro", "ro-MD", "moldovenească"},
   413  		{"ro", "mo", "moldovenească"},
   414  		{"en", "sh", "Serbo-Croatian"},
   415  		{"en", "sr-Latn", "Serbo-Croatian"},
   416  		{"en", "sr", "Serbian"},
   417  		{"en", "sr-ME", "Serbian"},
   418  		{"en", "sr-Latn-ME", "Serbo-Croatian"}, // See comments in TestTag.
   419  	}
   420  	for i, tt := range tests {
   421  		d := Languages(language.Raw.MustParse(tt.dict))
   422  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   423  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   424  		}
   425  		if len(tt.tag) <= 3 {
   426  			if n := d.Name(language.MustParseBase(tt.tag)); n != tt.name {
   427  				t.Errorf("%d:%s:base(%s): was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   428  			}
   429  		}
   430  	}
   431  }
   432  
   433  func TestScript(t *testing.T) {
   434  	tests := []struct {
   435  		dict string
   436  		scr  string
   437  		name string
   438  	}{
   439  		{"nl", "Arab", "Arabisch"},
   440  		{"en", "Arab", "Arabic"},
   441  		{"en", "Zzzz", "Unknown Script"},
   442  		{"zh-Hant", "Hang", "韓文字"},
   443  		{"zh-Hant-HK", "Hang", "韓文字母"},
   444  		{"zh", "Arab", "阿拉伯文"},
   445  		{"zh-Hans-HK", "Arab", "阿拉伯文"}, // same as zh
   446  		{"zh-Hant", "Arab", "阿拉伯文"},
   447  		{"zh-Hant-HK", "Arab", "阿拉伯文"}, // same as zh
   448  		// Canonicalized form
   449  		{"en", "Qaai", "Inherited"},    // deprecated script, now is Zinh
   450  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   451  		{"en", "en", "Unknown Script"},
   452  		// Don't introduce scripts with canonicalization.
   453  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   454  	}
   455  	for i, tt := range tests {
   456  		d := Scripts(language.MustParse(tt.dict))
   457  		var x interface{}
   458  		if unicode.IsUpper(rune(tt.scr[0])) {
   459  			x = language.MustParseScript(tt.scr)
   460  			tag, _ := language.Raw.Compose(x)
   461  			if n := d.Name(tag); n != tt.name {
   462  				t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name)
   463  			}
   464  		} else {
   465  			x = language.Raw.MustParse(tt.scr)
   466  		}
   467  		if n := d.Name(x); n != tt.name {
   468  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name)
   469  		}
   470  	}
   471  }
   472  
   473  func TestRegion(t *testing.T) {
   474  	tests := []struct {
   475  		dict string
   476  		reg  string
   477  		name string
   478  	}{
   479  		{"nl", "NL", "Nederland"},
   480  		{"en", "US", "United States"},
   481  		{"en", "ZZ", "Unknown Region"},
   482  		{"en", "UM", "U.S. Outlying Islands"},
   483  		{"en-GB", "UM", "U.S. Outlying Islands"},
   484  		{"en-GB", "NL", "Netherlands"},
   485  		// Canonical equivalents
   486  		{"en", "UK", "United Kingdom"},
   487  		// No region
   488  		{"en", "pt", "Unknown Region"},
   489  		{"en", "und", "Unknown Region"},
   490  		// Don't introduce regions with canonicalization.
   491  		{"en", "mo", "Unknown Region"},
   492  	}
   493  	for i, tt := range tests {
   494  		d := Regions(language.MustParse(tt.dict))
   495  		var x interface{}
   496  		if unicode.IsUpper(rune(tt.reg[0])) {
   497  			// Region
   498  			x = language.MustParseRegion(tt.reg)
   499  			tag, _ := language.Raw.Compose(x)
   500  			if n := d.Name(tag); n != tt.name {
   501  				t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name)
   502  			}
   503  		} else {
   504  			// Tag
   505  			x = language.Raw.MustParse(tt.reg)
   506  		}
   507  		if n := d.Name(x); n != tt.name {
   508  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name)
   509  		}
   510  	}
   511  }
   512  
   513  func TestSelf(t *testing.T) {
   514  	tests := []struct {
   515  		tag  string
   516  		name string
   517  	}{
   518  		{"nl", "Nederlands"},
   519  		{"nl-BE", "Vlaams"},
   520  		{"en-GB", "British English"},
   521  		{lastLang2zu.String(), "isiZulu"},
   522  		{firstLang2aa.String(), ""},  // not defined
   523  		{lastLang3zza.String(), ""},  // not defined
   524  		{firstLang3ace.String(), ""}, // not defined
   525  		{firstTagAr001.String(), "العربية الرسمية الحديثة"},
   526  		{"ar", "العربية"},
   527  		{lastTagZhHant.String(), "繁體中文"},
   528  		{"aaa", ""},
   529  		{"zzj", ""},
   530  		// Drop entries that are not in the requested script, even if there is
   531  		// an entry for the language.
   532  		{"aa-Hans", ""},
   533  		{"af-Arab", ""},
   534  		{"zu-Cyrl", ""},
   535  		// Append the country name in the language of the matching language.
   536  		{"af-NA", "Afrikaans"},
   537  		{"zh", "中文"},
   538  		// zh-TW should match zh-Hant instead of zh!
   539  		{"zh-TW", "繁體中文"},
   540  		{"zh-Hant", "繁體中文"},
   541  		{"zh-Hans", "简体中文"},
   542  		{"zh-Hant-TW", "繁體中文"},
   543  		{"zh-Hans-TW", "简体中文"},
   544  		// Take the entry for sr which has the matching script.
   545  		// TODO: Capitalization changed as of CLDR 26, but change seems
   546  		// arbitrary. Revisit capitalization with revision 27. See
   547  		// http://unicode.org/cldr/trac/ticket/8051.
   548  		{"sr", "српски"},
   549  		// TODO: sr-ME should show up as Serbian or Montenegrin, not Serbo-
   550  		// Croatian. This is an artifact of the current algorithm, which is the
   551  		// way it is to have the preferred behavior for other languages such as
   552  		// Chinese. We can hardwire this case in the table generator or package
   553  		// code, but we first check if CLDR can be updated.
   554  		// {"sr-ME", "Srpski"}, // Is Srpskohrvatski
   555  		{"sr-Latn-ME", "Srpskohrvatski"},
   556  		{"sr-Cyrl-ME", "српски"},
   557  		{"sr-NL", "српски"},
   558  		// Canonical equivalents.
   559  		{"ro-MD", "moldovenească"},
   560  		{"mo", "moldovenească"},
   561  		// NOTE: kk is defined, but in Cyrillic script. For China, Arab is the
   562  		// dominant script. We do not have data for kk-Arab and we chose to not
   563  		// fall back in such cases.
   564  		{"kk-CN", ""},
   565  	}
   566  	for i, tt := range tests {
   567  		d := Self
   568  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   569  			t.Errorf("%d:%s: was %q; want %q", i, tt.tag, n, tt.name)
   570  		}
   571  	}
   572  }
   573  
   574  func TestDictionaryLang(t *testing.T) {
   575  	tests := []struct {
   576  		d    *Dictionary
   577  		tag  string
   578  		name string
   579  	}{
   580  		{English, "en", "English"},
   581  		{Portuguese, "af", "africâner"},
   582  		{EuropeanPortuguese, "af", "africânder"},
   583  		{English, "nl-BE", "Flemish"},
   584  	}
   585  	for i, test := range tests {
   586  		tag := language.MustParse(test.tag)
   587  		if got := test.d.Tags().Name(tag); got != test.name {
   588  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   589  		}
   590  		if base, _ := language.Compose(tag.Base()); base == tag {
   591  			if got := test.d.Languages().Name(base); got != test.name {
   592  				t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   593  			}
   594  		}
   595  	}
   596  }
   597  
   598  func TestDictionaryRegion(t *testing.T) {
   599  	tests := []struct {
   600  		d      *Dictionary
   601  		region string
   602  		name   string
   603  	}{
   604  		{English, "FR", "France"},
   605  		{Portuguese, "009", "Oceania"},
   606  		{EuropeanPortuguese, "009", "Oceânia"},
   607  	}
   608  	for i, test := range tests {
   609  		tag := language.MustParseRegion(test.region)
   610  		if got := test.d.Regions().Name(tag); got != test.name {
   611  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   612  		}
   613  	}
   614  }
   615  
   616  func TestDictionaryScript(t *testing.T) {
   617  	tests := []struct {
   618  		d      *Dictionary
   619  		script string
   620  		name   string
   621  	}{
   622  		{English, "Cyrl", "Cyrillic"},
   623  		{Portuguese, "Gujr", "gujerati"},
   624  		{EuropeanPortuguese, "Gujr", "guzerate"},
   625  	}
   626  	for i, test := range tests {
   627  		tag := language.MustParseScript(test.script)
   628  		if got := test.d.Scripts().Name(tag); got != test.name {
   629  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   630  		}
   631  	}
   632  }