github.com/go-xe2/third@v1.0.3/golang.org/x/text/internal/cldrtree/cldrtree_test.go (about)

     1  // Copyright 2017 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 cldrtree
     6  
     7  import (
     8  	"bytes"
     9  	"flag"
    10  	"io/ioutil"
    11  	"log"
    12  	"math/rand"
    13  	"path/filepath"
    14  	"reflect"
    15  	"regexp"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/go-xe2/third/golang.org/x/text/internal/gen"
    21  	"github.com/go-xe2/third/golang.org/x/text/language"
    22  	"github.com/go-xe2/third/golang.org/x/text/unicode/cldr"
    23  )
    24  
    25  var genOutput = flag.Bool("gen", false, "generate output files")
    26  
    27  func TestAliasRegexp(t *testing.T) {
    28  	testCases := []struct {
    29  		alias string
    30  		want  []string
    31  	}{{
    32  		alias: "miscPatterns[@numberSystem='latn']",
    33  		want: []string{
    34  			"miscPatterns[@numberSystem='latn']",
    35  			"miscPatterns",
    36  			"[@numberSystem='latn']",
    37  			"numberSystem",
    38  			"latn",
    39  		},
    40  	}, {
    41  		alias: `calendar[@type='greg-foo']/days/`,
    42  		want: []string{
    43  			"calendar[@type='greg-foo']",
    44  			"calendar",
    45  			"[@type='greg-foo']",
    46  			"type",
    47  			"greg-foo",
    48  		},
    49  	}, {
    50  		alias: "eraAbbr",
    51  		want: []string{
    52  			"eraAbbr",
    53  			"eraAbbr",
    54  			"",
    55  			"",
    56  			"",
    57  		},
    58  	}, {
    59  		// match must be anchored at beginning.
    60  		alias: `../calendar[@type='gregorian']/days/`,
    61  	}}
    62  	for _, tc := range testCases {
    63  		t.Run(tc.alias, func(t *testing.T) {
    64  			got := aliasRe.FindStringSubmatch(tc.alias)
    65  			if !reflect.DeepEqual(got, tc.want) {
    66  				t.Errorf("got %v; want %v", got, tc.want)
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  func TestBuild(t *testing.T) {
    73  	tree1, _ := loadTestdata(t, "test1")
    74  	tree2, _ := loadTestdata(t, "test2")
    75  
    76  	// Constants for second test test
    77  	const (
    78  		calendar = iota
    79  		field
    80  	)
    81  	const (
    82  		month = iota
    83  		era
    84  		filler
    85  		cyclicNameSet
    86  	)
    87  	const (
    88  		abbreviated = iota
    89  		narrow
    90  		wide
    91  	)
    92  
    93  	testCases := []struct {
    94  		desc      string
    95  		tree      *Tree
    96  		locale    string
    97  		path      []uint16
    98  		isFeature bool
    99  		result    string
   100  	}{{
   101  		desc:   "und/chinese month format wide m1",
   102  		tree:   tree1,
   103  		locale: "und",
   104  		path:   path(calendar, 0, month, 0, wide, 1),
   105  		result: "cM01",
   106  	}, {
   107  		desc:   "und/chinese month format wide m12",
   108  		tree:   tree1,
   109  		locale: "und",
   110  		path:   path(calendar, 0, month, 0, wide, 12),
   111  		result: "cM12",
   112  	}, {
   113  		desc:   "und/non-existing value",
   114  		tree:   tree1,
   115  		locale: "und",
   116  		path:   path(calendar, 0, month, 0, wide, 13),
   117  		result: "",
   118  	}, {
   119  		desc:   "und/dangi:chinese month format wide",
   120  		tree:   tree1,
   121  		locale: "und",
   122  		path:   path(calendar, 1, month, 0, wide, 1),
   123  		result: "cM01",
   124  	}, {
   125  		desc:   "und/chinese month format abbreviated:wide",
   126  		tree:   tree1,
   127  		locale: "und",
   128  		path:   path(calendar, 0, month, 0, abbreviated, 1),
   129  		result: "cM01",
   130  	}, {
   131  		desc:   "und/chinese month format narrow:wide",
   132  		tree:   tree1,
   133  		locale: "und",
   134  		path:   path(calendar, 0, month, 0, narrow, 1),
   135  		result: "cM01",
   136  	}, {
   137  		desc:   "und/gregorian month format wide",
   138  		tree:   tree1,
   139  		locale: "und",
   140  		path:   path(calendar, 2, month, 0, wide, 2),
   141  		result: "gM02",
   142  	}, {
   143  		desc:   "und/gregorian month format:stand-alone narrow",
   144  		tree:   tree1,
   145  		locale: "und",
   146  		path:   path(calendar, 2, month, 0, narrow, 1),
   147  		result: "1",
   148  	}, {
   149  		desc:   "und/gregorian month stand-alone:format abbreviated",
   150  		tree:   tree1,
   151  		locale: "und",
   152  		path:   path(calendar, 2, month, 1, abbreviated, 1),
   153  		result: "gM01",
   154  	}, {
   155  		desc:   "und/gregorian month stand-alone:format wide ",
   156  		tree:   tree1,
   157  		locale: "und",
   158  		path:   path(calendar, 2, month, 1, abbreviated, 1),
   159  		result: "gM01",
   160  	}, {
   161  		desc:   "und/dangi:chinese month format narrow:wide ",
   162  		tree:   tree1,
   163  		locale: "und",
   164  		path:   path(calendar, 1, month, 0, narrow, 4),
   165  		result: "cM04",
   166  	}, {
   167  		desc:   "und/field era displayname 0",
   168  		tree:   tree2,
   169  		locale: "und",
   170  		path:   path(field, 0, 0, 0),
   171  		result: "Era",
   172  	}, {
   173  		desc:   "en/field era displayname 0",
   174  		tree:   tree2,
   175  		locale: "en",
   176  		path:   path(field, 0, 0, 0),
   177  		result: "era",
   178  	}, {
   179  		desc:   "und/calendar hebrew format wide 7-leap",
   180  		tree:   tree2,
   181  		locale: "und",
   182  		path:   path(calendar, 7, month, 0, wide, 0),
   183  		result: "Adar II",
   184  	}, {
   185  		desc:   "en-GB:en-001:en:und/calendar hebrew format wide 7-leap",
   186  		tree:   tree2,
   187  		locale: "en-GB",
   188  		path:   path(calendar, 7, month, 0, wide, 0),
   189  		result: "Adar II",
   190  	}, {
   191  		desc:   "und/buddhist month format wide 11",
   192  		tree:   tree2,
   193  		locale: "und",
   194  		path:   path(calendar, 0, month, 0, wide, 12),
   195  		result: "genWideM12",
   196  	}, {
   197  		desc:   "en-GB/gregorian month stand-alone narrow 2",
   198  		tree:   tree2,
   199  		locale: "en-GB",
   200  		path:   path(calendar, 6, month, 1, narrow, 3),
   201  		result: "gbNarrowM3",
   202  	}, {
   203  		desc:   "en-GB/gregorian month format narrow 3/missing in en-GB",
   204  		tree:   tree2,
   205  		locale: "en-GB",
   206  		path:   path(calendar, 6, month, 0, narrow, 4),
   207  		result: "enNarrowM4",
   208  	}, {
   209  		desc:   "en-GB/gregorian month format narrow 3/missing in en and en-GB",
   210  		tree:   tree2,
   211  		locale: "en-GB",
   212  		path:   path(calendar, 6, month, 0, narrow, 7),
   213  		result: "gregNarrowM7",
   214  	}, {
   215  		desc:   "en-GB/gregorian month format narrow 3/missing in en and en-GB",
   216  		tree:   tree2,
   217  		locale: "en-GB",
   218  		path:   path(calendar, 6, month, 0, narrow, 7),
   219  		result: "gregNarrowM7",
   220  	}, {
   221  		desc:      "en-GB/gregorian era narrow",
   222  		tree:      tree2,
   223  		locale:    "en-GB",
   224  		path:      path(calendar, 6, era, abbreviated, 0, 1),
   225  		isFeature: true,
   226  		result:    "AD",
   227  	}, {
   228  		desc:      "en-GB/gregorian era narrow",
   229  		tree:      tree2,
   230  		locale:    "en-GB",
   231  		path:      path(calendar, 6, era, narrow, 0, 0),
   232  		isFeature: true,
   233  		result:    "BC",
   234  	}, {
   235  		desc:      "en-GB/gregorian era narrow",
   236  		tree:      tree2,
   237  		locale:    "en-GB",
   238  		path:      path(calendar, 6, era, wide, 1, 0),
   239  		isFeature: true,
   240  		result:    "Before Common Era",
   241  	}, {
   242  		desc:      "en-GB/dangi:chinese cyclicName, months, format, narrow:abbreviated 2",
   243  		tree:      tree2,
   244  		locale:    "en-GB",
   245  		path:      path(calendar, 1, cyclicNameSet, 3, 0, 1, 2),
   246  		isFeature: true,
   247  		result:    "year2",
   248  	}, {
   249  		desc:   "en-GB/field era-narrow ",
   250  		tree:   tree2,
   251  		locale: "en-GB",
   252  		path:   path(field, 2, 0, 0),
   253  		result: "era",
   254  	}, {
   255  		desc:      "en-GB/field month-narrow relativeTime future one",
   256  		tree:      tree2,
   257  		locale:    "en-GB",
   258  		path:      path(field, 5, 2, 0, 1),
   259  		isFeature: true,
   260  		result:    "001NarrowFutMOne",
   261  	}, {
   262  		// Don't fall back to the one of "en".
   263  		desc:      "en-GB/field month-short relativeTime past one:other",
   264  		tree:      tree2,
   265  		locale:    "en-GB",
   266  		path:      path(field, 4, 2, 1, 1),
   267  		isFeature: true,
   268  		result:    "001ShortPastMOther",
   269  	}, {
   270  		desc:      "en-GB/field month relativeTime future two:other",
   271  		tree:      tree2,
   272  		locale:    "en-GB",
   273  		path:      path(field, 3, 2, 0, 2),
   274  		isFeature: true,
   275  		result:    "enFutMOther",
   276  	}}
   277  
   278  	for _, tc := range testCases {
   279  		t.Run(tc.desc, func(t *testing.T) {
   280  			tag, _ := language.CompactIndex(language.MustParse(tc.locale))
   281  			s := tc.tree.lookup(tag, tc.isFeature, tc.path...)
   282  			if s != tc.result {
   283  				t.Errorf("got %q; want %q", s, tc.result)
   284  			}
   285  		})
   286  	}
   287  }
   288  
   289  func path(e ...uint16) []uint16 { return e }
   290  
   291  func TestGen(t *testing.T) {
   292  	testCases := []string{"test1", "test2"}
   293  	for _, tc := range testCases {
   294  		t.Run(tc, func(t *testing.T) {
   295  			_, got := loadTestdata(t, tc)
   296  
   297  			// Remove sizes that may vary per architecture.
   298  			re := regexp.MustCompile("// Size: [0-9]*")
   299  			got = re.ReplaceAllLiteral(got, []byte("// Size: xxxx"))
   300  			re = regexp.MustCompile("// Total table size [0-9]*")
   301  			got = re.ReplaceAllLiteral(got, []byte("// Total table size: xxxx"))
   302  
   303  			file := filepath.Join("testdata", tc, "output.go")
   304  			if *genOutput {
   305  				ioutil.WriteFile(file, got, 0700)
   306  				t.SkipNow()
   307  			}
   308  
   309  			b, err := ioutil.ReadFile(file)
   310  			if err != nil {
   311  				t.Fatalf("failed to open file: %v", err)
   312  			}
   313  			if want := string(b); string(got) != want {
   314  				t.Log(string(got))
   315  				t.Errorf("files differ")
   316  			}
   317  		})
   318  	}
   319  }
   320  
   321  func loadTestdata(t *testing.T, test string) (tree *Tree, file []byte) {
   322  	b := New("test")
   323  
   324  	var d cldr.Decoder
   325  
   326  	data, err := d.DecodePath(filepath.Join("testdata", test))
   327  	if err != nil {
   328  		t.Fatalf("error decoding testdata: %v", err)
   329  	}
   330  
   331  	context := Enum("context")
   332  	widthMap := func(s string) string {
   333  		// Align era with width values.
   334  		if r, ok := map[string]string{
   335  			"eraAbbr":   "abbreviated",
   336  			"eraNarrow": "narrow",
   337  			"eraNames":  "wide",
   338  		}[s]; ok {
   339  			s = r
   340  		}
   341  		return "w" + strings.Title(s)
   342  	}
   343  	width := EnumFunc("width", widthMap, "abbreviated", "narrow", "wide")
   344  	month := Enum("month", "leap7")
   345  	relative := EnumFunc("relative", func(s string) string {
   346  		x, err := strconv.ParseInt(s, 10, 8)
   347  		if err != nil {
   348  			log.Fatal("Invalid number:", err)
   349  		}
   350  		return []string{
   351  			"before1",
   352  			"current",
   353  			"after1",
   354  		}[x+1]
   355  	})
   356  	cycleType := EnumFunc("cycleType", func(s string) string {
   357  		return "cyc" + strings.Title(s)
   358  	})
   359  	r := rand.New(rand.NewSource(0))
   360  
   361  	for _, loc := range data.Locales() {
   362  		ldml := data.RawLDML(loc)
   363  		x := b.Locale(language.Make(loc))
   364  
   365  		if x := x.Index(ldml.Dates.Calendars); x != nil {
   366  			for _, cal := range ldml.Dates.Calendars.Calendar {
   367  				x := x.IndexFromType(cal)
   368  				if x := x.Index(cal.Months); x != nil {
   369  					for _, mc := range cal.Months.MonthContext {
   370  						x := x.IndexFromType(mc, context)
   371  						for _, mw := range mc.MonthWidth {
   372  							x := x.IndexFromType(mw, width)
   373  							for _, m := range mw.Month {
   374  								x.SetValue(m.Yeartype+m.Type, m, month)
   375  							}
   376  						}
   377  					}
   378  				}
   379  				if x := x.Index(cal.CyclicNameSets); x != nil {
   380  					for _, cns := range cal.CyclicNameSets.CyclicNameSet {
   381  						x := x.IndexFromType(cns, cycleType)
   382  						for _, cc := range cns.CyclicNameContext {
   383  							x := x.IndexFromType(cc, context)
   384  							for _, cw := range cc.CyclicNameWidth {
   385  								x := x.IndexFromType(cw, width)
   386  								for _, c := range cw.CyclicName {
   387  									x.SetValue(c.Type, c)
   388  								}
   389  							}
   390  						}
   391  					}
   392  				}
   393  				if x := x.Index(cal.Eras); x != nil {
   394  					opts := []Option{width, SharedType()}
   395  					if x := x.Index(cal.Eras.EraNames, opts...); x != nil {
   396  						for _, e := range cal.Eras.EraNames.Era {
   397  							x.IndexFromAlt(e).SetValue(e.Type, e)
   398  						}
   399  					}
   400  					if x := x.Index(cal.Eras.EraAbbr, opts...); x != nil {
   401  						for _, e := range cal.Eras.EraAbbr.Era {
   402  							x.IndexFromAlt(e).SetValue(e.Type, e)
   403  						}
   404  					}
   405  					if x := x.Index(cal.Eras.EraNarrow, opts...); x != nil {
   406  						for _, e := range cal.Eras.EraNarrow.Era {
   407  							x.IndexFromAlt(e).SetValue(e.Type, e)
   408  						}
   409  					}
   410  				}
   411  				{
   412  					// Ensure having more than 2 buckets.
   413  					f := x.IndexWithName("filler")
   414  					b := make([]byte, maxStrlen)
   415  					opt := &options{parent: x}
   416  					r.Read(b)
   417  					f.setValue("0", string(b), opt)
   418  				}
   419  			}
   420  		}
   421  		if x := x.Index(ldml.Dates.Fields); x != nil {
   422  			for _, f := range ldml.Dates.Fields.Field {
   423  				x := x.IndexFromType(f)
   424  				for _, d := range f.DisplayName {
   425  					x.Index(d).SetValue("", d)
   426  				}
   427  				for _, r := range f.Relative {
   428  					x.Index(r).SetValue(r.Type, r, relative)
   429  				}
   430  				for _, rt := range f.RelativeTime {
   431  					x := x.Index(rt).IndexFromType(rt)
   432  					for _, p := range rt.RelativeTimePattern {
   433  						x.SetValue(p.Count, p)
   434  					}
   435  				}
   436  				for _, rp := range f.RelativePeriod {
   437  					x.Index(rp).SetValue("", rp)
   438  				}
   439  			}
   440  		}
   441  	}
   442  
   443  	tree, err = build(b)
   444  	if err != nil {
   445  		t.Fatal("error building tree:", err)
   446  	}
   447  	w := gen.NewCodeWriter()
   448  	generate(b, tree, w)
   449  	generateTestData(b, w)
   450  	buf := &bytes.Buffer{}
   451  	if _, err = w.WriteGo(buf, "test"); err != nil {
   452  		t.Log(buf.String())
   453  		t.Fatal("error generating code:", err)
   454  	}
   455  	return tree, buf.Bytes()
   456  }