mirror of
https://github.com/restic/restic.git
synced 2024-08-23 04:40:46 +02:00
Among others, this updates minio-go, so that the new "eu-west-3" zone for AWS is supported.
457 lines
11 KiB
Go
457 lines
11 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package cldrtree
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"io/ioutil"
|
|
"log"
|
|
"math/rand"
|
|
"path/filepath"
|
|
"reflect"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/text/internal/gen"
|
|
"golang.org/x/text/language"
|
|
"golang.org/x/text/unicode/cldr"
|
|
)
|
|
|
|
var genOutput = flag.Bool("gen", false, "generate output files")
|
|
|
|
func TestAliasRegexp(t *testing.T) {
|
|
testCases := []struct {
|
|
alias string
|
|
want []string
|
|
}{{
|
|
alias: "miscPatterns[@numberSystem='latn']",
|
|
want: []string{
|
|
"miscPatterns[@numberSystem='latn']",
|
|
"miscPatterns",
|
|
"[@numberSystem='latn']",
|
|
"numberSystem",
|
|
"latn",
|
|
},
|
|
}, {
|
|
alias: `calendar[@type='greg-foo']/days/`,
|
|
want: []string{
|
|
"calendar[@type='greg-foo']",
|
|
"calendar",
|
|
"[@type='greg-foo']",
|
|
"type",
|
|
"greg-foo",
|
|
},
|
|
}, {
|
|
alias: "eraAbbr",
|
|
want: []string{
|
|
"eraAbbr",
|
|
"eraAbbr",
|
|
"",
|
|
"",
|
|
"",
|
|
},
|
|
}, {
|
|
// match must be anchored at beginning.
|
|
alias: `../calendar[@type='gregorian']/days/`,
|
|
}}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.alias, func(t *testing.T) {
|
|
got := aliasRe.FindStringSubmatch(tc.alias)
|
|
if !reflect.DeepEqual(got, tc.want) {
|
|
t.Errorf("got %v; want %v", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuild(t *testing.T) {
|
|
tree1, _ := loadTestdata(t, "test1")
|
|
tree2, _ := loadTestdata(t, "test2")
|
|
|
|
// Constants for second test test
|
|
const (
|
|
calendar = iota
|
|
field
|
|
)
|
|
const (
|
|
month = iota
|
|
era
|
|
filler
|
|
cyclicNameSet
|
|
)
|
|
const (
|
|
abbreviated = iota
|
|
narrow
|
|
wide
|
|
)
|
|
|
|
testCases := []struct {
|
|
desc string
|
|
tree *Tree
|
|
locale string
|
|
path []uint16
|
|
isFeature bool
|
|
result string
|
|
}{{
|
|
desc: "und/chinese month format wide m1",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, wide, 1),
|
|
result: "cM01",
|
|
}, {
|
|
desc: "und/chinese month format wide m12",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, wide, 12),
|
|
result: "cM12",
|
|
}, {
|
|
desc: "und/non-existing value",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, wide, 13),
|
|
result: "",
|
|
}, {
|
|
desc: "und/dangi:chinese month format wide",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 1, month, 0, wide, 1),
|
|
result: "cM01",
|
|
}, {
|
|
desc: "und/chinese month format abbreviated:wide",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, abbreviated, 1),
|
|
result: "cM01",
|
|
}, {
|
|
desc: "und/chinese month format narrow:wide",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, narrow, 1),
|
|
result: "cM01",
|
|
}, {
|
|
desc: "und/gregorian month format wide",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 2, month, 0, wide, 2),
|
|
result: "gM02",
|
|
}, {
|
|
desc: "und/gregorian month format:stand-alone narrow",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 2, month, 0, narrow, 1),
|
|
result: "1",
|
|
}, {
|
|
desc: "und/gregorian month stand-alone:format abbreviated",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 2, month, 1, abbreviated, 1),
|
|
result: "gM01",
|
|
}, {
|
|
desc: "und/gregorian month stand-alone:format wide ",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 2, month, 1, abbreviated, 1),
|
|
result: "gM01",
|
|
}, {
|
|
desc: "und/dangi:chinese month format narrow:wide ",
|
|
tree: tree1,
|
|
locale: "und",
|
|
path: path(calendar, 1, month, 0, narrow, 4),
|
|
result: "cM04",
|
|
}, {
|
|
desc: "und/field era displayname 0",
|
|
tree: tree2,
|
|
locale: "und",
|
|
path: path(field, 0, 0, 0),
|
|
result: "Era",
|
|
}, {
|
|
desc: "en/field era displayname 0",
|
|
tree: tree2,
|
|
locale: "en",
|
|
path: path(field, 0, 0, 0),
|
|
result: "era",
|
|
}, {
|
|
desc: "und/calendar hebrew format wide 7-leap",
|
|
tree: tree2,
|
|
locale: "und",
|
|
path: path(calendar, 7, month, 0, wide, 0),
|
|
result: "Adar II",
|
|
}, {
|
|
desc: "en-GB:en-001:en:und/calendar hebrew format wide 7-leap",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 7, month, 0, wide, 0),
|
|
result: "Adar II",
|
|
}, {
|
|
desc: "und/buddhist month format wide 11",
|
|
tree: tree2,
|
|
locale: "und",
|
|
path: path(calendar, 0, month, 0, wide, 12),
|
|
result: "genWideM12",
|
|
}, {
|
|
desc: "en-GB/gregorian month stand-alone narrow 2",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, month, 1, narrow, 3),
|
|
result: "gbNarrowM3",
|
|
}, {
|
|
desc: "en-GB/gregorian month format narrow 3/missing in en-GB",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, month, 0, narrow, 4),
|
|
result: "enNarrowM4",
|
|
}, {
|
|
desc: "en-GB/gregorian month format narrow 3/missing in en and en-GB",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, month, 0, narrow, 7),
|
|
result: "gregNarrowM7",
|
|
}, {
|
|
desc: "en-GB/gregorian month format narrow 3/missing in en and en-GB",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, month, 0, narrow, 7),
|
|
result: "gregNarrowM7",
|
|
}, {
|
|
desc: "en-GB/gregorian era narrow",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, era, abbreviated, 0, 1),
|
|
isFeature: true,
|
|
result: "AD",
|
|
}, {
|
|
desc: "en-GB/gregorian era narrow",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, era, narrow, 0, 0),
|
|
isFeature: true,
|
|
result: "BC",
|
|
}, {
|
|
desc: "en-GB/gregorian era narrow",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 6, era, wide, 1, 0),
|
|
isFeature: true,
|
|
result: "Before Common Era",
|
|
}, {
|
|
desc: "en-GB/dangi:chinese cyclicName, months, format, narrow:abbreviated 2",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(calendar, 1, cyclicNameSet, 3, 0, 1, 2),
|
|
isFeature: true,
|
|
result: "year2",
|
|
}, {
|
|
desc: "en-GB/field era-narrow ",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(field, 2, 0, 0),
|
|
result: "era",
|
|
}, {
|
|
desc: "en-GB/field month-narrow relativeTime future one",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(field, 5, 2, 0, 1),
|
|
isFeature: true,
|
|
result: "001NarrowFutMOne",
|
|
}, {
|
|
// Don't fall back to the one of "en".
|
|
desc: "en-GB/field month-short relativeTime past one:other",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(field, 4, 2, 1, 1),
|
|
isFeature: true,
|
|
result: "001ShortPastMOther",
|
|
}, {
|
|
desc: "en-GB/field month relativeTime future two:other",
|
|
tree: tree2,
|
|
locale: "en-GB",
|
|
path: path(field, 3, 2, 0, 2),
|
|
isFeature: true,
|
|
result: "enFutMOther",
|
|
}}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
tag, _ := language.CompactIndex(language.MustParse(tc.locale))
|
|
s := tc.tree.lookup(tag, tc.isFeature, tc.path...)
|
|
if s != tc.result {
|
|
t.Errorf("got %q; want %q", s, tc.result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func path(e ...uint16) []uint16 { return e }
|
|
|
|
func TestGen(t *testing.T) {
|
|
testCases := []string{"test1", "test2"}
|
|
for _, tc := range testCases {
|
|
t.Run(tc, func(t *testing.T) {
|
|
_, got := loadTestdata(t, tc)
|
|
|
|
// Remove sizes that may vary per architecture.
|
|
re := regexp.MustCompile("// Size: [0-9]*")
|
|
got = re.ReplaceAllLiteral(got, []byte("// Size: xxxx"))
|
|
re = regexp.MustCompile("// Total table size [0-9]*")
|
|
got = re.ReplaceAllLiteral(got, []byte("// Total table size: xxxx"))
|
|
|
|
file := filepath.Join("testdata", tc, "output.go")
|
|
if *genOutput {
|
|
ioutil.WriteFile(file, got, 0700)
|
|
t.SkipNow()
|
|
}
|
|
|
|
b, err := ioutil.ReadFile(file)
|
|
if err != nil {
|
|
t.Fatalf("failed to open file: %v", err)
|
|
}
|
|
if want := string(b); string(got) != want {
|
|
t.Log(string(got))
|
|
t.Errorf("files differ")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func loadTestdata(t *testing.T, test string) (tree *Tree, file []byte) {
|
|
b := New("test")
|
|
|
|
var d cldr.Decoder
|
|
|
|
data, err := d.DecodePath(filepath.Join("testdata", test))
|
|
if err != nil {
|
|
t.Fatalf("error decoding testdata: %v", err)
|
|
}
|
|
|
|
context := Enum("context")
|
|
widthMap := func(s string) string {
|
|
// Align era with width values.
|
|
if r, ok := map[string]string{
|
|
"eraAbbr": "abbreviated",
|
|
"eraNarrow": "narrow",
|
|
"eraNames": "wide",
|
|
}[s]; ok {
|
|
s = r
|
|
}
|
|
return "w" + strings.Title(s)
|
|
}
|
|
width := EnumFunc("width", widthMap, "abbreviated", "narrow", "wide")
|
|
month := Enum("month", "leap7")
|
|
relative := EnumFunc("relative", func(s string) string {
|
|
x, err := strconv.ParseInt(s, 10, 8)
|
|
if err != nil {
|
|
log.Fatal("Invalid number:", err)
|
|
}
|
|
return []string{
|
|
"before1",
|
|
"current",
|
|
"after1",
|
|
}[x+1]
|
|
})
|
|
cycleType := EnumFunc("cycleType", func(s string) string {
|
|
return "cyc" + strings.Title(s)
|
|
})
|
|
r := rand.New(rand.NewSource(0))
|
|
|
|
for _, loc := range data.Locales() {
|
|
ldml := data.RawLDML(loc)
|
|
x := b.Locale(language.Make(loc))
|
|
|
|
if x := x.Index(ldml.Dates.Calendars); x != nil {
|
|
for _, cal := range ldml.Dates.Calendars.Calendar {
|
|
x := x.IndexFromType(cal)
|
|
if x := x.Index(cal.Months); x != nil {
|
|
for _, mc := range cal.Months.MonthContext {
|
|
x := x.IndexFromType(mc, context)
|
|
for _, mw := range mc.MonthWidth {
|
|
x := x.IndexFromType(mw, width)
|
|
for _, m := range mw.Month {
|
|
x.SetValue(m.Yeartype+m.Type, m, month)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if x := x.Index(cal.CyclicNameSets); x != nil {
|
|
for _, cns := range cal.CyclicNameSets.CyclicNameSet {
|
|
x := x.IndexFromType(cns, cycleType)
|
|
for _, cc := range cns.CyclicNameContext {
|
|
x := x.IndexFromType(cc, context)
|
|
for _, cw := range cc.CyclicNameWidth {
|
|
x := x.IndexFromType(cw, width)
|
|
for _, c := range cw.CyclicName {
|
|
x.SetValue(c.Type, c)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if x := x.Index(cal.Eras); x != nil {
|
|
opts := []Option{width, SharedType()}
|
|
if x := x.Index(cal.Eras.EraNames, opts...); x != nil {
|
|
for _, e := range cal.Eras.EraNames.Era {
|
|
x.IndexFromAlt(e).SetValue(e.Type, e)
|
|
}
|
|
}
|
|
if x := x.Index(cal.Eras.EraAbbr, opts...); x != nil {
|
|
for _, e := range cal.Eras.EraAbbr.Era {
|
|
x.IndexFromAlt(e).SetValue(e.Type, e)
|
|
}
|
|
}
|
|
if x := x.Index(cal.Eras.EraNarrow, opts...); x != nil {
|
|
for _, e := range cal.Eras.EraNarrow.Era {
|
|
x.IndexFromAlt(e).SetValue(e.Type, e)
|
|
}
|
|
}
|
|
}
|
|
{
|
|
// Ensure having more than 2 buckets.
|
|
f := x.IndexWithName("filler")
|
|
b := make([]byte, maxStrlen)
|
|
opt := &options{parent: x}
|
|
r.Read(b)
|
|
f.setValue("0", string(b), opt)
|
|
}
|
|
}
|
|
}
|
|
if x := x.Index(ldml.Dates.Fields); x != nil {
|
|
for _, f := range ldml.Dates.Fields.Field {
|
|
x := x.IndexFromType(f)
|
|
for _, d := range f.DisplayName {
|
|
x.Index(d).SetValue("", d)
|
|
}
|
|
for _, r := range f.Relative {
|
|
x.Index(r).SetValue(r.Type, r, relative)
|
|
}
|
|
for _, rt := range f.RelativeTime {
|
|
x := x.Index(rt).IndexFromType(rt)
|
|
for _, p := range rt.RelativeTimePattern {
|
|
x.SetValue(p.Count, p)
|
|
}
|
|
}
|
|
for _, rp := range f.RelativePeriod {
|
|
x.Index(rp).SetValue("", rp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tree, err = build(b)
|
|
if err != nil {
|
|
t.Fatal("error building tree:", err)
|
|
}
|
|
w := gen.NewCodeWriter()
|
|
generate(b, tree, w)
|
|
generateTestData(b, w)
|
|
buf := &bytes.Buffer{}
|
|
if _, err = w.WriteGo(buf, "test", ""); err != nil {
|
|
t.Log(buf.String())
|
|
t.Fatal("error generating code:", err)
|
|
}
|
|
return tree, buf.Bytes()
|
|
}
|