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) 2009-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;
  61 
  62 import java.time.*;
  63 
  64 import static java.time.temporal.ChronoUnit.DAYS;
  65 import static java.time.temporal.ChronoUnit.HOURS;
  66 import static java.time.temporal.ChronoUnit.MINUTES;
  67 import static java.time.temporal.ChronoUnit.MONTHS;
  68 import static java.time.temporal.ChronoUnit.NANOS;
  69 import static java.time.temporal.ChronoUnit.SECONDS;
  70 import static java.time.temporal.ChronoUnit.YEARS;
  71 import static org.testng.Assert.assertEquals;
  72 
  73 import java.time.format.DateTimeParseException;
  74 
  75 import org.testng.annotations.DataProvider;
  76 import org.testng.annotations.Test;
  77 
  78 /**
  79  * Test PeriodParser.
  80  */
  81 @Test
  82 public class TestPeriodParser {
  83 
  84     //-----------------------------------------------------------------------
  85     // parse(String)
  86     //-----------------------------------------------------------------------
  87     @DataProvider(name="Parse")
  88     Object[][] provider_factory_parse() {
  89         return new Object[][] {
  90             {"Pt0S", Period.ZERO},
  91             {"pT0S", Period.ZERO},
  92             {"PT0S", Period.ZERO},
  93             {"Pt0s", Period.ZERO},
  94             {"pt0s", Period.ZERO},
  95             {"P0Y0M0DT0H0M0.0S", Period.ZERO},
  96 
  97             {"P1Y", Period.of(1, YEARS)},
  98             {"P100Y", Period.of(100, YEARS)},
  99             {"P-25Y", Period.of(-25, YEARS)},
 100             {"P" + Integer.MAX_VALUE + "Y", Period.of(Integer.MAX_VALUE, YEARS)},
 101             {"P" + Integer.MIN_VALUE + "Y", Period.of(Integer.MIN_VALUE, YEARS)},
 102 
 103             {"P1M", Period.of(1, MONTHS)},
 104             {"P0M", Period.of(0, MONTHS)},
 105             {"P-1M", Period.of(-1, MONTHS)},
 106             {"P" + Integer.MAX_VALUE + "M", Period.of(Integer.MAX_VALUE, MONTHS)},
 107             {"P" + Integer.MIN_VALUE + "M", Period.of(Integer.MIN_VALUE, MONTHS)},
 108 
 109             {"P1D", Period.of(1, DAYS)},
 110             {"P0D", Period.of(0, DAYS)},
 111             {"P-1D", Period.of(-1, DAYS)},
 112             {"P" + Integer.MAX_VALUE + "D", Period.of(Integer.MAX_VALUE, DAYS)},
 113             {"P" + Integer.MIN_VALUE + "D", Period.of(Integer.MIN_VALUE, DAYS)},
 114 
 115             {"P2Y3M25D", Period.ofDate(2, 3, 25)},
 116 
 117             {"PT1H", Period.of(1, HOURS)},
 118             {"PT-1H", Period.of(-1, HOURS)},
 119             {"PT24H", Period.of(24, HOURS)},
 120             {"PT-24H", Period.of(-24, HOURS)},
 121             {"PT" + Integer.MAX_VALUE / (3600 * 8) + "H", Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS)},
 122             {"PT" + Integer.MIN_VALUE / (3600 * 8) + "H", Period.of(Integer.MIN_VALUE / (3600 * 8), HOURS)},
 123 
 124             {"PT1M", Period.of(1, MINUTES)},
 125             {"PT-1M", Period.of(-1, MINUTES)},
 126             {"PT60M", Period.of(60, MINUTES)},
 127             {"PT-60M", Period.of(-60, MINUTES)},
 128             {"PT" + Integer.MAX_VALUE / (60 * 8) + "M", Period.of(Integer.MAX_VALUE / (60 * 8), MINUTES)},
 129             {"PT" + Integer.MIN_VALUE / (60 * 8) + "M", Period.of(Integer.MIN_VALUE / (60 * 8), MINUTES)},
 130 
 131             {"PT1S", Period.of(1, SECONDS)},
 132             {"PT-1S", Period.of(-1, SECONDS)},
 133             {"PT60S", Period.of(60, SECONDS)},
 134             {"PT-60S", Period.of(-60, SECONDS)},
 135             {"PT" + Integer.MAX_VALUE + "S", Period.of(Integer.MAX_VALUE, SECONDS)},
 136             {"PT" + Integer.MIN_VALUE + "S", Period.of(Integer.MIN_VALUE, SECONDS)},
 137 
 138             {"PT0.1S", Period.of( 0, 0, 0, 0, 0, 0, 100000000 ) },
 139             {"PT-0.1S", Period.of( 0, 0, 0, 0, 0, 0, -100000000 ) },
 140             {"PT1.1S", Period.of( 0, 0, 0, 0, 0, 1, 100000000 ) },
 141             {"PT-1.1S", Period.of( 0, 0, 0, 0, 0, -1, -100000000 ) },
 142             {"PT1.0001S", Period.of(1, SECONDS).plus( 100000, NANOS ) },
 143             {"PT1.0000001S", Period.of(1, SECONDS).plus( 100, NANOS ) },
 144             {"PT1.123456789S", Period.of( 0, 0, 0, 0, 0, 1, 123456789 ) },
 145             {"PT1.999999999S", Period.of( 0, 0, 0, 0, 0, 1, 999999999 ) },
 146 
 147         };
 148     }
 149 
 150     @Test(dataProvider="Parse")
 151     public void factory_parse(String text, Period expected) {
 152         Period p = Period.parse(text);
 153         assertEquals(p, expected);
 154     }
 155 
 156     @Test(dataProvider="Parse")
 157     public void factory_parse_comma(String text, Period expected) {
 158         if (text.contains(".")) {
 159             text = text.replace('.', ',');
 160             Period p = Period.parse(text);
 161             assertEquals(p, expected);
 162         }
 163     }
 164 
 165     @DataProvider(name="ParseFailures")
 166     Object[][] provider_factory_parseFailures() {
 167         return new Object[][] {
 168             {"", 0},
 169             {"PTS", 2},
 170             {"AT0S", 0},
 171             {"PA0S", 1},
 172             {"PT0A", 3},
 173 
 174             {"PT+S", 2},
 175             {"PT-S", 2},
 176             {"PT.S", 2},
 177             {"PTAS", 2},
 178 
 179             {"PT+0S", 2},
 180             {"PT-0S", 2},
 181             {"PT+1S", 2},
 182             {"PT-.S", 2},
 183 
 184             {"PT1ABC2S", 3},
 185             {"PT1.1ABC2S", 5},
 186 
 187             {"PT123456789123456789123456789S", 2},
 188             {"PT0.1234567891S", 4},
 189             {"PT1.S", 2},
 190             {"PT.1S", 2},
 191 
 192             {"PT2.-3S", 2},
 193             {"PT-2.-3S", 2},
 194 
 195             {"P1Y1MT1DT1M1S", 7},
 196             {"P1Y1MT1HT1M1S", 8},
 197             {"P1YMD", 3},
 198             {"PT1ST1D", 4},
 199             {"P1Y2Y", 4},
 200             {"PT1M+3S", 4},
 201 
 202             {"PT1S1", 4},
 203             {"PT1S.", 4},
 204             {"PT1SA", 4},
 205             {"PT1M1", 4},
 206             {"PT1M.", 4},
 207             {"PT1MA", 4},
 208         };
 209     }
 210 
 211     @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class)
 212     public void factory_parseFailures(String text, int errPos) {
 213         try {
 214             Period.parse(text);
 215         } catch (DateTimeParseException ex) {
 216             assertEquals(ex.getParsedString(), text);
 217             assertEquals(ex.getErrorIndex(), errPos);
 218             throw ex;
 219         }
 220     }
 221 
 222     @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class)
 223     public void factory_parseFailures_comma(String text, int errPos) {
 224         text = text.replace('.', ',');
 225         try {
 226             Period.parse(text);
 227         } catch (DateTimeParseException ex) {
 228             assertEquals(ex.getParsedString(), text);
 229             assertEquals(ex.getErrorIndex(), errPos);
 230             throw ex;
 231         }
 232     }
 233 
 234     @Test(expectedExceptions=DateTimeParseException.class)
 235     public void factory_parse_tooBig() {
 236         String text = "PT" + Long.MAX_VALUE + "1S";
 237         Period.parse(text);
 238     }
 239 
 240     @Test(expectedExceptions=DateTimeParseException.class)
 241     public void factory_parse_tooBig_decimal() {
 242         String text = "PT" + Long.MAX_VALUE + "1.1S";
 243         Period.parse(text);
 244     }
 245 
 246     @Test(expectedExceptions=DateTimeParseException.class)
 247     public void factory_parse_tooSmall() {
 248         String text = "PT" + Long.MIN_VALUE + "1S";
 249         Period.parse(text);
 250     }
 251 
 252     @Test(expectedExceptions=DateTimeParseException.class)
 253     public void factory_parse_tooSmall_decimal() {
 254         String text = "PT" + Long.MIN_VALUE + ".1S";
 255         Period.parse(text);
 256     }
 257 
 258     @Test(expectedExceptions=NullPointerException.class)
 259     public void factory_parse_null() {
 260         Period.parse(null);
 261     }
 262 
 263     @DataProvider(name="ParseSequenceFailures")
 264     Object[][] provider_factory_parseSequenceFailures() {
 265         return new Object[][] {
 266             {"P0M0Y0DT0H0M0.0S"},
 267             {"P0M0D0YT0H0M0.0S"},
 268             {"P0S0D0YT0S0M0.0H"},
 269             {"PT0M0H0.0S"},
 270             {"PT0M0H"},
 271             {"PT0S0M"},
 272             {"PT0.0M2S"},
 273         };
 274     }
 275 
 276     @Test(dataProvider="ParseSequenceFailures", expectedExceptions=DateTimeParseException.class)
 277     public void factory_parse_badSequence(String text) {
 278         Period.parse(text);
 279     }
 280 
 281 }