1 /* 2 * Copyright (c) 2012, 2019, 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 static java.time.temporal.ChronoField.MILLI_OF_SECOND; 63 import static java.time.temporal.ChronoField.NANO_OF_SECOND; 64 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; 65 import static org.testng.Assert.assertEquals; 66 import static org.testng.Assert.fail; 67 68 import java.text.ParsePosition; 69 import java.time.DateTimeException; 70 import java.time.LocalTime; 71 import java.time.format.DateTimeFormatter; 72 import java.time.temporal.TemporalAccessor; 73 import java.time.temporal.TemporalField; 74 75 import org.testng.annotations.DataProvider; 76 import org.testng.annotations.Test; 77 import test.java.time.temporal.MockFieldValue; 78 79 /** 80 * Test FractionPrinterParser. 81 * 82 * @bug 8230136 83 */ 84 @Test 85 public class TestFractionPrinterParser extends AbstractTestPrinterParser { 86 getFormatter(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint)87 private DateTimeFormatter getFormatter(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { 88 return builder.appendFraction(field, minWidth, maxWidth, decimalPoint).toFormatter(locale).withDecimalStyle(decimalStyle); 89 } 90 91 //----------------------------------------------------------------------- 92 // print 93 //----------------------------------------------------------------------- 94 @Test(expectedExceptions=DateTimeException.class) test_print_emptyCalendrical()95 public void test_print_emptyCalendrical() throws Exception { 96 getFormatter(NANO_OF_SECOND, 0, 9, true).formatTo(EMPTY_DTA, buf); 97 } 98 test_print_append()99 public void test_print_append() throws Exception { 100 buf.append("EXISTING"); 101 getFormatter(NANO_OF_SECOND, 0, 9, true).formatTo(LocalTime.of(12, 30, 40, 3), buf); 102 assertEquals(buf.toString(), "EXISTING.000000003"); 103 } 104 105 //----------------------------------------------------------------------- 106 @DataProvider(name="Nanos") provider_nanos()107 Object[][] provider_nanos() { 108 return new Object[][] { 109 {0, 9, 0, ""}, 110 {0, 9, 2, ".000000002"}, 111 {0, 9, 20, ".00000002"}, 112 {0, 9, 200, ".0000002"}, 113 {0, 9, 2000, ".000002"}, 114 {0, 9, 20000, ".00002"}, 115 {0, 9, 200000, ".0002"}, 116 {0, 9, 2000000, ".002"}, 117 {0, 9, 20000000, ".02"}, 118 {0, 9, 200000000, ".2"}, 119 {0, 9, 1, ".000000001"}, 120 {0, 9, 12, ".000000012"}, 121 {0, 9, 123, ".000000123"}, 122 {0, 9, 1234, ".000001234"}, 123 {0, 9, 12345, ".000012345"}, 124 {0, 9, 123456, ".000123456"}, 125 {0, 9, 1234567, ".001234567"}, 126 {0, 9, 12345678, ".012345678"}, 127 {0, 9, 123456789, ".123456789"}, 128 129 {1, 9, 0, ".0"}, 130 {1, 9, 2, ".000000002"}, 131 {1, 9, 20, ".00000002"}, 132 {1, 9, 200, ".0000002"}, 133 {1, 9, 2000, ".000002"}, 134 {1, 9, 20000, ".00002"}, 135 {1, 9, 200000, ".0002"}, 136 {1, 9, 2000000, ".002"}, 137 {1, 9, 20000000, ".02"}, 138 {1, 9, 200000000, ".2"}, 139 140 {2, 3, 0, ".00"}, 141 {2, 3, 2, ".000"}, 142 {2, 3, 20, ".000"}, 143 {2, 3, 200, ".000"}, 144 {2, 3, 2000, ".000"}, 145 {2, 3, 20000, ".000"}, 146 {2, 3, 200000, ".000"}, 147 {2, 3, 2000000, ".002"}, 148 {2, 3, 20000000, ".02"}, 149 {2, 3, 200000000, ".20"}, 150 {2, 3, 1, ".000"}, 151 {2, 3, 12, ".000"}, 152 {2, 3, 123, ".000"}, 153 {2, 3, 1234, ".000"}, 154 {2, 3, 12345, ".000"}, 155 {2, 3, 123456, ".000"}, 156 {2, 3, 1234567, ".001"}, 157 {2, 3, 12345678, ".012"}, 158 {2, 3, 123456789, ".123"}, 159 160 {6, 6, 0, ".000000"}, 161 {6, 6, 2, ".000000"}, 162 {6, 6, 20, ".000000"}, 163 {6, 6, 200, ".000000"}, 164 {6, 6, 2000, ".000002"}, 165 {6, 6, 20000, ".000020"}, 166 {6, 6, 200000, ".000200"}, 167 {6, 6, 2000000, ".002000"}, 168 {6, 6, 20000000, ".020000"}, 169 {6, 6, 200000000, ".200000"}, 170 {6, 6, 1, ".000000"}, 171 {6, 6, 12, ".000000"}, 172 {6, 6, 123, ".000000"}, 173 {6, 6, 1234, ".000001"}, 174 {6, 6, 12345, ".000012"}, 175 {6, 6, 123456, ".000123"}, 176 {6, 6, 1234567, ".001234"}, 177 {6, 6, 12345678, ".012345"}, 178 {6, 6, 123456789, ".123456"}, 179 }; 180 } 181 182 @Test(dataProvider="Nanos") test_print_nanos(int minWidth, int maxWidth, int value, String result)183 public void test_print_nanos(int minWidth, int maxWidth, int value, String result) throws Exception { 184 getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).formatTo(new MockFieldValue(NANO_OF_SECOND, value), buf); 185 if (result == null) { 186 fail("Expected exception"); 187 } 188 assertEquals(buf.toString(), result); 189 } 190 191 @Test(dataProvider="Nanos") test_print_nanos_noDecimalPoint(int minWidth, int maxWidth, int value, String result)192 public void test_print_nanos_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { 193 getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).formatTo(new MockFieldValue(NANO_OF_SECOND, value), buf); 194 if (result == null) { 195 fail("Expected exception"); 196 } 197 assertEquals(buf.toString(), (result.startsWith(".") ? result.substring(1) : result)); 198 } 199 200 //----------------------------------------------------------------------- 201 @DataProvider(name="Seconds") provider_seconds()202 Object[][] provider_seconds() { 203 return new Object[][] { 204 {0, 9, 0, ""}, 205 {0, 9, 3, ".05"}, 206 {0, 9, 6, ".1"}, 207 {0, 9, 9, ".15"}, 208 {0, 9, 12, ".2"}, 209 {0, 9, 15, ".25"}, 210 {0, 9, 30, ".5"}, 211 {0, 9, 45, ".75"}, 212 213 {2, 2, 0, ".00"}, 214 {2, 2, 3, ".05"}, 215 {2, 2, 6, ".10"}, 216 {2, 2, 9, ".15"}, 217 {2, 2, 12, ".20"}, 218 {2, 2, 15, ".25"}, 219 {2, 2, 30, ".50"}, 220 {2, 2, 45, ".75"}, 221 }; 222 } 223 224 @Test(dataProvider="Seconds") test_print_seconds(int minWidth, int maxWidth, int value, String result)225 public void test_print_seconds(int minWidth, int maxWidth, int value, String result) throws Exception { 226 getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).formatTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); 227 if (result == null) { 228 fail("Expected exception"); 229 } 230 assertEquals(buf.toString(), result); 231 } 232 233 @Test(dataProvider="Seconds") test_print_seconds_noDecimalPoint(int minWidth, int maxWidth, int value, String result)234 public void test_print_seconds_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { 235 getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, false).formatTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); 236 if (result == null) { 237 fail("Expected exception"); 238 } 239 assertEquals(buf.toString(), (result.startsWith(".") ? result.substring(1) : result)); 240 } 241 242 //----------------------------------------------------------------------- 243 // parse 244 //----------------------------------------------------------------------- 245 @Test(dataProvider="Nanos") test_reverseParse(int minWidth, int maxWidth, int value, String result)246 public void test_reverseParse(int minWidth, int maxWidth, int value, String result) throws Exception { 247 ParsePosition pos = new ParsePosition(0); 248 int expectedValue = fixParsedValue(maxWidth, value); 249 TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(result, pos); 250 assertEquals(pos.getIndex(), result.length()); 251 assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); 252 } 253 254 @Test(dataProvider="Nanos") test_reverseParse_noDecimalPoint(int minWidth, int maxWidth, int value, String result)255 public void test_reverseParse_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { 256 ParsePosition pos = new ParsePosition((result.startsWith(".") ? 1 : 0)); 257 TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).parseUnresolved(result, pos); 258 assertEquals(pos.getIndex(), result.length()); 259 int expectedValue = fixParsedValue(maxWidth, value); 260 assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); 261 } 262 263 @Test(dataProvider="Nanos") test_reverseParse_followedByNonDigit(int minWidth, int maxWidth, int value, String result)264 public void test_reverseParse_followedByNonDigit(int minWidth, int maxWidth, int value, String result) throws Exception { 265 ParsePosition pos = new ParsePosition(0); 266 int expectedValue = fixParsedValue(maxWidth, value); 267 TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(result + " ", pos); 268 assertEquals(pos.getIndex(), result.length()); 269 assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); 270 } 271 272 // @Test(dataProvider="Nanos") 273 // public void test_reverseParse_followedByNonDigit_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { 274 // FractionPrinterParser pp = new FractionPrinterParser(NANO_OF_SECOND, minWidth, maxWidth, false); 275 // int newPos = pp.parse(parseContext, result + " ", (result.startsWith(".") ? 1 : 0)); 276 // assertEquals(newPos, result.length()); 277 // int expectedValue = fixParsedValue(maxWidth, value); 278 // assertParsed(parseContext, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); 279 // } 280 281 @Test(dataProvider="Nanos") test_reverseParse_preceededByNonDigit(int minWidth, int maxWidth, int value, String result)282 public void test_reverseParse_preceededByNonDigit(int minWidth, int maxWidth, int value, String result) throws Exception { 283 ParsePosition pos = new ParsePosition(1); 284 int expectedValue = fixParsedValue(maxWidth, value); 285 TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(" " + result, pos); 286 assertEquals(pos.getIndex(), result.length() + 1); 287 assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); 288 } 289 fixParsedValue(int maxWidth, int value)290 private int fixParsedValue(int maxWidth, int value) { 291 if (maxWidth < 9) { 292 int power = (int) Math.pow(10, (9 - maxWidth)); 293 value = (value / power) * power; 294 } 295 return value; 296 } 297 298 @Test(dataProvider="Seconds") test_reverseParse_seconds(int minWidth, int maxWidth, int value, String result)299 public void test_reverseParse_seconds(int minWidth, int maxWidth, int value, String result) throws Exception { 300 ParsePosition pos = new ParsePosition(0); 301 TemporalAccessor parsed = getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).parseUnresolved(result, pos); 302 assertEquals(pos.getIndex(), result.length()); 303 assertParsed(parsed, SECOND_OF_MINUTE, value == 0 && minWidth == 0 ? null : (long) value); 304 } 305 assertParsed(TemporalAccessor parsed, TemporalField field, Long value)306 private void assertParsed(TemporalAccessor parsed, TemporalField field, Long value) { 307 if (value == null) { 308 assertEquals(parsed.isSupported(field), false); 309 } else { 310 assertEquals(parsed.isSupported(field), true); 311 assertEquals(parsed.getLong(field), (long) value); 312 } 313 } 314 315 //----------------------------------------------------------------------- 316 @DataProvider(name="ParseNothing") provider_parseNothing()317 Object[][] provider_parseNothing() { 318 return new Object[][] { 319 {NANO_OF_SECOND, 3, 6, true, "", 0, 0}, 320 {NANO_OF_SECOND, 3, 6, true, "A", 0, 0}, 321 {NANO_OF_SECOND, 3, 6, true, ".", 0, 1}, 322 {NANO_OF_SECOND, 3, 6, true, ".5", 0, 1}, 323 {NANO_OF_SECOND, 3, 6, true, ".51", 0, 1}, 324 {NANO_OF_SECOND, 3, 6, true, ".A23456", 0, 1}, 325 {NANO_OF_SECOND, 3, 6, true, ".1A3456", 0, 1}, 326 }; 327 } 328 329 @Test(dataProvider = "ParseNothing") test_parse_nothing(TemporalField field, int min, int max, boolean decimalPoint, String text, int pos, int expected)330 public void test_parse_nothing(TemporalField field, int min, int max, boolean decimalPoint, String text, int pos, int expected) { 331 ParsePosition ppos = new ParsePosition(pos); 332 TemporalAccessor parsed = getFormatter(field, min, max, decimalPoint).parseUnresolved(text, ppos); 333 assertEquals(ppos.getErrorIndex(), expected); 334 assertEquals(parsed, null); 335 } 336 337 @DataProvider(name="ParseMinWidth") provider_parseMinWidth()338 Object[][] provider_parseMinWidth() { 339 return new Object[][] { 340 {MILLI_OF_SECOND, 3, 3, true, ".1x"}, 341 {MILLI_OF_SECOND, 3, 3, true, ".12x"}, 342 {MILLI_OF_SECOND, 3, 3, true, ".1234x"}, 343 }; 344 } 345 346 @Test(dataProvider="ParseMinWidth", expectedExceptions=DateTimeException.class) test_parse_minWidth(TemporalField field, int min, int max, boolean decimalPoint, String text)347 public void test_parse_minWidth(TemporalField field, int min, int max, boolean decimalPoint, String text) throws Exception { 348 builder 349 .appendFraction(field, min, max, decimalPoint) 350 .appendLiteral("x") 351 .toFormatter(locale) 352 .parse(text); 353 } 354 355 //----------------------------------------------------------------------- test_toString()356 public void test_toString() throws Exception { 357 assertEquals(getFormatter(NANO_OF_SECOND, 3, 6, true).toString(), "Fraction(NanoOfSecond,3,6,DecimalPoint)"); 358 } 359 test_toString_noDecimalPoint()360 public void test_toString_noDecimalPoint() throws Exception { 361 assertEquals(getFormatter(NANO_OF_SECOND, 3, 6, false).toString(), "Fraction(NanoOfSecond,3,6)"); 362 } 363 364 } 365