test/java/time/test/java/time/format/TestNumberParser.java

Print this page




  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},


 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},


 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},


 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},


 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 }


  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 static java.time.temporal.ChronoField.DAY_OF_MONTH;
  63 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
  64 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
  65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  66 import static org.testng.Assert.assertEquals;
  67 import static org.testng.Assert.assertTrue;
  68 import static org.testng.Assert.fail;
  69 
  70 import java.text.ParsePosition;


  71 import java.time.format.DateTimeFormatter;
  72 import java.time.format.SignStyle;
  73 import java.time.temporal.Queries;
  74 import java.time.temporal.TemporalAccessor;
  75 import java.time.temporal.TemporalField;
  76 
  77 import org.testng.annotations.DataProvider;
  78 import org.testng.annotations.Test;
  79 
  80 /**
  81  * Test NumberPrinterParser.
  82  */
  83 @Test(groups={"implementation"})
  84 public class TestNumberParser extends AbstractTestPrinterParser {
  85 
  86     //-----------------------------------------------------------------------
  87     @DataProvider(name="error")
  88     Object[][] data_error() {
  89         return new Object[][] {
  90             {DAY_OF_MONTH, 1, 2, SignStyle.NEVER, "12", -1, IndexOutOfBoundsException.class},
  91             {DAY_OF_MONTH, 1, 2, SignStyle.NEVER, "12", 3, IndexOutOfBoundsException.class},
  92         };
  93     }
  94 
  95     @Test(dataProvider="error")
  96     public void test_parse_error(TemporalField field, int min, int max, SignStyle style, String text, int pos, Class<?> expected) {
  97         try {
  98             getFormatter(field, min, max, style).parseUnresolved(text, new ParsePosition(pos));
  99             fail();
 100         } catch (RuntimeException ex) {
 101             assertTrue(expected.isInstance(ex));
 102         }
 103     }
 104 
 105     //-----------------------------------------------------------------------
 106     @DataProvider(name="parseData")
 107     Object[][] provider_parseData() {
 108         return new Object[][] {
 109             // normal
 110             {1, 2, SignStyle.NEVER, 0, "12", 0, 2, 12L},       // normal
 111             {1, 2, SignStyle.NEVER, 0, "Xxx12Xxx", 3, 5, 12L}, // parse in middle
 112             {1, 2, SignStyle.NEVER, 0, "99912999", 3, 5, 12L}, // parse in middle
 113             {2, 4, SignStyle.NEVER, 0, "12345", 0, 4, 1234L},  // stops at max width
 114             {2, 4, SignStyle.NEVER, 0, "12-45", 0, 2, 12L},    // stops at dash
 115             {2, 4, SignStyle.NEVER, 0, "123-5", 0, 3, 123L},   // stops at dash
 116             {1, 10, SignStyle.NORMAL, 0, "2147483647", 0, 10, Integer.MAX_VALUE},
 117             {1, 10, SignStyle.NORMAL, 0, "-2147483648", 0, 11, Integer.MIN_VALUE},
 118             {1, 10, SignStyle.NORMAL, 0, "2147483648", 0, 10, 2147483648L},
 119             {1, 10, SignStyle.NORMAL, 0, "-2147483649", 0, 11, -2147483649L},


 154             {1, 19, SignStyle.NEVER, 2, "12345", 0, 3, 123L},
 155             {1, 19, SignStyle.NEVER, 2, "12345678901", 0, 9, 123456789L},
 156             {1, 19, SignStyle.NEVER, 2, "123456789012345678901234567890", 0, 19, 1234567890123456789L},
 157             {1, 19, SignStyle.NEVER, 2, "1", 0, 1, 1L},  // error from next field
 158             {1, 19, SignStyle.NEVER, 2, "12", 0, 1, 1L},  // error from next field
 159             {2, 2, SignStyle.NEVER, 2, "12", 0, 2, 12L},  // error from next field
 160             {2, 19, SignStyle.NEVER, 2, "1", 0, 0, 0},
 161             {2, 19, SignStyle.NEVER, 2, "1AAAAABBBBBCCCCC", 0, 0, 0},
 162         };
 163     }
 164 
 165     //-----------------------------------------------------------------------
 166     @Test(dataProvider="parseData")
 167     public void test_parse_fresh(int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth, String text, int pos, int expectedPos, long expectedValue) {
 168         ParsePosition ppos = new ParsePosition(pos);
 169         DateTimeFormatter dtf = getFormatter(DAY_OF_MONTH, minWidth, maxWidth, signStyle);
 170         if (subsequentWidth > 0) {
 171             // hacky, to reserve space
 172             dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols);
 173         }
 174         TemporalAccessor parsed = dtf.parseUnresolved(text, ppos);
 175         if (ppos.getErrorIndex() != -1) {
 176             assertEquals(ppos.getErrorIndex(), expectedPos);
 177         } else {
 178             assertTrue(subsequentWidth >= 0);
 179             assertEquals(ppos.getIndex(), expectedPos + subsequentWidth);
 180             assertEquals(parsed.getLong(DAY_OF_MONTH), expectedValue);
 181             assertEquals(parsed.query(Queries.chronology()), null);
 182             assertEquals(parsed.query(Queries.zoneId()), null);
 183         }
 184     }
 185 
 186     @Test(dataProvider="parseData")
 187     public void test_parse_textField(int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth, String text, int pos, int expectedPos, long expectedValue) {
 188         ParsePosition ppos = new ParsePosition(pos);
 189         DateTimeFormatter dtf = getFormatter(DAY_OF_WEEK, minWidth, maxWidth, signStyle);
 190         if (subsequentWidth > 0) {
 191             // hacky, to reserve space
 192             dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols);
 193         }
 194         TemporalAccessor parsed = dtf.parseUnresolved(text, ppos);
 195         if (ppos.getErrorIndex() != -1) {
 196             assertEquals(ppos.getErrorIndex(), expectedPos);
 197         } else {
 198             assertTrue(subsequentWidth >= 0);
 199             assertEquals(ppos.getIndex(), expectedPos + subsequentWidth);
 200             assertEquals(parsed.getLong(DAY_OF_WEEK), expectedValue);
 201             assertEquals(parsed.query(Queries.chronology()), null);
 202             assertEquals(parsed.query(Queries.zoneId()), null);
 203         }
 204     }
 205 
 206     //-----------------------------------------------------------------------
 207     @DataProvider(name="parseSignsStrict")
 208     Object[][] provider_parseSignsStrict() {
 209         return new Object[][] {
 210             // basics
 211             {"0", 1, 2, SignStyle.NEVER, 1, 0},
 212             {"1", 1, 2, SignStyle.NEVER, 1, 1},
 213             {"2", 1, 2, SignStyle.NEVER, 1, 2},
 214             {"3", 1, 2, SignStyle.NEVER, 1, 3},
 215             {"4", 1, 2, SignStyle.NEVER, 1, 4},
 216             {"5", 1, 2, SignStyle.NEVER, 1, 5},
 217             {"6", 1, 2, SignStyle.NEVER, 1, 6},
 218             {"7", 1, 2, SignStyle.NEVER, 1, 7},
 219             {"8", 1, 2, SignStyle.NEVER, 1, 8},
 220             {"9", 1, 2, SignStyle.NEVER, 1, 9},
 221             {"10", 1, 2, SignStyle.NEVER, 2, 10},
 222             {"100", 1, 2, SignStyle.NEVER, 2, 10},


 290             {"0", 1, 2, SignStyle.EXCEEDS_PAD, 1, 0},
 291             {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5},
 292             {"50", 1, 2, SignStyle.EXCEEDS_PAD, 0, null},
 293             {"500", 1, 2, SignStyle.EXCEEDS_PAD, 0, null},
 294             {"-0", 1, 2, SignStyle.EXCEEDS_PAD, 0, null},
 295             {"-5", 1, 2, SignStyle.EXCEEDS_PAD, 2, -5},
 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             {"+0", 1, 2, SignStyle.EXCEEDS_PAD, 0, null},
 300             {"+5", 1, 2, SignStyle.EXCEEDS_PAD, 0, null},
 301             {"+50", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
 302             {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
 303             {"+AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null},
 304        };
 305     }
 306 
 307     @Test(dataProvider="parseSignsStrict")
 308     public void test_parseSignsStrict(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception {
 309         ParsePosition pos = new ParsePosition(0);
 310         TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos);
 311         if (pos.getErrorIndex() != -1) {
 312             assertEquals(pos.getErrorIndex(), parseLen);
 313         } else {
 314             assertEquals(pos.getIndex(), parseLen);
 315             assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal);
 316             assertEquals(parsed.query(Queries.chronology()), null);
 317             assertEquals(parsed.query(Queries.zoneId()), null);
 318         }
 319     }
 320 
 321     //-----------------------------------------------------------------------
 322     @DataProvider(name="parseSignsLenient")
 323     Object[][] provider_parseSignsLenient() {
 324         return new Object[][] {
 325             // never
 326             {"0", 1, 2, SignStyle.NEVER, 1, 0},
 327             {"5", 1, 2, SignStyle.NEVER, 1, 5},
 328             {"50", 1, 2, SignStyle.NEVER, 2, 50},
 329             {"500", 1, 2, SignStyle.NEVER, 2, 50},
 330             {"-0", 1, 2, SignStyle.NEVER, 2, 0},
 331             {"-5", 1, 2, SignStyle.NEVER, 2, -5},
 332             {"-50", 1, 2, SignStyle.NEVER, 3, -50},
 333             {"-500", 1, 2, SignStyle.NEVER, 3, -50},
 334             {"-AAA", 1, 2, SignStyle.NEVER, 1, null},
 335             {"+0", 1, 2, SignStyle.NEVER, 2, 0},
 336             {"+5", 1, 2, SignStyle.NEVER, 2, 5},
 337             {"+50", 1, 2, SignStyle.NEVER, 3, 50},


 400             {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5},
 401             {"50", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50},
 402             {"500", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50},
 403             {"-0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0},
 404             {"-5", 1, 2, SignStyle.EXCEEDS_PAD, 2, -5},
 405             {"-50", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50},
 406             {"-500", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50},
 407             {"-AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null},
 408             {"+0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0},
 409             {"+5", 1, 2, SignStyle.EXCEEDS_PAD, 2, 5},
 410             {"+50", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
 411             {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
 412             {"+AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null},
 413        };
 414     }
 415 
 416     @Test(dataProvider="parseSignsLenient")
 417     public void test_parseSignsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception {
 418         setStrict(false);
 419         ParsePosition pos = new ParsePosition(0);
 420         TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos);
 421         if (pos.getErrorIndex() != -1) {
 422             assertEquals(pos.getErrorIndex(), parseLen);
 423         } else {
 424             assertEquals(pos.getIndex(), parseLen);
 425             assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal);
 426             assertEquals(parsed.query(Queries.chronology()), null);
 427             assertEquals(parsed.query(Queries.zoneId()), null);
 428         }
 429     }
 430 
 431     //-----------------------------------------------------------------------
 432     @DataProvider(name="parseDigitsLenient")
 433     Object[][] provider_parseDigitsLenient() {
 434         return new Object[][] {
 435                 // never
 436                 {"5", 1, 2, SignStyle.NEVER, 1, 5},
 437                 {"5", 2, 2, SignStyle.NEVER, 1, 5},
 438                 {"54", 1, 3, SignStyle.NEVER, 2, 54},
 439                 {"54", 2, 3, SignStyle.NEVER, 2, 54},
 440                 {"54", 3, 3, SignStyle.NEVER, 2, 54},
 441                 {"543", 1, 3, SignStyle.NEVER, 3, 543},
 442                 {"543", 2, 3, SignStyle.NEVER, 3, 543},
 443                 {"543", 3, 3, SignStyle.NEVER, 3, 543},
 444                 {"5432", 1, 3, SignStyle.NEVER, 3, 543},
 445                 {"5432", 2, 3, SignStyle.NEVER, 3, 543},
 446                 {"5432", 3, 3, SignStyle.NEVER, 3, 543},
 447                 {"5AAA", 2, 3, SignStyle.NEVER, 1, 5},


 491                 // exceeds pad
 492                 {"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5},
 493                 {"5", 2, 2, SignStyle.EXCEEDS_PAD, 1, 5},
 494                 {"54", 1, 3, SignStyle.EXCEEDS_PAD, 2, 54},
 495                 {"54", 2, 3, SignStyle.EXCEEDS_PAD, 2, 54},
 496                 {"54", 3, 3, SignStyle.EXCEEDS_PAD, 2, 54},
 497                 {"543", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 498                 {"543", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 499                 {"543", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 500                 {"5432", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 501                 {"5432", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 502                 {"5432", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543},
 503                 {"5AAA", 2, 3, SignStyle.EXCEEDS_PAD, 1, 5},
 504         };
 505     }
 506 
 507     @Test(dataProvider="parseDigitsLenient")
 508     public void test_parseDigitsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception {
 509         setStrict(false);
 510         ParsePosition pos = new ParsePosition(0);
 511         TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos);
 512         if (pos.getErrorIndex() != -1) {
 513             assertEquals(pos.getErrorIndex(), parseLen);
 514         } else {
 515             assertEquals(pos.getIndex(), parseLen);
 516             assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal);
 517             assertEquals(parsed.query(Queries.chronology()), null);
 518             assertEquals(parsed.query(Queries.zoneId()), null);
 519         }
 520     }
 521 
 522     //-----------------------------------------------------------------------
 523     @DataProvider(name="parseDigitsAdjacentLenient")
 524     Object[][] provider_parseDigitsAdjacentLenient() {
 525         return new Object[][] {
 526                 // never
 527                 {"5", 1, null, null},
 528                 {"54", 1, null, null},
 529 
 530                 {"543", 3, 5, 43},
 531                 {"543A", 3, 5, 43},
 532 
 533                 {"5432", 4, 54, 32},
 534                 {"5432A", 4, 54, 32},
 535 
 536                 {"54321", 4, 54, 32},
 537                 {"54321A", 4, 54, 32},
 538         };
 539     }
 540 
 541     @Test(dataProvider="parseDigitsAdjacentLenient")
 542     public void test_parseDigitsAdjacentLenient(String input, int parseLen, Integer parseMonth, Integer parsedDay) throws Exception {
 543         setStrict(false);
 544         ParsePosition pos = new ParsePosition(0);
 545         DateTimeFormatter f = builder
 546                 .appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL)
 547                 .appendValue(DAY_OF_MONTH, 2).toFormatter(locale).withSymbols(symbols);
 548         TemporalAccessor parsed = f.parseUnresolved(input, pos);
 549         if (pos.getErrorIndex() != -1) {
 550             assertEquals(pos.getErrorIndex(), parseLen);
 551         } else {
 552             assertEquals(pos.getIndex(), parseLen);
 553             assertEquals(parsed.getLong(MONTH_OF_YEAR), (long) parseMonth);
 554             assertEquals(parsed.getLong(DAY_OF_MONTH), (long) parsedDay);
 555             assertEquals(parsed.query(Queries.chronology()), null);
 556             assertEquals(parsed.query(Queries.zoneId()), null);
 557         }
 558     }
 559 
 560 }