blob: 355a33a70c2349be9ca108ca9cd1f3cd658b3b52 [file] [log] [blame]
// 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 number
import (
"fmt"
"log"
"strings"
"testing"
"golang.org/x/text/language"
)
func TestAppendDecimal(t *testing.T) {
type pairs map[string]string // alternates with decimal input and result
testCases := []struct {
pattern string
// We want to be able to test some forms of patterns that cannot be
// represented as a string.
pat *Pattern
test pairs
}{{
pattern: "0",
test: pairs{
"0": "0",
"1": "1",
"-1": "-1",
".00": "0",
"10.": "10",
"12": "12",
"1.2": "1",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "+0",
test: pairs{
"0": "+0",
"1": "+1",
"-1": "-1",
".00": "+0",
"10.": "+10",
"12": "+12",
"1.2": "+1",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "0 +",
test: pairs{
"0": "0 +",
"1": "1 +",
"-1": "1 -",
".00": "0 +",
},
}, {
pattern: "0;0-",
test: pairs{
"-1": "1-",
},
}, {
pattern: "0000",
test: pairs{
"0": "0000",
"1": "0001",
"12": "0012",
"12345": "12345",
},
}, {
pattern: ".0",
test: pairs{
"0": ".0",
"1": "1.0",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#.0",
test: pairs{
"0": ".0",
},
}, {
pattern: "#.0#",
test: pairs{
"0": ".0",
"1": "1.0",
},
}, {
pattern: "0.0#",
test: pairs{
"0": "0.0",
},
}, {
pattern: "#0.###",
test: pairs{
"0": "0",
"1": "1",
"1.2": "1.2",
"1.2345": "1.234", // rounding should have been done earlier
"1234.5": "1234.5",
"1234.567": "1234.567",
},
}, {
pattern: "#0.######",
test: pairs{
"0": "0",
"1234.5678": "1234.5678",
"0.123456789": "0.123456",
"NaN": "NaN",
"Inf": "∞",
},
// Test separators.
}, {
pattern: "#,#.00",
test: pairs{
"100": "1,0,0.00",
},
}, {
pattern: "#,0.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,0",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,##,#.00",
test: pairs{
"1000": "1,00,0.00",
},
}, {
pattern: "#,##0.###",
test: pairs{
"0": "0",
"1234.5678": "1,234.567",
"0.123456789": "0.123",
},
}, {
pattern: "#,##,##0.###",
test: pairs{
"0": "0",
"123456789012": "1,23,45,67,89,012",
"0.123456789": "0.123",
},
// Support for ill-formed patterns.
}, {
pattern: "#",
test: pairs{
".00": "0",
"0": "0",
"1": "1",
"10.": "10",
},
}, {
pattern: ".#",
test: pairs{
"0": "0",
"1": "1",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#,#.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,#",
test: pairs{
"10": "1,0",
},
// Special patterns
}, {
pattern: "#,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
},
test: pairs{
"2017": "17",
},
}, {
pattern: "0,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 1,
},
test: pairs{
"2000": "0",
"2001": "1",
"2017": "17",
},
}, {
pattern: "00,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 2,
},
test: pairs{
"2000": "00",
"2001": "01",
"2017": "17",
},
}, {
pattern: "@@@@,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinSignificantDigits: 4,
},
test: pairs{
"2017": "17.00",
"2000": "0.000",
"2001": "1.000",
},
// Significant digits
}, {
pattern: "@@##",
test: pairs{
"1": "1.0",
"0.1": "0.10",
"123": "123",
"1234": "1234",
"12345": "12340",
},
}, {
pattern: "@@@@",
test: pairs{
"1": "1.000",
".1": "0.1000",
".001": "0.001000",
"123": "123.0",
"1234": "1234",
"12345": "12340", // rounding down
"NaN": "NaN",
"-Inf": "-∞",
},
// TODO: rounding
// {"@@@@": "23456": "23460"}, // rounding up
// TODO: padding
// Scientific and Engineering notation
}, {
pattern: "#E0",
test: pairs{
"0": "0E0",
"1": "1E0",
"123.456": "1E2",
},
}, {
pattern: "#E+0",
test: pairs{
"0": "0E+0",
"1000": "1E+3",
"1E100": "1E+100",
"1E-100": "1E-100",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "##0E00",
test: pairs{
"100": "100E00",
"12345": "10E03",
"123.456": "100E00",
},
}, {
pattern: "##0.###E00",
test: pairs{
"100": "100E00",
"12345": "12.34E03",
"123.456": "123.4E00",
},
}, {
pattern: "##0.000E00",
test: pairs{
"100": "100.0E00",
"12345": "12.34E03",
"123.456": "123.4E00",
},
}}
// TODO:
// "@@E0",
// "@###E00",
// "0.0%",
// "0.0‰",
// "#,##0.00¤",
// "#,##0.00 ¤;(#,##0.00 ¤)",
// // padding
// "*x#",
// "#*x",
// "*xpre#suf",
// "pre*x#suf",
// "pre#*xsuf",
// "pre#suf*x",
for _, tc := range testCases {
pat := tc.pat
if pat == nil {
var err error
if pat, err = ParsePattern(tc.pattern); err != nil {
log.Fatal(err)
}
}
f := &Formatter{
pat,
InfoFromTag(language.English),
RoundingContext{},
appendDecimal,
}
if strings.IndexByte(tc.pattern, 'E') != -1 {
f.f = appendScientific
}
for dec, want := range tc.test {
buf := make([]byte, 100)
t.Run(tc.pattern+"/"+dec, func(t *testing.T) {
dec := mkdec(dec)
buf = f.Format(buf[:0], &dec)
if got := string(buf); got != want {
t.Errorf("\n got %q\nwant %q", got, want)
}
})
}
}
}
func TestLocales(t *testing.T) {
testCases := []struct {
tag language.Tag
num string
want string
}{
{language.Make("en"), "123456.78", "123,456.78"},
{language.Make("de"), "123456.78", "123.456,78"},
{language.Make("de-CH"), "123456.78", "123'456.78"},
{language.Make("fr"), "123456.78", "123 456,78"},
{language.Make("bn"), "123456.78", "১,২৩,৪৫৬.৭৮"},
}
for _, tc := range testCases {
t.Run(fmt.Sprint(tc.tag, "/", tc.num), func(t *testing.T) {
f := &Formatter{
lookupFormat(tc.tag, tagToDecimal),
InfoFromTag(tc.tag),
RoundingContext{},
appendDecimal,
}
d := mkdec(tc.num)
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %q; want %q", got, tc.want)
}
})
}
}