github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/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  	"reflect"
     9  	"testing"
    10  	"unicode"
    11  
    12  	"golang.org/x/text/language"
    13  )
    14  
    15  // TODO: test that tables are properly dropped by the linker for various use
    16  // cases.
    17  
    18  var (
    19  	firstLang2aa  = language.MustParseBase("aa")
    20  	lastLang2zu   = language.MustParseBase("zu")
    21  	firstLang3ace = language.MustParseBase("ace")
    22  	lastLang3zza  = language.MustParseBase("zza")
    23  	firstTagAr001 = language.MustParse("ar-001")
    24  	lastTagZhHant = language.MustParse("zh-Hant")
    25  )
    26  
    27  func TestSupported(t *testing.T) {
    28  	supportedTags := Supported.Tags()
    29  	if len(supportedTags) != numSupported {
    30  		t.Errorf("number of supported was %d; want %d", len(supportedTags), numSupported)
    31  	}
    32  
    33  	tags := make(map[language.Tag]bool)
    34  	namers := make(map[Namer]bool)
    35  	// isNil verifies that the namer is unique and returns whether it is nil.
    36  	isNil := func(n Namer) bool {
    37  		if n != nil {
    38  			if namers[n] {
    39  				t.Errorf("%s: duplicate namer", n)
    40  			}
    41  			namers[n] = true
    42  		}
    43  		return n == nil
    44  	}
    45  
    46  	for _, tag := range supportedTags {
    47  		if isNil(Languages(tag)) && isNil(Regions(tag)) && isNil(Scripts(tag)) {
    48  			t.Errorf("%s: supported, but no data available", tag)
    49  		}
    50  		if tags[tag] {
    51  			t.Errorf("%s: included in Supported.Tags more than once", tag)
    52  		}
    53  		tags[tag] = true
    54  	}
    55  }
    56  
    57  func TestCoverage(t *testing.T) {
    58  	en := language.English
    59  	tests := []struct {
    60  		n Namer
    61  		x interface{}
    62  	}{
    63  		{Languages(en), Values.Tags()},
    64  		{Scripts(en), Values.Scripts()},
    65  		{Regions(en), Values.Regions()},
    66  	}
    67  	for i, tt := range tests {
    68  		uniq := make(map[string]interface{})
    69  
    70  		v := reflect.ValueOf(tt.x)
    71  		for j := 0; j < v.Len(); j++ {
    72  			x := v.Index(j).Interface()
    73  			s := tt.n.Name(x)
    74  			if s == "" {
    75  				t.Errorf("%d:%d:%s: missing content", i, j, x)
    76  			} else if uniq[s] != nil {
    77  				t.Errorf("%d:%d:%s: identical return value %q for %v and %v", i, j, x, s, x, uniq[s])
    78  			}
    79  			uniq[s] = x
    80  		}
    81  	}
    82  }
    83  
    84  // TestUpdate tests whether dictionary entries for certain languages need to be
    85  // updated. For some languages, some of the headers may be empty or they may be
    86  // identical to the parent. This code detects if such entries need to be updated
    87  // after a table update.
    88  func TestUpdate(t *testing.T) {
    89  	tests := []struct {
    90  		d   *Dictionary
    91  		tag string
    92  	}{
    93  		{ModernStandardArabic, "ar-001"},
    94  		{AmericanEnglish, "en-US"},
    95  		{EuropeanSpanish, "es-ES"},
    96  		{BrazilianPortuguese, "pt-BR"},
    97  		{SimplifiedChinese, "zh-Hans"},
    98  	}
    99  
   100  	for _, tt := range tests {
   101  		_, i, _ := matcher.Match(language.MustParse(tt.tag))
   102  		if !reflect.DeepEqual(tt.d.lang, langHeaders[i]) {
   103  			t.Errorf("%s: lang table update needed", tt.tag)
   104  		}
   105  		if !reflect.DeepEqual(tt.d.script, scriptHeaders[i]) {
   106  			t.Errorf("%s: script table update needed", tt.tag)
   107  		}
   108  		if !reflect.DeepEqual(tt.d.region, regionHeaders[i]) {
   109  			t.Errorf("%s: region table update needed", tt.tag)
   110  		}
   111  	}
   112  }
   113  
   114  func TestIndex(t *testing.T) {
   115  	notIn := []string{"aa", "xx", "zz", "aaa", "xxx", "zzz", "Aaaa", "Xxxx", "Zzzz"}
   116  	tests := []tagIndex{
   117  		{
   118  			"",
   119  			"",
   120  			"",
   121  		},
   122  		{
   123  			"bb",
   124  			"",
   125  			"",
   126  		},
   127  		{
   128  			"",
   129  			"bbb",
   130  			"",
   131  		},
   132  		{
   133  			"",
   134  			"",
   135  			"Bbbb",
   136  		},
   137  		{
   138  			"bb",
   139  			"bbb",
   140  			"Bbbb",
   141  		},
   142  		{
   143  			"bbccddyy",
   144  			"bbbcccdddyyy",
   145  			"BbbbCcccDdddYyyy",
   146  		},
   147  	}
   148  	for i, tt := range tests {
   149  		// Create the test set from the tagIndex.
   150  		cnt := 0
   151  		for sz := 2; sz <= 4; sz++ {
   152  			a := tt[sz-2]
   153  			for j := 0; j < len(a); j += sz {
   154  				s := a[j : j+sz]
   155  				if idx := tt.index(s); idx != cnt {
   156  					t.Errorf("%d:%s: index was %d; want %d", i, s, idx, cnt)
   157  				}
   158  				cnt++
   159  			}
   160  		}
   161  		if n := tt.len(); n != cnt {
   162  			t.Errorf("%d: len was %d; want %d", i, n, cnt)
   163  		}
   164  		for _, x := range notIn {
   165  			if idx := tt.index(x); idx != -1 {
   166  				t.Errorf("%d:%s: index was %d; want -1", i, x, idx)
   167  			}
   168  		}
   169  	}
   170  }
   171  
   172  func TestTag(t *testing.T) {
   173  	tests := []struct {
   174  		dict string
   175  		tag  string
   176  		name string
   177  	}{
   178  		{"nl", "nl", "Nederlands"},
   179  		{"nl", "nl-BE", "Vlaams"},
   180  		{"en", "en", "English"},
   181  		{"en", "en-GB", "British English"},
   182  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   183  		{"ru", "ru", "русский"},
   184  		{"ru", "ru-RU", "русский (Россия)"},
   185  		// TODO: Script capitalization changed in CLDR 26, but the change seems
   186  		// aribitrary as for most scripts it did not.
   187  		{"ru", "ru-Cyrl", "русский (Кириллица)"},
   188  		{"en", lastLang2zu.String(), "Zulu"},
   189  		{"en", firstLang2aa.String(), "Afar"},
   190  		{"en", lastLang3zza.String(), "Zaza"},
   191  		{"en", firstLang3ace.String(), "Achinese"},
   192  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   193  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   194  		{"en", "aaa", ""},
   195  		{"en", "zzj", ""},
   196  		// If full tag doesn't match, try without script or retion.
   197  		{"en", "aa-Hans", "Afar (Simplified Han)"},
   198  		{"en", "af-Arab", "Afrikaans (Arabic)"},
   199  		{"en", "zu-Cyrl", "Zulu (Cyrillic)"},
   200  		{"en", "aa-GB", "Afar (United Kingdom)"},
   201  		{"en", "af-NA", "Afrikaans (Namibia)"},
   202  		{"en", "zu-BR", "Zulu (Brazil)"},
   203  		// Correct inheritance and language selection.
   204  		{"zh", "zh-TW", "中文 (台湾)"},
   205  		{"zh", "zh-Hant-TW", "繁体中文 (台湾)"},
   206  		{"zh-Hant", "zh-TW", "中文 (台灣)"},
   207  		{"zh-Hant", "zh-Hant-TW", "繁體中文 (台灣)"},
   208  		// Some rather arbitrary interpretations for Serbian. This is arguably
   209  		// correct and consistent with the way zh-[Hant-]TW is handled. It will
   210  		// also give results more in line with the expectations if users
   211  		// explicitly use "sh".
   212  		{"sr-Latn", "sr-ME", "Srpski (Crna Gora)"},
   213  		{"sr-Latn", "sr-Latn-ME", "Srpskohrvatski (Crna Gora)"},
   214  		// Double script and region
   215  		{"nl", "en-Cyrl-BE", "Engels (Cyrillisch, België)"},
   216  		// Canonical equivalents.
   217  		{"ro", "ro-MD", "moldovenească"},
   218  		{"ro", "mo", "moldovenească"},
   219  	}
   220  	for i, tt := range tests {
   221  		d := Tags(language.MustParse(tt.dict))
   222  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   223  			// Change back to Errorf when CLDR ticker
   224  			// http://unicode.org/cldr/trac/ticket/8051 is resolved.
   225  			t.Skipf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   226  		}
   227  	}
   228  }
   229  
   230  func TestLanguage(t *testing.T) {
   231  	tests := []struct {
   232  		dict string
   233  		tag  string
   234  		name string
   235  	}{
   236  		{"nl", "nl", "Nederlands"},
   237  		{"nl", "nl-BE", "Vlaams"},
   238  		{"en", "pt", "Portuguese"},
   239  		{"en", "pt-PT", "European Portuguese"},
   240  		{"en", "pt-BR", "Brazilian Portuguese"},
   241  		{"en", "en", "English"},
   242  		{"en", "en-GB", "British English"},
   243  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   244  		{"en", lastLang2zu.String(), "Zulu"},
   245  		{"en", firstLang2aa.String(), "Afar"},
   246  		{"en", lastLang3zza.String(), "Zaza"},
   247  		{"en", firstLang3ace.String(), "Achinese"},
   248  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   249  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   250  		{"en", "aaa", ""},
   251  		{"en", "zzj", ""},
   252  		// If full tag doesn't match, try without script or region.
   253  		{"en", "aa-Hans", "Afar"},
   254  		{"en", "af-Arab", "Afrikaans"},
   255  		{"en", "zu-Cyrl", "Zulu"},
   256  		{"en", "aa-GB", "Afar"},
   257  		{"en", "af-NA", "Afrikaans"},
   258  		{"en", "zu-BR", "Zulu"},
   259  		{"agq", "zh-Hant", ""},
   260  		// Canonical equivalents.
   261  		{"ro", "ro-MD", "moldovenească"},
   262  		{"ro", "mo", "moldovenească"},
   263  		{"en", "sh", "Serbo-Croatian"},
   264  		{"en", "sr-Latn", "Serbo-Croatian"},
   265  		{"en", "sr", "Serbian"},
   266  		{"en", "sr-ME", "Serbian"},
   267  		{"en", "sr-Latn-ME", "Serbo-Croatian"}, // See comments in TestTag.
   268  	}
   269  	for i, tt := range tests {
   270  		d := Languages(language.Raw.MustParse(tt.dict))
   271  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   272  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   273  		}
   274  		if len(tt.tag) <= 3 {
   275  			if n := d.Name(language.MustParseBase(tt.tag)); n != tt.name {
   276  				t.Errorf("%d:%s:base(%s): was %q; want %q", i, tt.dict, tt.tag, n, tt.name)
   277  			}
   278  		}
   279  	}
   280  }
   281  
   282  func TestScript(t *testing.T) {
   283  	tests := []struct {
   284  		dict string
   285  		scr  string
   286  		name string
   287  	}{
   288  		{"nl", "Arab", "Arabisch"},
   289  		{"en", "Arab", "Arabic"},
   290  		{"en", "Zzzz", "Unknown Script"},
   291  		{"zh-Hant", "Hang", "韓文字"},
   292  		{"zh-Hant-HK", "Hang", "韓文字母"},
   293  		{"zh", "Arab", "阿拉伯文"},
   294  		{"zh-Hans-HK", "Arab", "阿拉伯文"}, // same as zh
   295  		{"zh-Hant", "Arab", "阿拉伯文"},
   296  		{"zh-Hant-HK", "Arab", "阿拉伯文"}, // same as zh
   297  		// Canonicalized form
   298  		{"en", "Qaai", "Inherited"},    // deprecated script, now is Zinh
   299  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   300  		{"en", "en", "Unknown Script"},
   301  		// Don't introduce scripts with canonicalization.
   302  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   303  	}
   304  	for i, tt := range tests {
   305  		d := Scripts(language.MustParse(tt.dict))
   306  		var x interface{}
   307  		if unicode.IsUpper(rune(tt.scr[0])) {
   308  			x = language.MustParseScript(tt.scr)
   309  			tag, _ := language.Raw.Compose(x)
   310  			if n := d.Name(tag); n != tt.name {
   311  				t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name)
   312  			}
   313  		} else {
   314  			x = language.Raw.MustParse(tt.scr)
   315  		}
   316  		if n := d.Name(x); n != tt.name {
   317  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name)
   318  		}
   319  	}
   320  }
   321  
   322  func TestRegion(t *testing.T) {
   323  	tests := []struct {
   324  		dict string
   325  		reg  string
   326  		name string
   327  	}{
   328  		{"nl", "NL", "Nederland"},
   329  		{"en", "US", "United States"},
   330  		{"en", "ZZ", "Unknown Region"},
   331  		{"en", "UM", "U.S. Outlying Islands"},
   332  		{"en-GB", "UM", "U.S. Outlying Islands"},
   333  		{"en-GB", "NL", "Netherlands"},
   334  		// Canonical equivalents
   335  		{"en", "UK", "United Kingdom"},
   336  		// No region
   337  		{"en", "pt", "Unknown Region"},
   338  		{"en", "und", "Unknown Region"},
   339  		// Don't introduce regions with canonicalization.
   340  		{"en", "mo", "Unknown Region"},
   341  	}
   342  	for i, tt := range tests {
   343  		d := Regions(language.MustParse(tt.dict))
   344  		var x interface{}
   345  		if unicode.IsUpper(rune(tt.reg[0])) {
   346  			// Region
   347  			x = language.MustParseRegion(tt.reg)
   348  			tag, _ := language.Raw.Compose(x)
   349  			if n := d.Name(tag); n != tt.name {
   350  				t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name)
   351  			}
   352  		} else {
   353  			// Tag
   354  			x = language.Raw.MustParse(tt.reg)
   355  		}
   356  		if n := d.Name(x); n != tt.name {
   357  			t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name)
   358  		}
   359  	}
   360  }
   361  
   362  func TestSelf(t *testing.T) {
   363  	tests := []struct {
   364  		tag  string
   365  		name string
   366  	}{
   367  		{"nl", "Nederlands"},
   368  		{"nl-BE", "Vlaams"},
   369  		{"en-GB", "British English"},
   370  		{lastLang2zu.String(), "isiZulu"},
   371  		{firstLang2aa.String(), ""},  // not defined
   372  		{lastLang3zza.String(), ""},  // not defined
   373  		{firstLang3ace.String(), ""}, // not defined
   374  		{firstTagAr001.String(), "العربية الرسمية الحديثة"},
   375  		{"ar", "العربية"},
   376  		{lastTagZhHant.String(), "繁體中文"},
   377  		{"aaa", ""},
   378  		{"zzj", ""},
   379  		// Drop entries that are not in the requested script, even if there is
   380  		// an entry for the language.
   381  		{"aa-Hans", ""},
   382  		{"af-Arab", ""},
   383  		{"zu-Cyrl", ""},
   384  		// Append the country name in the language of the matching language.
   385  		{"af-NA", "Afrikaans"},
   386  		{"zh", "中文"},
   387  		// zh-TW should match zh-Hant instead of zh!
   388  		{"zh-TW", "繁體中文"},
   389  		{"zh-Hant", "繁體中文"},
   390  		{"zh-Hans", "简体中文"},
   391  		{"zh-Hant-TW", "繁體中文"},
   392  		{"zh-Hans-TW", "简体中文"},
   393  		// Take the entry for sr which has the matching script.
   394  		// TODO: Capitalization changed as of CLDR 26, but change seems
   395  		// arbitrary. Revisit capitalization with revision 27. See
   396  		// http://unicode.org/cldr/trac/ticket/8051.
   397  		{"sr", "српски"},
   398  		// TODO: sr-ME should show up as Serbian or Montenegrin, not Serbo-
   399  		// Croatian. This is an artifact of the current algorithm, which is the
   400  		// way it is to have the preferred behavior for other languages such as
   401  		// Chinese. We can hardwire this case in the table generator or package
   402  		// code, but we first check if CLDR can be updated.
   403  		// {"sr-ME", "Srpski"}, // Is Srpskohrvatski
   404  		{"sr-Latn-ME", "Srpskohrvatski"},
   405  		{"sr-Cyrl-ME", "српски"},
   406  		{"sr-NL", "српски"},
   407  		// Canonical equivalents.
   408  		{"ro-MD", "moldovenească"},
   409  		{"mo", "moldovenească"},
   410  		// NOTE: kk is defined, but in Cyrillic script. For China, Arab is the
   411  		// dominant script. We do not have data for kk-Arab and we chose to not
   412  		// fall back in such cases.
   413  		{"kk-CN", ""},
   414  	}
   415  	for i, tt := range tests {
   416  		d := Self
   417  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   418  			t.Errorf("%d:%s: was %q; want %q", i, tt.tag, n, tt.name)
   419  		}
   420  	}
   421  }