1 /*
   2  * Copyright (c) 2014, 2015, 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 package datatype;
  25 
  26 import java.math.BigDecimal;
  27 import java.math.BigInteger;
  28 
  29 import javax.xml.datatype.DatatypeConfigurationException;
  30 import javax.xml.datatype.DatatypeConstants;
  31 import javax.xml.datatype.DatatypeFactory;
  32 import javax.xml.datatype.Duration;
  33 import javax.xml.namespace.QName;
  34 
  35 import org.testng.Assert;
  36 import org.testng.annotations.Test;
  37 
  38 /*
  39  * @bug 6937964
  40  * @summary Test Duration is normalized.
  41  */
  42 public class Bug6937964Test {
  43     /**
  44      * Print debugging to System.err.
  45      */
  46     private static final boolean DEBUG = false;
  47     /**
  48      * Constant to indicate expected lexical test failure.
  49      */
  50     private static final String TEST_VALUE_FAIL = "*FAIL*";
  51 
  52     private static final String FIELD_UNDEFINED = "FIELD_UNDEFINED";
  53     static final DatatypeConstants.Field[] fields = { DatatypeConstants.YEARS, DatatypeConstants.MONTHS, DatatypeConstants.DAYS, DatatypeConstants.HOURS,
  54             DatatypeConstants.MINUTES, DatatypeConstants.SECONDS };
  55 
  56     @Test
  57     public void test() throws DatatypeConfigurationException {
  58         DatatypeFactory dtf = DatatypeFactory.newInstance();
  59         Duration d = dtf.newDurationYearMonth("P20Y15M");
  60         int years = d.getYears();
  61         System.out.println(d.getYears() == 21 ? "pass" : "fail");
  62     }
  63 
  64     @Test
  65     public void testNewDurationYearMonthLexicalRepresentation() throws DatatypeConfigurationException {
  66         DatatypeFactory dtf = DatatypeFactory.newInstance();
  67         Duration d = dtf.newDurationYearMonth("P20Y15M");
  68         int years = d.getYears();
  69         Assert.assertTrue(years == 21, "Return value should be normalized");
  70     }
  71 
  72     @Test
  73     public void testNewDurationYearMonthMilliseconds() throws DatatypeConfigurationException {
  74         DatatypeFactory dtf = DatatypeFactory.newInstance();
  75         Duration d = dtf.newDurationYearMonth(671976000000L);
  76         int years = d.getYears();
  77         System.out.println("Years: " + years);
  78         Assert.assertTrue(years == 21, "Return value should be normalized");
  79     }
  80 
  81     @Test
  82     public void testNewDurationYearMonthBigInteger() throws DatatypeConfigurationException {
  83         DatatypeFactory dtf = DatatypeFactory.newInstance();
  84         BigInteger year = new BigInteger("20");
  85         BigInteger mon = new BigInteger("15");
  86         Duration d = dtf.newDurationYearMonth(true, year, mon);
  87         int years = d.getYears();
  88         Assert.assertTrue(years == 21, "Return value should be normalized");
  89     }
  90 
  91     @Test
  92     public void testNewDurationYearMonthInt() throws DatatypeConfigurationException {
  93         DatatypeFactory dtf = DatatypeFactory.newInstance();
  94         Duration d = dtf.newDurationYearMonth(true, 20, 15);
  95         int years = d.getYears();
  96         Assert.assertTrue(years == 21, "Return value should be normalized");
  97     }
  98 
  99     @Test
 100     public void testNewDurationDayTimeLexicalRepresentation() throws DatatypeConfigurationException {
 101         DatatypeFactory dtf = DatatypeFactory.newInstance();
 102         Duration d = dtf.newDurationDayTime("P1DT23H59M65S");
 103         int days = d.getDays();
 104         Assert.assertTrue(days == 2, "Return value should be normalized");
 105     }
 106 
 107     @Test
 108     public void testNewDurationDayTimeMilliseconds() throws DatatypeConfigurationException {
 109         DatatypeFactory dtf = DatatypeFactory.newInstance();
 110         Duration d = dtf.newDurationDayTime(172805000L);
 111         int days = d.getDays();
 112         Assert.assertTrue(days == 2, "Return value should be normalized");
 113     }
 114 
 115     @Test
 116     public void testNewDurationDayTimeBigInteger() throws DatatypeConfigurationException {
 117         DatatypeFactory dtf = DatatypeFactory.newInstance();
 118         BigInteger day = new BigInteger("1");
 119         BigInteger hour = new BigInteger("23");
 120         BigInteger min = new BigInteger("59");
 121         BigInteger sec = new BigInteger("65");
 122         Duration d = dtf.newDurationDayTime(true, day, hour, min, sec);
 123         int days = d.getDays();
 124         System.out.println("Days: " + days);
 125         Assert.assertTrue(days == 2, "Return value should be normalized");
 126     }
 127 
 128     @Test
 129     public void testNewDurationDayTimeInt() throws DatatypeConfigurationException {
 130         DatatypeFactory dtf = DatatypeFactory.newInstance();
 131         Duration d = dtf.newDurationDayTime(true, 1, 23, 59, 65);
 132         int days = d.getDays();
 133         System.out.println("Days: " + days);
 134         Assert.assertTrue(days == 2, "Return value should be normalized");
 135     }
 136 
 137     @Test
 138     public final void testNewDurationYearMonthLexicalRepresentation1() {
 139 
 140         /**
 141          * Lexical test values to test.
 142          */
 143         final String[] TEST_VALUES_LEXICAL = { "P13M", "P1Y1M", "-P13M", "-P1Y1M", "P1Y", "P1Y", "-P1Y", "-P1Y", "P1Y25M", "P3Y1M", "-P1Y25M", "-P3Y1M" };
 144 
 145         DatatypeFactory datatypeFactory = null;
 146         try {
 147             datatypeFactory = DatatypeFactory.newInstance();
 148         } catch (DatatypeConfigurationException datatypeConfigurationException) {
 149             Assert.fail(datatypeConfigurationException.toString());
 150         }
 151 
 152         if (DEBUG) {
 153             System.err.println("DatatypeFactory created: " + datatypeFactory.toString());
 154         }
 155 
 156         // test each value
 157         for (int onTestValue = 0; onTestValue < TEST_VALUES_LEXICAL.length; onTestValue = onTestValue + 2) {
 158 
 159             if (DEBUG) {
 160                 System.err.println("testing value: \"" + TEST_VALUES_LEXICAL[onTestValue] + "\", expecting: \"" + TEST_VALUES_LEXICAL[onTestValue + 1] + "\"");
 161             }
 162 
 163             try {
 164                 Duration duration = datatypeFactory.newDurationYearMonth(TEST_VALUES_LEXICAL[onTestValue]);
 165 
 166                 if (DEBUG) {
 167                     System.err.println("Duration created: \"" + duration.toString() + "\"");
 168                 }
 169 
 170                 // was this expected to fail?
 171                 if (TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) {
 172                     Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\"");
 173                 }
 174 
 175                 // right XMLSchemaType?
 176                 // TODO: enable test, it should pass, it fails with Exception(s)
 177                 // for now due to a bug
 178                 try {
 179                     QName xmlSchemaType = duration.getXMLSchemaType();
 180                     if (!xmlSchemaType.equals(DatatypeConstants.DURATION_YEARMONTH)) {
 181                         Assert.fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \""
 182                                 + DatatypeConstants.DURATION_YEARMONTH + "\" and has the value \"" + duration.toString() + "\"");
 183                     }
 184                 } catch (IllegalStateException illegalStateException) {
 185                     // TODO; this test really should pass
 186                     System.err.println("Please fix this bug that is being ignored, for now: " + illegalStateException.getMessage());
 187                 }
 188 
 189                 // does it have the right value?
 190                 if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(duration.toString())) {
 191                     Assert.fail("Duration created with \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" was expected to be \""
 192                             + TEST_VALUES_LEXICAL[onTestValue + 1] + "\" and has the value \"" + duration.toString() + "\"");
 193                 }
 194 
 195                 // Duration created with correct value
 196             } catch (Exception exception) {
 197 
 198                 if (DEBUG) {
 199                     System.err.println("Exception in creating duration: \"" + exception.toString() + "\"");
 200                 }
 201 
 202                 // was this expected to succed?
 203                 if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) {
 204                     Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\"");
 205                 }
 206                 // expected failure
 207             }
 208         }
 209     }
 210 
 211     /**
 212      * TCK test failure
 213      */
 214     @Test
 215     public void testNewDurationDayTime005() {
 216         BigInteger one = new BigInteger("1");
 217         BigInteger zero = new BigInteger("0");
 218         BigDecimal bdZero = new BigDecimal("0");
 219         BigDecimal bdOne = new BigDecimal("1");
 220 
 221         Object[][] values = {
 222                 // lex, isPositive, years, month, days, hours, minutes, seconds
 223                 { "P1D", Boolean.TRUE, null, null, one, zero, zero, bdZero }, { "PT1H", Boolean.TRUE, null, null, zero, one, zero, bdZero },
 224                 { "PT1M", Boolean.TRUE, null, null, zero, zero, one, bdZero }, { "PT1.1S", Boolean.TRUE, null, null, zero, zero, zero, bdOne },
 225                 { "-PT1H1.1S", Boolean.FALSE, null, null, zero, one, zero, bdOne }, };
 226 
 227         StringBuffer result = new StringBuffer();
 228         DatatypeFactory df = null;
 229 
 230         try {
 231             df = DatatypeFactory.newInstance();
 232         } catch (DatatypeConfigurationException e) {
 233             Assert.fail(e.toString());
 234         }
 235 
 236         for (int valueIndex = 0; valueIndex < values.length; ++valueIndex) {
 237             Duration duration = null;
 238             try {
 239                 duration = df.newDurationDayTime(values[valueIndex][1].equals(Boolean.TRUE), ((BigInteger) values[valueIndex][4]).intValue(),
 240                         ((BigInteger) values[valueIndex][5]).intValue(), ((BigInteger) values[valueIndex][6]).intValue(),
 241                         ((BigDecimal) values[valueIndex][7]).intValue());
 242             } catch (IllegalArgumentException e) {
 243                 result.append("; unexpected " + e + " trying to create duration \'" + values[valueIndex][0] + "\'");
 244             }
 245             if (duration != null) {
 246                 if ((duration.getSign() == 1) != values[valueIndex][1].equals(Boolean.TRUE)) {
 247                     result.append("; " + values[valueIndex][0] + ": wrong sign " + duration.getSign() + ", expected " + values[valueIndex][1]);
 248                 }
 249                 for (int i = 0; i < fields.length; ++i) {
 250                     Number value = duration.getField(fields[i]);
 251                     if ((value != null && values[valueIndex][2 + i] == null) || (value == null && values[valueIndex][2 + i] != null)
 252                             || (value != null && !value.equals(values[valueIndex][2 + i]))) {
 253                         result.append("; " + values[valueIndex][0] + ": wrong value of the field " + fields[i] + ": \'" + value + "\'" + ", expected \'"
 254                                 + values[valueIndex][2 + i] + "\'");
 255                     }
 256                 }
 257             }
 258         }
 259 
 260         if (result.length() > 0) {
 261             Assert.fail(result.substring(2));
 262         }
 263         System.out.println("OK");
 264 
 265     }
 266 }