blob: 5386ea006c83141f63ca6caaa4c7f52d117dc9e8 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Binary i18n_test tests message catalogues.
package i18n
import "strings"
import "testing"
import (
"fmt"
"v.io/v23/context"
)
// testLookupSetAndRemove tests Lookup, Set, and Set-to-empty on *cat.
func testLookupSetAndRemove(t *testing.T, cat *Catalogue, catName string) {
want := "expected format"
expectLookup(t, cat, "", "en", "bar", catName+" 1")
expectLookup(t, cat, "", "en-US", "bar", catName+" 2")
expectLookup(t, cat, "", "en", "foo", catName+" 3")
expectLookup(t, cat, "", "en-US", "foo", catName+" 4")
if cat.Set(LangID("en-US"), MsgID("bar"), want) != "" {
t.Errorf("Set found en-US/bar in %s catalogue", catName)
}
if cat.SetWithBase(LangID("en-US"), MsgID("foo"), want) != "" {
t.Errorf("Set found en-US/foo in %s catalogue", catName)
}
expectLookup(t, cat, "", "en", "bar", catName+" 5")
expectLookup(t, cat, want, "en-US", "bar", catName+" 6")
expectLookup(t, cat, want, "en", "foo", catName+" 7")
expectLookup(t, cat, want, "en-US", "foo", catName+" 8")
// Check that Set(..., "") doesn't delete the base entry.
if cat.Set(LangID("en"), MsgID("bar"), "other format") != "" {
t.Errorf("Set found en/bar in %s catalogue", catName)
}
if cat.Set(LangID("en-US"), MsgID("bar"), "") != want {
t.Errorf("Set didn't find en-US/bar in %s catalogue", catName)
}
if cat.SetWithBase(LangID("en-US"), MsgID("foo"), "") != want {
t.Errorf("Set didn't find en-US/foo in %s catalogue", catName)
}
// The previous SetWithBase will not have removed the base entry.
if cat.Set(LangID("en"), MsgID("foo"), "") != want {
t.Errorf("Set didn't find en/foo in %s catalogue", catName)
}
expectLookup(t, cat, "other format", "en", "bar", catName+" 9")
// Test that a lookup of en-US finds the "en" entry.
expectLookup(t, cat, "other format", "en-US", "bar", catName+" 10")
if cat.Set(LangID("en"), MsgID("bar"), "") != "other format" {
t.Errorf("Set didn't find en/bar in %s catalogue", catName)
}
expectLookup(t, cat, "", "en", "bar", catName+" 11")
expectLookup(t, cat, "", "en-US", "bar", catName+" 12")
expectLookup(t, cat, "", "en", "foo", catName+" 13")
expectLookup(t, cat, "", "en-US", "foo", catName+" 14")
}
// testLookupSetAndRemove tests Lookup, Set, and Set-to-empty on
// a newly created catalogue.
func TestLookupSetAndRemove(t *testing.T) {
testLookupSetAndRemove(t, new(Catalogue), "new")
}
// TestDefaultCatalogue verifies that the default Catalogue behaves like a
// catalogue and is the same whenever it's invoked.
func TestDefaultCatalogue(t *testing.T) {
cat := Cat()
if cat != Cat() {
t.Errorf("got different default Catalogue")
}
testLookupSetAndRemove(t, cat, "default")
if cat != Cat() {
t.Errorf("got different default Catalogue")
}
}
// expectFormatParams verifies that FormatParams(format, v...) generates
// want.
func expectFormatParams(t *testing.T, want string, format string, v ...interface{}) {
got := FormatParams(format, v...)
if want != got {
t.Errorf("FormatParams(%q, %v): got %q, want %q", format, v, got, want)
}
}
// TestFormatParams tests the FormatParams() call with various arguments
func TestFormatParams(t *testing.T) {
expectFormatParams(t, "", "", "1st")
expectFormatParams(t, "", "{_}")
expectFormatParams(t, "? ? ? ? ? ?", "{0} {1} {2} {3} {4} {5}")
expectFormatParams(t, "{ foo }?", "{ foo }{2}")
expectFormatParams(t, "3rd: foo 2nd bar 1st 4th (3rd)",
"{3}: foo {2} bar {_} ({3})", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, "?: foo 4th ?",
"{0}: foo {4} {5}", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, " foo 1st 2nd 3rd 4th{-1}",
"{_} foo {_}{-1}", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, "{ foo }2nd",
"{ foo }{2}", "1st", "2nd", "3rd", "4th")
// Test the formatting of colon-formats.
expectFormatParams(t, "", "{:_}")
expectFormatParams(t, "", "{_:}")
expectFormatParams(t, "", "{:_:}")
expectFormatParams(t, ": 1st 2nd", "{:_}", "1st", "2nd")
expectFormatParams(t, "1st 2nd:", "{_:}", "1st", "2nd")
expectFormatParams(t, ": 1st 2nd:", "{:_:}", "1st", "2nd")
expectFormatParams(t, "", "{:_}", "")
expectFormatParams(t, "", "{_:}", "")
expectFormatParams(t, "", "{:_:}", "")
expectFormatParams(t, ": 1st", "{:1}", "1st")
expectFormatParams(t, "1st:", "{1:}", "1st")
expectFormatParams(t, ": 1st:", "{:1:}", "1st")
expectFormatParams(t, "", "{:1}", "")
expectFormatParams(t, "", "{1:}", "")
expectFormatParams(t, "", "{:1:}", "")
expectFormatParams(t, "?: ? ?: ?: ?: ?", "{0}{:1} {2:} {3}{:4:} {5}")
expectFormatParams(t, "{: foo }?", "{: foo }{2}")
expectFormatParams(t, "{ foo :}?", "{ foo :}{2}")
expectFormatParams(t, "{: foo :}?", "{: foo :}{2}")
expectFormatParams(t, "3rd: foo 2nd bar: 1st 4th (3rd)",
"{3:} foo {2} bar{:_} ({3})", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, "?: foo: 4th ?",
"{0:} foo{:4} {5}", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, " foo: 1st 2nd 3rd 4th{-1}",
"{_:} foo{:_}{-1}", "1st", "2nd", "3rd", "4th")
expectFormatParams(t, "{ foo }: 2nd",
"{4:}{ foo }{:2}", "1st", "2nd", "3rd", "")
expectFormatParams(t, "1st foo 2nd: bar: 3rd wombat: 4th: numbat",
"{1} foo {2:} bar{:3} wombat{:4:} numbat",
"1st", "2nd", "3rd", "4th")
expectFormatParams(t, " foo bar wombat numbat",
"{1} foo {2:} bar{:3} wombat{:4:} numbat",
"", "", "", "")
expectFormatParams(t, "3: foo 2 bar 1 4 (3)",
"{3}: foo {2} bar {_} ({3})", 1, 2, 3, 4)
expectFormatParams(t, "2: error1",
"{2}: {1}", fmt.Errorf("error1"), 2)
}
var mergeData string = `# In what follows we use the "languages" "fwd" and "back".
fwd foo "{1} foo to {2}"
# Next line has a missing trailing double quote, so will be ignored.
back foo "{2} from foo {1}
# Comment "quote"
# The following two lines are ignored, since each has fewer than three tokens.
one
one two
fwd bar "{1} bar to {2}"
back bar "{2} from bar {1}" extraneous word
back funny.msg.id "{2} from funny msg id {1}"
odd.lang.id funny.msg.id "odd and\b \"funny\""
`
// expectLookup verifies that cat.Lookup(lang, msg)==want
func expectLookup(t *testing.T, cat *Catalogue, want string,
lang string, msg string, tag string) {
got := cat.Lookup(LangID(lang), MsgID(msg))
if want != got {
t.Errorf("%s: cat.Lookup(%s, %s): got %q, want %q",
tag, lang, msg, got, want)
}
}
// expectInMap verifies that m[s]==true.
func expectInMap(t *testing.T, m map[string]bool, s string) {
if !m[s] {
t.Errorf("m[%#v]==false; want true", s)
}
}
// A writableString can be appended to via the Writer interface.
type writeableString struct {
s string
}
// Write writes p to the the target string.
func (ws *writeableString) Write(p []byte) (n int, err error) {
ws.s += string(p)
return len(p), nil
}
// TestMerge tests the Merge() call.
func TestMergeAndOutput(t *testing.T) {
cat := new(Catalogue)
// Check that Merge() works.
cat.Merge(strings.NewReader(mergeData))
expectLookup(t, cat, "{1} foo to {2}", "fwd", "foo", "1")
expectLookup(t, cat, "", "back", "foo", "2")
expectLookup(t, cat, "{1} bar to {2}", "fwd", "bar", "3")
expectLookup(t, cat, "{2} from bar {1}", "back", "bar", "4")
expectLookup(t, cat, "{2} from funny msg id {1}", "back", "funny.msg.id", "5")
expectLookup(t, cat, "odd and\b \"funny\"", "odd.lang.id", "funny.msg.id", "6")
// Verify that the result of Output is as expected.
var ws writeableString
err := cat.Output(&ws)
if err != nil {
t.Errorf("error from cat.Output(): %v", err)
}
m := make(map[string]bool)
for _, line := range strings.Split(ws.s, "\n") {
if line != "" {
m[line] = true
}
}
expectInMap(t, m, "fwd foo \"{1} foo to {2}\"")
expectInMap(t, m, "fwd bar \"{1} bar to {2}\"")
expectInMap(t, m, "back bar \"{2} from bar {1}\"")
expectInMap(t, m, "back funny.msg.id \"{2} from funny msg id {1}\"")
expectInMap(t, m, "odd.lang.id funny.msg.id \"odd and\\b \\\"funny\\\"\"")
if want := 5; len(m) != want {
t.Errorf("wrong number of lines in <%s>; got %d, want %d ", ws.s, len(m), want)
}
}
// expectNormalizeLangID verifies that NormalizeLangID(input)==want.
func expectNormalizeLangID(t *testing.T, input string, want LangID) {
got := NormalizeLangID(input)
if got != want {
t.Errorf("NormalizeLangID(%s) got %q, want %q", input, got, want)
}
}
// TestNormalizeLangID tests NormalizeLangID().
func TestNormalizeLangID(t *testing.T) {
expectNormalizeLangID(t, "en", "en")
expectNormalizeLangID(t, "en-US", "en-US")
expectNormalizeLangID(t, "en_US", "en-US")
}
// expectBaseLangID verifies that BaseLangID(input)==want.
func expectBaseLangID(t *testing.T, input LangID, want LangID) {
got := BaseLangID(input)
if got != want {
t.Errorf("BaseLangID(%s) got %q, want %q", input, got, want)
}
}
// TestBaseLangID tests BaseLangID().
func TestBaseLangID(t *testing.T) {
expectBaseLangID(t, "en", "en")
expectBaseLangID(t, "en-US", "en")
}
func testContext() *context.T {
ctx, _ := context.RootContext()
return ctx
}
// TestGetWithLangID tests GetLangID() and WithLangID.
func TestGetWithLangID(t *testing.T) {
var dcWithoutLangID *context.T = testContext()
dcWithEN := WithLangID(dcWithoutLangID, "en")
dcWithFR := WithLangID(dcWithEN, "fr")
var got LangID
got = GetLangID(dcWithoutLangID)
if got != NoLangID {
t.Errorf("GetLangID(dcWithoutLangID); got %v, want \"\"", got)
}
got = GetLangID(dcWithEN)
if got != LangID("en") {
t.Errorf("GetLangID(dcWithEN); got %v, want \"en\"", got)
}
got = GetLangID(dcWithFR)
if got != LangID("fr") {
t.Errorf("GetLangID(dcWithFR); got %v, want \"fr\"", got)
}
}