mirror of
https://github.com/miniflux/v2.git
synced 2024-08-31 00:27:24 +02:00
439 lines
7.7 KiB
Go
439 lines
7.7 KiB
Go
// Copyright 2015 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 (
|
|
"reflect"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
var testCases = []struct {
|
|
pat string
|
|
want *Pattern
|
|
}{{
|
|
"#",
|
|
&Pattern{
|
|
FormatWidth: 1,
|
|
// TODO: Should MinIntegerDigits be 1?
|
|
},
|
|
}, {
|
|
"0",
|
|
&Pattern{
|
|
FormatWidth: 1,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"+0",
|
|
&Pattern{
|
|
Affix: "\x01+\x00",
|
|
FormatWidth: 2,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"0+",
|
|
&Pattern{
|
|
Affix: "\x00\x01+",
|
|
FormatWidth: 2,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"0000",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 4,
|
|
},
|
|
},
|
|
}, {
|
|
".#",
|
|
&Pattern{
|
|
FormatWidth: 2,
|
|
RoundingContext: RoundingContext{
|
|
MaxFractionDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"#0.###",
|
|
&Pattern{
|
|
FormatWidth: 6,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 3,
|
|
},
|
|
},
|
|
}, {
|
|
"#0.######",
|
|
&Pattern{
|
|
FormatWidth: 9,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 6,
|
|
},
|
|
},
|
|
}, {
|
|
"#,0",
|
|
&Pattern{
|
|
FormatWidth: 3,
|
|
GroupingSize: [2]uint8{1, 0},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"#,0.00",
|
|
&Pattern{
|
|
FormatWidth: 6,
|
|
GroupingSize: [2]uint8{1, 0},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 2,
|
|
MaxFractionDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
"#,##0.###",
|
|
&Pattern{
|
|
FormatWidth: 9,
|
|
GroupingSize: [2]uint8{3, 0},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 3,
|
|
},
|
|
},
|
|
}, {
|
|
"#,##,##0.###",
|
|
&Pattern{
|
|
FormatWidth: 12,
|
|
GroupingSize: [2]uint8{3, 2},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 3,
|
|
},
|
|
},
|
|
}, {
|
|
// Ignore additional separators.
|
|
"#,####,##,##0.###",
|
|
&Pattern{
|
|
FormatWidth: 17,
|
|
GroupingSize: [2]uint8{3, 2},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 3,
|
|
},
|
|
},
|
|
}, {
|
|
"#E0",
|
|
&Pattern{
|
|
FormatWidth: 3,
|
|
RoundingContext: RoundingContext{
|
|
MaxIntegerDigits: 1,
|
|
MinExponentDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
// At least one exponent digit is required. As long as this is true, one can
|
|
// determine that scientific rendering is needed if MinExponentDigits > 0.
|
|
"#E#",
|
|
nil,
|
|
}, {
|
|
"0E0",
|
|
&Pattern{
|
|
FormatWidth: 3,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MinExponentDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"##0.###E00",
|
|
&Pattern{
|
|
FormatWidth: 10,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxIntegerDigits: 3,
|
|
MaxFractionDigits: 3,
|
|
MinExponentDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
"##00.0#E0",
|
|
&Pattern{
|
|
FormatWidth: 9,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 2,
|
|
MaxIntegerDigits: 4,
|
|
MinFractionDigits: 1,
|
|
MaxFractionDigits: 2,
|
|
MinExponentDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"#00.0E+0",
|
|
&Pattern{
|
|
FormatWidth: 8,
|
|
Flags: AlwaysExpSign,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 2,
|
|
MaxIntegerDigits: 3,
|
|
MinFractionDigits: 1,
|
|
MaxFractionDigits: 1,
|
|
MinExponentDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"0.0E++0",
|
|
nil,
|
|
}, {
|
|
"#0E+",
|
|
nil,
|
|
}, {
|
|
// significant digits
|
|
"@",
|
|
&Pattern{
|
|
FormatWidth: 1,
|
|
RoundingContext: RoundingContext{
|
|
MinSignificantDigits: 1,
|
|
MaxSignificantDigits: 1,
|
|
MaxFractionDigits: -1,
|
|
},
|
|
},
|
|
}, {
|
|
// significant digits
|
|
"@@@@",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
MinSignificantDigits: 4,
|
|
MaxSignificantDigits: 4,
|
|
MaxFractionDigits: -1,
|
|
},
|
|
},
|
|
}, {
|
|
"@###",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
MinSignificantDigits: 1,
|
|
MaxSignificantDigits: 4,
|
|
MaxFractionDigits: -1,
|
|
},
|
|
},
|
|
}, {
|
|
// Exponents in significant digits mode gets normalized.
|
|
"@@E0",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxIntegerDigits: 1,
|
|
MinFractionDigits: 1,
|
|
MaxFractionDigits: 1,
|
|
MinExponentDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"@###E00",
|
|
&Pattern{
|
|
FormatWidth: 7,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxIntegerDigits: 1,
|
|
MinFractionDigits: 0,
|
|
MaxFractionDigits: 3,
|
|
MinExponentDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
// The significant digits mode does not allow fractions.
|
|
"@###.#E0",
|
|
nil,
|
|
}, {
|
|
//alternative negative pattern
|
|
"#0.###;(#0.###)",
|
|
&Pattern{
|
|
Affix: "\x00\x00\x01(\x01)",
|
|
NegOffset: 2,
|
|
FormatWidth: 6,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MaxFractionDigits: 3,
|
|
},
|
|
},
|
|
}, {
|
|
// Rounding increment
|
|
"1.05",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
Increment: 105,
|
|
IncrementScale: 2,
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 2,
|
|
MaxFractionDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
// Rounding increment with grouping
|
|
"1,05",
|
|
&Pattern{
|
|
FormatWidth: 4,
|
|
GroupingSize: [2]uint8{2, 0},
|
|
RoundingContext: RoundingContext{
|
|
Increment: 105,
|
|
IncrementScale: 0,
|
|
MinIntegerDigits: 3,
|
|
MinFractionDigits: 0,
|
|
MaxFractionDigits: 0,
|
|
},
|
|
},
|
|
}, {
|
|
"0.0%",
|
|
&Pattern{
|
|
Affix: "\x00\x01%",
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
DigitShift: 2,
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 1,
|
|
MaxFractionDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"0.0‰",
|
|
&Pattern{
|
|
Affix: "\x00\x03‰",
|
|
FormatWidth: 4,
|
|
RoundingContext: RoundingContext{
|
|
DigitShift: 3,
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 1,
|
|
MaxFractionDigits: 1,
|
|
},
|
|
},
|
|
}, {
|
|
"#,##0.00¤",
|
|
&Pattern{
|
|
Affix: "\x00\x02¤",
|
|
FormatWidth: 9,
|
|
GroupingSize: [2]uint8{3, 0},
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 2,
|
|
MaxFractionDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
"#,##0.00 ¤;(#,##0.00 ¤)",
|
|
&Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
|
|
NegOffset: 6,
|
|
FormatWidth: 10,
|
|
GroupingSize: [2]uint8{3, 0},
|
|
RoundingContext: RoundingContext{
|
|
DigitShift: 0,
|
|
MinIntegerDigits: 1,
|
|
MinFractionDigits: 2,
|
|
MaxFractionDigits: 2,
|
|
},
|
|
},
|
|
}, {
|
|
// padding
|
|
"*x#",
|
|
&Pattern{
|
|
PadRune: 'x',
|
|
FormatWidth: 1,
|
|
},
|
|
}, {
|
|
// padding
|
|
"#*x",
|
|
&Pattern{
|
|
PadRune: 'x',
|
|
FormatWidth: 1,
|
|
Flags: PadBeforeSuffix,
|
|
},
|
|
}, {
|
|
"*xpre#suf",
|
|
&Pattern{
|
|
Affix: "\x03pre\x03suf",
|
|
PadRune: 'x',
|
|
FormatWidth: 7,
|
|
},
|
|
}, {
|
|
"pre*x#suf",
|
|
&Pattern{
|
|
Affix: "\x03pre\x03suf",
|
|
PadRune: 'x',
|
|
FormatWidth: 7,
|
|
Flags: PadAfterPrefix,
|
|
},
|
|
}, {
|
|
"pre#*xsuf",
|
|
&Pattern{
|
|
Affix: "\x03pre\x03suf",
|
|
PadRune: 'x',
|
|
FormatWidth: 7,
|
|
Flags: PadBeforeSuffix,
|
|
},
|
|
}, {
|
|
"pre#suf*x",
|
|
&Pattern{
|
|
Affix: "\x03pre\x03suf",
|
|
PadRune: 'x',
|
|
FormatWidth: 7,
|
|
Flags: PadAfterSuffix,
|
|
},
|
|
}, {
|
|
`* #0 o''clock`,
|
|
&Pattern{Affix: "\x00\x09 o\\'clock",
|
|
FormatWidth: 10,
|
|
PadRune: 32,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 0x1,
|
|
},
|
|
},
|
|
}, {
|
|
`'123'* #0'456'`,
|
|
&Pattern{Affix: "\x05'123'\x05'456'",
|
|
FormatWidth: 8,
|
|
PadRune: 32,
|
|
RoundingContext: RoundingContext{
|
|
MinIntegerDigits: 0x1,
|
|
},
|
|
Flags: PadAfterPrefix},
|
|
}, {
|
|
// no duplicate padding
|
|
"*xpre#suf*x", nil,
|
|
}, {
|
|
// no duplicate padding
|
|
"*xpre#suf*x", nil,
|
|
}}
|
|
|
|
func TestParsePattern(t *testing.T) {
|
|
for i, tc := range testCases {
|
|
t.Run(tc.pat, func(t *testing.T) {
|
|
f, err := ParsePattern(tc.pat)
|
|
if !reflect.DeepEqual(f, tc.want) {
|
|
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
|
|
}
|
|
if got, want := err != nil, tc.want == nil; got != want {
|
|
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPatternSize(t *testing.T) {
|
|
if sz := unsafe.Sizeof(Pattern{}); sz > 56 {
|
|
t.Errorf("got %d; want <= 56", sz)
|
|
}
|
|
|
|
}
|