1 /* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * This file is available under and governed by the GNU General Public 26 * License version 2 only, as published by the Free Software Foundation. 27 * However, the following notice accompanied the original version of this 28 * file: 29 * 30 * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos 31 * 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions are met: 36 * 37 * * Redistributions of source code must retain the above copyright notice, 38 * this list of conditions and the following disclaimer. 39 * 40 * * Redistributions in binary form must reproduce the above copyright notice, 41 * this list of conditions and the following disclaimer in the documentation 42 * and/or other materials provided with the distribution. 43 * 44 * * Neither the name of JSR-310 nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 50 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 51 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 52 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 */ 60 package test.java.time.format; 61 62 import java.time.format.*; 63 64 import static java.time.temporal.ChronoField.DAY_OF_MONTH; 65 import static java.time.temporal.ChronoField.DAY_OF_WEEK; 66 import static java.time.temporal.ChronoField.DAY_OF_YEAR; 67 import static java.time.temporal.ChronoField.MONTH_OF_YEAR; 68 import static org.testng.Assert.assertEquals; 69 import static org.testng.Assert.assertTrue; 70 71 import java.text.ParsePosition; 72 import java.time.format.DateTimeBuilder; 73 import java.time.temporal.TemporalField; 74 import java.time.format.DateTimeFormatter; 75 76 import org.testng.annotations.DataProvider; 77 import org.testng.annotations.Test; 78 79 /** 80 * Test NumberPrinterParser. 81 */ 82 @Test(groups={"implementation"}) 83 public class TestNumberParser extends AbstractTestPrinterParser { 84 85 //----------------------------------------------------------------------- 86 @DataProvider(name="error") 87 Object[][] data_error() { 88 return new Object[][] { 89 {DAY_OF_MONTH, 1, 2, SignStyle.NEVER, "12", -1, IndexOutOfBoundsException.class}, 90 {DAY_OF_MONTH, 1, 2, SignStyle.NEVER, "12", 3, IndexOutOfBoundsException.class}, 91 }; 92 } 93 94 @Test(dataProvider="error") 95 public void test_parse_error(TemporalField field, int min, int max, SignStyle style, String text, int pos, Class<?> expected) { 96 try { 97 getFormatter(field, min, max, style).parseToBuilder(text, new ParsePosition(pos)); 98 assertTrue(false); 99 } catch (RuntimeException ex) { 100 assertTrue(expected.isInstance(ex)); 101 } 102 } 103 104 //----------------------------------------------------------------------- 105 @DataProvider(name="parseData") 106 Object[][] provider_parseData() { 107 return new Object[][] { 108 // normal 109 {1, 2, SignStyle.NEVER, 0, "12", 0, 2, 12L}, // normal 110 {1, 2, SignStyle.NEVER, 0, "Xxx12Xxx", 3, 5, 12L}, // parse in middle 111 {1, 2, SignStyle.NEVER, 0, "99912999", 3, 5, 12L}, // parse in middle 112 {2, 4, SignStyle.NEVER, 0, "12345", 0, 4, 1234L}, // stops at max width 113 {2, 4, SignStyle.NEVER, 0, "12-45", 0, 2, 12L}, // stops at dash 114 {2, 4, SignStyle.NEVER, 0, "123-5", 0, 3, 123L}, // stops at dash 115 {1, 10, SignStyle.NORMAL, 0, "2147483647", 0, 10, Integer.MAX_VALUE}, 116 {1, 10, SignStyle.NORMAL, 0, "-2147483648", 0, 11, Integer.MIN_VALUE}, 117 {1, 10, SignStyle.NORMAL, 0, "2147483648", 0, 10, 2147483648L}, 118 {1, 10, SignStyle.NORMAL, 0, "-2147483649", 0, 11, -2147483649L}, 119 {1, 10, SignStyle.NORMAL, 0, "987659876598765", 0, 10, 9876598765L}, 120 {1, 19, SignStyle.NORMAL, 0, "999999999999999999", 0, 18, 999999999999999999L}, 121 {1, 19, SignStyle.NORMAL, 0, "-999999999999999999", 0, 19, -999999999999999999L}, 122 {1, 19, SignStyle.NORMAL, 0, "1000000000000000000", 0, 19, 1000000000000000000L}, 123 {1, 19, SignStyle.NORMAL, 0, "-1000000000000000000", 0, 20, -1000000000000000000L}, 124 {1, 19, SignStyle.NORMAL, 0, "000000000000000000", 0, 18, 0L}, 125 {1, 19, SignStyle.NORMAL, 0, "0000000000000000000", 0, 19, 0L}, 126 {1, 19, SignStyle.NORMAL, 0, "9223372036854775807", 0, 19, Long.MAX_VALUE}, 127 {1, 19, SignStyle.NORMAL, 0, "-9223372036854775808", 0, 20, Long.MIN_VALUE}, 128 {1, 19, SignStyle.NORMAL, 0, "9223372036854775808", 0, 18, 922337203685477580L}, // last digit not parsed 129 {1, 19, SignStyle.NORMAL, 0, "-9223372036854775809", 0, 19, -922337203685477580L}, // last digit not parsed 130 // no match 131 {1, 2, SignStyle.NEVER, 1, "A1", 0, 0, 0}, 132 {1, 2, SignStyle.NEVER, 1, " 1", 0, 0, 0}, 133 {1, 2, SignStyle.NEVER, 1, " 1", 1, 1, 0}, 134 {2, 2, SignStyle.NEVER, 1, "1", 0, 0, 0}, 135 {2, 2, SignStyle.NEVER, 1, "Xxx1", 0, 0, 0}, 136 {2, 2, SignStyle.NEVER, 1, "1", 1, 1, 0}, 137 {2, 2, SignStyle.NEVER, 1, "Xxx1", 4, 4, 0}, 138 {2, 2, SignStyle.NEVER, 1, "1-2", 0, 0, 0}, 139 {1, 19, SignStyle.NORMAL, 0, "-000000000000000000", 0, 0, 0}, 140 {1, 19, SignStyle.NORMAL, 0, "-0000000000000000000", 0, 0, 0}, 141 // parse reserving space 1 (adjacent-parsing) 142 {1, 1, SignStyle.NEVER, 1, "12", 0, 1, 1L}, 143 {1, 19, SignStyle.NEVER, 1, "12", 0, 1, 1L}, 144 {1, 19, SignStyle.NEVER, 1, "12345", 0, 4, 1234L}, 145 {1, 19, SignStyle.NEVER, 1, "12345678901", 0, 10, 1234567890L}, 146 {1, 19, SignStyle.NEVER, 1, "123456789012345678901234567890", 0, 19, 1234567890123456789L}, 147 {1, 19, SignStyle.NEVER, 1, "1", 0, 1, 1L}, // error from next field 148 {2, 2, SignStyle.NEVER, 1, "12", 0, 2, 12L}, // error from next field 149 {2, 19, SignStyle.NEVER, 1, "1", 0, 0, 0}, 150 // parse reserving space 2 (adjacent-parsing) 151 {1, 1, SignStyle.NEVER, 2, "123", 0, 1, 1L}, 152 {1, 19, SignStyle.NEVER, 2, "123", 0, 1, 1L}, 153 {1, 19, SignStyle.NEVER, 2, "12345", 0, 3, 123L}, 154 {1, 19, SignStyle.NEVER, 2, "12345678901", 0, 9, 123456789L}, 155 {1, 19, SignStyle.NEVER, 2, "123456789012345678901234567890", 0, 19, 1234567890123456789L}, 156 {1, 19, SignStyle.NEVER, 2, "1", 0, 1, 1L}, // error from next field 157 {1, 19, SignStyle.NEVER, 2, "12", 0, 1, 1L}, // error from next field 158 {2, 2, SignStyle.NEVER, 2, "12", 0, 2, 12L}, // error from next field 159 {2, 19, SignStyle.NEVER, 2, "1", 0, 0, 0}, 160 {2, 19, SignStyle.NEVER, 2, "1AAAAABBBBBCCCCC", 0, 0, 0}, 161 }; 162 } 163 164 //----------------------------------------------------------------------- 165 @Test(dataProvider="parseData") 166 public void test_parse_fresh(int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth, String text, int pos, int expectedPos, long expectedValue) { 167 ParsePosition ppos = new ParsePosition(pos); 168 DateTimeFormatter dtf = getFormatter(DAY_OF_MONTH, minWidth, maxWidth, signStyle); 169 if (subsequentWidth > 0) { 170 // hacky, to reserve space 171 dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols); 172 } 173 DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); 174 if (ppos.getErrorIndex() != -1) { 175 assertEquals(ppos.getErrorIndex(), expectedPos); 176 } else { 177 assertTrue(subsequentWidth >= 0); 178 assertEquals(ppos.getIndex(), expectedPos + subsequentWidth); 179 assertEquals(dtb.getLong(DAY_OF_MONTH), expectedValue); 180 } 181 } 182 183 @Test(dataProvider="parseData") 184 public void test_parse_textField(int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth, String text, int pos, int expectedPos, long expectedValue) { 185 ParsePosition ppos = new ParsePosition(pos); 186 DateTimeFormatter dtf = getFormatter(DAY_OF_WEEK, minWidth, maxWidth, signStyle); 187 if (subsequentWidth > 0) { 188 // hacky, to reserve space 189 dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols); 190 } 191 DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); 192 if (ppos.getErrorIndex() != -1) { 193 assertEquals(ppos.getErrorIndex(), expectedPos); 194 } else { 195 assertTrue(subsequentWidth >= 0); 196 assertEquals(ppos.getIndex(), expectedPos + subsequentWidth); 197 assertEquals(dtb.getLong(DAY_OF_WEEK), expectedValue); 198 } 199 } 200 201 //----------------------------------------------------------------------- 202 @DataProvider(name="parseSignsStrict") 203 Object[][] provider_parseSignsStrict() { 204 return new Object[][] { 205 // basics 206 {"0", 1, 2, SignStyle.NEVER, 1, 0}, 207 {"1", 1, 2, SignStyle.NEVER, 1, 1}, 208 {"2", 1, 2, SignStyle.NEVER, 1, 2}, 209 {"3", 1, 2, SignStyle.NEVER, 1, 3}, 210 {"4", 1, 2, SignStyle.NEVER, 1, 4}, 211 {"5", 1, 2, SignStyle.NEVER, 1, 5}, 212 {"6", 1, 2, SignStyle.NEVER, 1, 6}, 213 {"7", 1, 2, SignStyle.NEVER, 1, 7}, 214 {"8", 1, 2, SignStyle.NEVER, 1, 8}, 215 {"9", 1, 2, SignStyle.NEVER, 1, 9}, 216 {"10", 1, 2, SignStyle.NEVER, 2, 10}, 217 {"100", 1, 2, SignStyle.NEVER, 2, 10}, 218 {"100", 1, 3, SignStyle.NEVER, 3, 100}, 219 220 // never 221 {"0", 1, 2, SignStyle.NEVER, 1, 0}, 222 {"5", 1, 2, SignStyle.NEVER, 1, 5}, 223 {"50", 1, 2, SignStyle.NEVER, 2, 50}, 224 {"500", 1, 2, SignStyle.NEVER, 2, 50}, 225 {"-0", 1, 2, SignStyle.NEVER, 0, null}, 226 {"-5", 1, 2, SignStyle.NEVER, 0, null}, 227 {"-50", 1, 2, SignStyle.NEVER, 0, null}, 228 {"-500", 1, 2, SignStyle.NEVER, 0, null}, 229 {"-AAA", 1, 2, SignStyle.NEVER, 0, null}, 230 {"+0", 1, 2, SignStyle.NEVER, 0, null}, 231 {"+5", 1, 2, SignStyle.NEVER, 0, null}, 232 {"+50", 1, 2, SignStyle.NEVER, 0, null}, 233 {"+500", 1, 2, SignStyle.NEVER, 0, null}, 234 {"+AAA", 1, 2, SignStyle.NEVER, 0, null}, 235 236 // not negative 237 {"0", 1, 2, SignStyle.NOT_NEGATIVE, 1, 0}, 238 {"5", 1, 2, SignStyle.NOT_NEGATIVE, 1, 5}, 239 {"50", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50}, 240 {"500", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50}, 241 {"-0", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 242 {"-5", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 243 {"-50", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 244 {"-500", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 245 {"-AAA", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 246 {"+0", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 247 {"+5", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 248 {"+50", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 249 {"+500", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 250 {"+AAA", 1, 2, SignStyle.NOT_NEGATIVE, 0, null}, 251 252 // normal 253 {"0", 1, 2, SignStyle.NORMAL, 1, 0}, 254 {"5", 1, 2, SignStyle.NORMAL, 1, 5}, 255 {"50", 1, 2, SignStyle.NORMAL, 2, 50}, 256 {"500", 1, 2, SignStyle.NORMAL, 2, 50}, 257 {"-0", 1, 2, SignStyle.NORMAL, 0, null}, 258 {"-5", 1, 2, SignStyle.NORMAL, 2, -5}, 259 {"-50", 1, 2, SignStyle.NORMAL, 3, -50}, 260 {"-500", 1, 2, SignStyle.NORMAL, 3, -50}, 261 {"-AAA", 1, 2, SignStyle.NORMAL, 1, null}, 262 {"+0", 1, 2, SignStyle.NORMAL, 0, null}, 263 {"+5", 1, 2, SignStyle.NORMAL, 0, null}, 264 {"+50", 1, 2, SignStyle.NORMAL, 0, null}, 265 {"+500", 1, 2, SignStyle.NORMAL, 0, null}, 266 {"+AAA", 1, 2, SignStyle.NORMAL, 0, null}, 267 268 // always 269 {"0", 1, 2, SignStyle.ALWAYS, 0, null}, 270 {"5", 1, 2, SignStyle.ALWAYS, 0, null}, 271 {"50", 1, 2, SignStyle.ALWAYS, 0, null}, 272 {"500", 1, 2, SignStyle.ALWAYS, 0, null}, 273 {"-0", 1, 2, SignStyle.ALWAYS, 0, null}, 274 {"-5", 1, 2, SignStyle.ALWAYS, 2, -5}, 275 {"-50", 1, 2, SignStyle.ALWAYS, 3, -50}, 276 {"-500", 1, 2, SignStyle.ALWAYS, 3, -50}, 277 {"-AAA", 1, 2, SignStyle.ALWAYS, 1, null}, 278 {"+0", 1, 2, SignStyle.ALWAYS, 2, 0}, 279 {"+5", 1, 2, SignStyle.ALWAYS, 2, 5}, 280 {"+50", 1, 2, SignStyle.ALWAYS, 3, 50}, 281 {"+500", 1, 2, SignStyle.ALWAYS, 3, 50}, 282 {"+AAA", 1, 2, SignStyle.ALWAYS, 1, null}, 283 284 // exceeds pad 285 {"0", 1, 2, SignStyle.EXCEEDS_PAD, 1, 0}, 286 {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5}, 287 {"50", 1, 2, SignStyle.EXCEEDS_PAD, 0, null}, 288 {"500", 1, 2, SignStyle.EXCEEDS_PAD, 0, null}, 289 {"-0", 1, 2, SignStyle.EXCEEDS_PAD, 0, null}, 290 {"-5", 1, 2, SignStyle.EXCEEDS_PAD, 2, -5}, 291 {"-50", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50}, 292 {"-500", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50}, 293 {"-AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null}, 294 {"+0", 1, 2, SignStyle.EXCEEDS_PAD, 0, null}, 295 {"+5", 1, 2, SignStyle.EXCEEDS_PAD, 0, null}, 296 {"+50", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50}, 297 {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50}, 298 {"+AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null}, 299 }; 300 } 301 302 @Test(dataProvider="parseSignsStrict") 303 public void test_parseSignsStrict(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { 304 ParsePosition pos = new ParsePosition(0); 305 DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); 306 if (pos.getErrorIndex() != -1) { 307 assertEquals(pos.getErrorIndex(), parseLen); 308 } else { 309 assertEquals(pos.getIndex(), parseLen); 310 assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); 311 } 312 } 313 314 //----------------------------------------------------------------------- 315 @DataProvider(name="parseSignsLenient") 316 Object[][] provider_parseSignsLenient() { 317 return new Object[][] { 318 // never 319 {"0", 1, 2, SignStyle.NEVER, 1, 0}, 320 {"5", 1, 2, SignStyle.NEVER, 1, 5}, 321 {"50", 1, 2, SignStyle.NEVER, 2, 50}, 322 {"500", 1, 2, SignStyle.NEVER, 2, 50}, 323 {"-0", 1, 2, SignStyle.NEVER, 2, 0}, 324 {"-5", 1, 2, SignStyle.NEVER, 2, -5}, 325 {"-50", 1, 2, SignStyle.NEVER, 3, -50}, 326 {"-500", 1, 2, SignStyle.NEVER, 3, -50}, 327 {"-AAA", 1, 2, SignStyle.NEVER, 1, null}, 328 {"+0", 1, 2, SignStyle.NEVER, 2, 0}, 329 {"+5", 1, 2, SignStyle.NEVER, 2, 5}, 330 {"+50", 1, 2, SignStyle.NEVER, 3, 50}, 331 {"+500", 1, 2, SignStyle.NEVER, 3, 50}, 332 {"+AAA", 1, 2, SignStyle.NEVER, 1, null}, 333 {"50", 2, 2, SignStyle.NEVER, 2, 50}, 334 {"-50", 2, 2, SignStyle.NEVER, 0, null}, 335 {"+50", 2, 2, SignStyle.NEVER, 0, null}, 336 337 // not negative 338 {"0", 1, 2, SignStyle.NOT_NEGATIVE, 1, 0}, 339 {"5", 1, 2, SignStyle.NOT_NEGATIVE, 1, 5}, 340 {"50", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50}, 341 {"500", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50}, 342 {"-0", 1, 2, SignStyle.NOT_NEGATIVE, 2, 0}, 343 {"-5", 1, 2, SignStyle.NOT_NEGATIVE, 2, -5}, 344 {"-50", 1, 2, SignStyle.NOT_NEGATIVE, 3, -50}, 345 {"-500", 1, 2, SignStyle.NOT_NEGATIVE, 3, -50}, 346 {"-AAA", 1, 2, SignStyle.NOT_NEGATIVE, 1, null}, 347 {"+0", 1, 2, SignStyle.NOT_NEGATIVE, 2, 0}, 348 {"+5", 1, 2, SignStyle.NOT_NEGATIVE, 2, 5}, 349 {"+50", 1, 2, SignStyle.NOT_NEGATIVE, 3, 50}, 350 {"+500", 1, 2, SignStyle.NOT_NEGATIVE, 3, 50}, 351 {"+AAA", 1, 2, SignStyle.NOT_NEGATIVE, 1, null}, 352 {"50", 2, 2, SignStyle.NOT_NEGATIVE, 2, 50}, 353 {"-50", 2, 2, SignStyle.NOT_NEGATIVE, 0, null}, 354 {"+50", 2, 2, SignStyle.NOT_NEGATIVE, 0, null}, 355 356 // normal 357 {"0", 1, 2, SignStyle.NORMAL, 1, 0}, 358 {"5", 1, 2, SignStyle.NORMAL, 1, 5}, 359 {"50", 1, 2, SignStyle.NORMAL, 2, 50}, 360 {"500", 1, 2, SignStyle.NORMAL, 2, 50}, 361 {"-0", 1, 2, SignStyle.NORMAL, 2, 0}, 362 {"-5", 1, 2, SignStyle.NORMAL, 2, -5}, 363 {"-50", 1, 2, SignStyle.NORMAL, 3, -50}, 364 {"-500", 1, 2, SignStyle.NORMAL, 3, -50}, 365 {"-AAA", 1, 2, SignStyle.NORMAL, 1, null}, 366 {"+0", 1, 2, SignStyle.NORMAL, 2, 0}, 367 {"+5", 1, 2, SignStyle.NORMAL, 2, 5}, 368 {"+50", 1, 2, SignStyle.NORMAL, 3, 50}, 369 {"+500", 1, 2, SignStyle.NORMAL, 3, 50}, 370 {"+AAA", 1, 2, SignStyle.NORMAL, 1, null}, 371 {"50", 2, 2, SignStyle.NORMAL, 2, 50}, 372 {"-50", 2, 2, SignStyle.NORMAL, 3, -50}, 373 {"+50", 2, 2, SignStyle.NORMAL, 3, 50}, 374 375 // always 376 {"0", 1, 2, SignStyle.ALWAYS, 1, 0}, 377 {"5", 1, 2, SignStyle.ALWAYS, 1, 5}, 378 {"50", 1, 2, SignStyle.ALWAYS, 2, 50}, 379 {"500", 1, 2, SignStyle.ALWAYS, 2, 50}, 380 {"-0", 1, 2, SignStyle.ALWAYS, 2, 0}, 381 {"-5", 1, 2, SignStyle.ALWAYS, 2, -5}, 382 {"-50", 1, 2, SignStyle.ALWAYS, 3, -50}, 383 {"-500", 1, 2, SignStyle.ALWAYS, 3, -50}, 384 {"-AAA", 1, 2, SignStyle.ALWAYS, 1, null}, 385 {"+0", 1, 2, SignStyle.ALWAYS, 2, 0}, 386 {"+5", 1, 2, SignStyle.ALWAYS, 2, 5}, 387 {"+50", 1, 2, SignStyle.ALWAYS, 3, 50}, 388 {"+500", 1, 2, SignStyle.ALWAYS, 3, 50}, 389 {"+AAA", 1, 2, SignStyle.ALWAYS, 1, null}, 390 391 // exceeds pad 392 {"0", 1, 2, SignStyle.EXCEEDS_PAD, 1, 0}, 393 {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5}, 394 {"50", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50}, 395 {"500", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50}, 396 {"-0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0}, 397 {"-5", 1, 2, SignStyle.EXCEEDS_PAD, 2, -5}, 398 {"-50", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50}, 399 {"-500", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50}, 400 {"-AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null}, 401 {"+0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0}, 402 {"+5", 1, 2, SignStyle.EXCEEDS_PAD, 2, 5}, 403 {"+50", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50}, 404 {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50}, 405 {"+AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null}, 406 }; 407 } 408 409 @Test(dataProvider="parseSignsLenient") 410 public void test_parseSignsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { 411 setStrict(false); 412 ParsePosition pos = new ParsePosition(0); 413 DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); 414 if (pos.getErrorIndex() != -1) { 415 assertEquals(pos.getErrorIndex(), parseLen); 416 } else { 417 assertEquals(pos.getIndex(), parseLen); 418 assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); 419 } 420 } 421 422 //----------------------------------------------------------------------- 423 @DataProvider(name="parseDigitsLenient") 424 Object[][] provider_parseDigitsLenient() { 425 return new Object[][] { 426 // never 427 {"5", 1, 2, SignStyle.NEVER, 1, 5}, 428 {"5", 2, 2, SignStyle.NEVER, 1, 5}, 429 {"54", 1, 3, SignStyle.NEVER, 2, 54}, 430 {"54", 2, 3, SignStyle.NEVER, 2, 54}, 431 {"54", 3, 3, SignStyle.NEVER, 2, 54}, 432 {"543", 1, 3, SignStyle.NEVER, 3, 543}, 433 {"543", 2, 3, SignStyle.NEVER, 3, 543}, 434 {"543", 3, 3, SignStyle.NEVER, 3, 543}, 435 {"5432", 1, 3, SignStyle.NEVER, 3, 543}, 436 {"5432", 2, 3, SignStyle.NEVER, 3, 543}, 437 {"5432", 3, 3, SignStyle.NEVER, 3, 543}, 438 {"5AAA", 2, 3, SignStyle.NEVER, 1, 5}, 439 440 // not negative 441 {"5", 1, 2, SignStyle.NOT_NEGATIVE, 1, 5}, 442 {"5", 2, 2, SignStyle.NOT_NEGATIVE, 1, 5}, 443 {"54", 1, 3, SignStyle.NOT_NEGATIVE, 2, 54}, 444 {"54", 2, 3, SignStyle.NOT_NEGATIVE, 2, 54}, 445 {"54", 3, 3, SignStyle.NOT_NEGATIVE, 2, 54}, 446 {"543", 1, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 447 {"543", 2, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 448 {"543", 3, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 449 {"5432", 1, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 450 {"5432", 2, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 451 {"5432", 3, 3, SignStyle.NOT_NEGATIVE, 3, 543}, 452 {"5AAA", 2, 3, SignStyle.NOT_NEGATIVE, 1, 5}, 453 454 // normal 455 {"5", 1, 2, SignStyle.NORMAL, 1, 5}, 456 {"5", 2, 2, SignStyle.NORMAL, 1, 5}, 457 {"54", 1, 3, SignStyle.NORMAL, 2, 54}, 458 {"54", 2, 3, SignStyle.NORMAL, 2, 54}, 459 {"54", 3, 3, SignStyle.NORMAL, 2, 54}, 460 {"543", 1, 3, SignStyle.NORMAL, 3, 543}, 461 {"543", 2, 3, SignStyle.NORMAL, 3, 543}, 462 {"543", 3, 3, SignStyle.NORMAL, 3, 543}, 463 {"5432", 1, 3, SignStyle.NORMAL, 3, 543}, 464 {"5432", 2, 3, SignStyle.NORMAL, 3, 543}, 465 {"5432", 3, 3, SignStyle.NORMAL, 3, 543}, 466 {"5AAA", 2, 3, SignStyle.NORMAL, 1, 5}, 467 468 // always 469 {"5", 1, 2, SignStyle.ALWAYS, 1, 5}, 470 {"5", 2, 2, SignStyle.ALWAYS, 1, 5}, 471 {"54", 1, 3, SignStyle.ALWAYS, 2, 54}, 472 {"54", 2, 3, SignStyle.ALWAYS, 2, 54}, 473 {"54", 3, 3, SignStyle.ALWAYS, 2, 54}, 474 {"543", 1, 3, SignStyle.ALWAYS, 3, 543}, 475 {"543", 2, 3, SignStyle.ALWAYS, 3, 543}, 476 {"543", 3, 3, SignStyle.ALWAYS, 3, 543}, 477 {"5432", 1, 3, SignStyle.ALWAYS, 3, 543}, 478 {"5432", 2, 3, SignStyle.ALWAYS, 3, 543}, 479 {"5432", 3, 3, SignStyle.ALWAYS, 3, 543}, 480 {"5AAA", 2, 3, SignStyle.ALWAYS, 1, 5}, 481 482 // exceeds pad 483 {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5}, 484 {"5", 2, 2, SignStyle.EXCEEDS_PAD, 1, 5}, 485 {"54", 1, 3, SignStyle.EXCEEDS_PAD, 2, 54}, 486 {"54", 2, 3, SignStyle.EXCEEDS_PAD, 2, 54}, 487 {"54", 3, 3, SignStyle.EXCEEDS_PAD, 2, 54}, 488 {"543", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 489 {"543", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 490 {"543", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 491 {"5432", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 492 {"5432", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 493 {"5432", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543}, 494 {"5AAA", 2, 3, SignStyle.EXCEEDS_PAD, 1, 5}, 495 }; 496 } 497 498 @Test(dataProvider="parseDigitsLenient") 499 public void test_parseDigitsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { 500 setStrict(false); 501 ParsePosition pos = new ParsePosition(0); 502 DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); 503 if (pos.getErrorIndex() != -1) { 504 assertEquals(pos.getErrorIndex(), parseLen); 505 } else { 506 assertEquals(pos.getIndex(), parseLen); 507 assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); 508 } 509 } 510 511 //----------------------------------------------------------------------- 512 @DataProvider(name="parseDigitsAdjacentLenient") 513 Object[][] provider_parseDigitsAdjacentLenient() { 514 return new Object[][] { 515 // never 516 {"5", 1, null, null}, 517 {"54", 1, null, null}, 518 519 {"543", 3, 5, 43}, 520 {"543A", 3, 5, 43}, 521 522 {"5432", 4, 54, 32}, 523 {"5432A", 4, 54, 32}, 524 525 {"54321", 4, 54, 32}, 526 {"54321A", 4, 54, 32}, 527 }; 528 } 529 530 @Test(dataProvider="parseDigitsAdjacentLenient") 531 public void test_parseDigitsAdjacentLenient(String input, int parseLen, Integer parseMonth, Integer parsedDay) throws Exception { 532 setStrict(false); 533 ParsePosition pos = new ParsePosition(0); 534 DateTimeFormatter f = builder 535 .appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL) 536 .appendValue(DAY_OF_MONTH, 2).toFormatter(locale).withSymbols(symbols); 537 DateTimeBuilder dtb = f.parseToBuilder(input, pos); 538 if (pos.getErrorIndex() != -1) { 539 assertEquals(pos.getErrorIndex(), parseLen); 540 } else { 541 assertEquals(pos.getIndex(), parseLen); 542 assertEquals(dtb.getLong(MONTH_OF_YEAR), (long) parseMonth); 543 assertEquals(dtb.getLong(DAY_OF_MONTH), (long) parsedDay); 544 } 545 } 546 547 }