1// Copyright 2015 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 5package number 6 7import ( 8 "reflect" 9 "testing" 10 "unsafe" 11) 12 13var testCases = []struct { 14 pat string 15 want *Pattern 16}{{ 17 "#", 18 &Pattern{ 19 FormatWidth: 1, 20 // TODO: Should MinIntegerDigits be 1? 21 }, 22}, { 23 "0", 24 &Pattern{ 25 FormatWidth: 1, 26 MinIntegerDigits: 1, 27 }, 28}, { 29 "+0", 30 &Pattern{ 31 Affix: "\x01+\x00", 32 FormatWidth: 2, 33 MinIntegerDigits: 1, 34 }, 35}, { 36 "0+", 37 &Pattern{ 38 Affix: "\x00\x01+", 39 FormatWidth: 2, 40 MinIntegerDigits: 1, 41 }, 42}, { 43 "0000", 44 &Pattern{ 45 FormatWidth: 4, 46 MinIntegerDigits: 4, 47 }, 48}, { 49 ".#", 50 &Pattern{ 51 FormatWidth: 2, 52 MaxFractionDigits: 1, 53 }, 54}, { 55 "#0.###", 56 &Pattern{ 57 FormatWidth: 6, 58 MinIntegerDigits: 1, 59 MaxFractionDigits: 3, 60 }, 61}, { 62 "#0.######", 63 &Pattern{ 64 FormatWidth: 9, 65 MinIntegerDigits: 1, 66 MaxFractionDigits: 6, 67 }, 68}, { 69 "#,0", 70 &Pattern{ 71 FormatWidth: 3, 72 GroupingSize: [2]uint8{1, 0}, 73 MinIntegerDigits: 1, 74 }, 75}, { 76 "#,0.00", 77 &Pattern{ 78 FormatWidth: 6, 79 GroupingSize: [2]uint8{1, 0}, 80 MinIntegerDigits: 1, 81 MinFractionDigits: 2, 82 MaxFractionDigits: 2, 83 }, 84}, { 85 "#,##0.###", 86 &Pattern{ 87 FormatWidth: 9, 88 GroupingSize: [2]uint8{3, 0}, 89 MinIntegerDigits: 1, 90 MaxFractionDigits: 3, 91 }, 92}, { 93 "#,##,##0.###", 94 &Pattern{ 95 FormatWidth: 12, 96 GroupingSize: [2]uint8{3, 2}, 97 MinIntegerDigits: 1, 98 MaxFractionDigits: 3, 99 }, 100}, { 101 // Ignore additional separators. 102 "#,####,##,##0.###", 103 &Pattern{ 104 FormatWidth: 17, 105 GroupingSize: [2]uint8{3, 2}, 106 MinIntegerDigits: 1, 107 MaxFractionDigits: 3, 108 }, 109}, { 110 "#E0", 111 &Pattern{ 112 FormatWidth: 3, 113 MaxIntegerDigits: 1, 114 MinExponentDigits: 1, 115 }, 116}, { 117 // At least one exponent digit is required. As long as this is true, one can 118 // determine that scientific rendering is needed if MinExponentDigits > 0. 119 "#E#", 120 nil, 121}, { 122 "0E0", 123 &Pattern{ 124 FormatWidth: 3, 125 MinIntegerDigits: 1, 126 MinExponentDigits: 1, 127 }, 128}, { 129 "##00.0#E0", 130 &Pattern{ 131 FormatWidth: 9, 132 MinIntegerDigits: 2, 133 MaxIntegerDigits: 4, 134 MinFractionDigits: 1, 135 MaxFractionDigits: 2, 136 MinExponentDigits: 1, 137 }, 138}, { 139 "#00.0E+0", 140 &Pattern{ 141 FormatWidth: 8, 142 Flags: AlwaysExpSign, 143 MinIntegerDigits: 2, 144 MaxIntegerDigits: 3, 145 MinFractionDigits: 1, 146 MaxFractionDigits: 1, 147 MinExponentDigits: 1, 148 }, 149}, { 150 "0.0E++0", 151 nil, 152}, { 153 "#0E+", 154 nil, 155}, { 156 // significant digits 157 "@", 158 &Pattern{ 159 FormatWidth: 1, 160 MinSignificantDigits: 1, 161 MaxSignificantDigits: 1, 162 }, 163}, { 164 // significant digits 165 "@@@@", 166 &Pattern{ 167 FormatWidth: 4, 168 MinSignificantDigits: 4, 169 MaxSignificantDigits: 4, 170 }, 171}, { 172 "@###", 173 &Pattern{ 174 FormatWidth: 4, 175 MinSignificantDigits: 1, 176 MaxSignificantDigits: 4, 177 }, 178}, { 179 // Exponents in significant digits mode gets normalized. 180 "@@E0", 181 &Pattern{ 182 FormatWidth: 4, 183 MinIntegerDigits: 1, 184 MaxIntegerDigits: 1, 185 MinFractionDigits: 1, 186 MaxFractionDigits: 1, 187 MinExponentDigits: 1, 188 }, 189}, { 190 "@###E00", 191 &Pattern{ 192 FormatWidth: 7, 193 MinIntegerDigits: 1, 194 MaxIntegerDigits: 1, 195 MinFractionDigits: 0, 196 MaxFractionDigits: 3, 197 MinExponentDigits: 2, 198 }, 199}, { 200 // The significant digits mode does not allow fractions. 201 "@###.#E0", 202 nil, 203}, { 204 //alternative negative pattern 205 "#0.###;(#0.###)", 206 &Pattern{ 207 Affix: "\x00\x00\x01(\x01)", 208 NegOffset: 2, 209 FormatWidth: 6, 210 MinIntegerDigits: 1, 211 MaxFractionDigits: 3, 212 }, 213}, { 214 // Rounding increment 215 "1.05", 216 &Pattern{ 217 RoundIncrement: 105, 218 FormatWidth: 4, 219 MinIntegerDigits: 1, 220 MinFractionDigits: 2, 221 MaxFractionDigits: 2, 222 }, 223}, { 224 // Rounding increment with grouping 225 "1,05", 226 &Pattern{ 227 RoundIncrement: 105, 228 FormatWidth: 4, 229 GroupingSize: [2]uint8{2, 0}, 230 MinIntegerDigits: 3, 231 MinFractionDigits: 0, 232 MaxFractionDigits: 0, 233 }, 234}, { 235 "0.0%", 236 &Pattern{ 237 Affix: "\x00\x01%", 238 DigitShift: 2, 239 FormatWidth: 4, 240 MinIntegerDigits: 1, 241 MinFractionDigits: 1, 242 MaxFractionDigits: 1, 243 }, 244}, { 245 "0.0‰", 246 &Pattern{ 247 Affix: "\x00\x03‰", 248 DigitShift: 3, 249 FormatWidth: 4, 250 MinIntegerDigits: 1, 251 MinFractionDigits: 1, 252 MaxFractionDigits: 1, 253 }, 254}, { 255 "#,##0.00¤", 256 &Pattern{ 257 Affix: "\x00\x02¤", 258 FormatWidth: 9, 259 GroupingSize: [2]uint8{3, 0}, 260 MinIntegerDigits: 1, 261 MinFractionDigits: 2, 262 MaxFractionDigits: 2, 263 }, 264}, { 265 "#,##0.00 ¤;(#,##0.00 ¤)", 266 &Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)", 267 NegOffset: 6, 268 DigitShift: 0, 269 FormatWidth: 10, 270 GroupingSize: [2]uint8{3, 0}, 271 MinIntegerDigits: 1, 272 MinFractionDigits: 2, 273 MaxFractionDigits: 2, 274 }, 275}, { 276 // padding 277 "*x#", 278 &Pattern{ 279 PadRune: 'x', 280 FormatWidth: 1, 281 }, 282}, { 283 // padding 284 "#*x", 285 &Pattern{ 286 PadRune: 'x', 287 FormatWidth: 1, 288 Flags: PadBeforeSuffix, 289 }, 290}, { 291 "*xpre#suf", 292 &Pattern{ 293 Affix: "\x03pre\x03suf", 294 PadRune: 'x', 295 FormatWidth: 7, 296 }, 297}, { 298 "pre*x#suf", 299 &Pattern{ 300 Affix: "\x03pre\x03suf", 301 PadRune: 'x', 302 FormatWidth: 7, 303 Flags: PadAfterPrefix, 304 }, 305}, { 306 "pre#*xsuf", 307 &Pattern{ 308 Affix: "\x03pre\x03suf", 309 PadRune: 'x', 310 FormatWidth: 7, 311 Flags: PadBeforeSuffix, 312 }, 313}, { 314 "pre#suf*x", 315 &Pattern{ 316 Affix: "\x03pre\x03suf", 317 PadRune: 'x', 318 FormatWidth: 7, 319 Flags: PadAfterSuffix, 320 }, 321}, { 322 `* #0 o''clock`, 323 &Pattern{Affix: "\x00\x09 o\\'clock", 324 FormatWidth: 10, 325 PadRune: 32, 326 MinIntegerDigits: 0x1}, 327}, { 328 `'123'* #0'456'`, 329 &Pattern{Affix: "\x05'123'\x05'456'", 330 FormatWidth: 8, 331 PadRune: 32, 332 MinIntegerDigits: 0x1, 333 Flags: PadAfterPrefix}, 334}, { 335 // no duplicate padding 336 "*xpre#suf*x", nil, 337}, { 338 // no duplicate padding 339 "*xpre#suf*x", nil, 340}} 341 342func TestParsePattern(t *testing.T) { 343 for i, tc := range testCases { 344 t.Run(tc.pat, func(t *testing.T) { 345 f, err := ParsePattern(tc.pat) 346 if !reflect.DeepEqual(f, tc.want) { 347 t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want) 348 } 349 if got, want := err != nil, tc.want == nil; got != want { 350 t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want) 351 } 352 }) 353 } 354} 355 356func TestPatternSize(t *testing.T) { 357 if sz := unsafe.Sizeof(Pattern{}); sz > 48 { 358 t.Errorf("got %d; want <= 48", sz) 359 } 360 361} 362