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