/* * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.xml.datatype.ptests; import static javax.xml.datatype.DatatypeConstants.DAYS; import static javax.xml.datatype.DatatypeConstants.HOURS; import static javax.xml.datatype.DatatypeConstants.MINUTES; import static javax.xml.datatype.DatatypeConstants.MONTHS; import static javax.xml.datatype.DatatypeConstants.SECONDS; import static javax.xml.datatype.DatatypeConstants.YEARS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Calendar; import java.util.function.Function; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import javax.xml.namespace.QName; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Listeners; import org.testng.annotations.Test; /* * @test * @library /javax/xml/jaxp/libs * @run testng/othervm -DrunSecMngr=true javax.xml.datatype.ptests.DurationTest * @run testng/othervm javax.xml.datatype.ptests.DurationTest * @summary Class containing the test cases for Duration. */ @Listeners({jaxp.library.BasePolicy.class}) public class DurationTest { private DatatypeFactory datatypeFactory; /* * Setup. */ @BeforeClass public void setup() throws DatatypeConfigurationException { datatypeFactory = DatatypeFactory.newInstance(); } @DataProvider(name = "legal-number-duration") public Object[][] getLegalNumberDuration() { return new Object[][] { // is positive, year, month, day, hour, minute, second { true, 1, 1, 1, 1, 1, 1 }, { false, 1, 1, 1, 1, 1, 1 }, { true, 1, 0, 0, 0, 0, 0 }, { false, 1, 0, 0, 0, 0, 0 } }; } /* * Test for constructor Duration(boolean isPositive,int years,int months, * int days,int hours,int minutes,int seconds). */ @Test(dataProvider = "legal-number-duration") public void checkNumberDurationPos(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds) { datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); } @DataProvider(name = "illegal-number-duration") public Object[][] getIllegalNumberDuration() { return new Object[][] { // is positive, year, month, day, hour, minute, second { true, 1, 1, -1, 1, 1, 1 }, { false, 1, 1, -1, 1, 1, 1 }, { true, undef, undef, undef, undef, undef, undef }, { false, undef, undef, undef, undef, undef, undef } }; } /* * Test for constructor Duration(boolean isPositive,int years,int months, * int days,int hours,int minutes,int seconds), if any of the fields is * negative should throw IllegalArgumentException. */ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegal-number-duration") public void checkDurationNumberNeg(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds) { datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); } @DataProvider(name = "legal-bigint-duration") public Object[][] getLegalBigIntegerDuration() { return new Object[][] { // is positive, year, month, day, hour, minute, second { true, zero, zero, zero, zero, zero, new BigDecimal(zero) }, { false, zero, zero, zero, zero, zero, new BigDecimal(zero) }, { true, one, one, one, one, one, new BigDecimal(one) }, { false, one, one, one, one, one, new BigDecimal(one) }, { true, null, null, null, null, null, new BigDecimal(one) }, { false, null, null, null, null, null, new BigDecimal(one) } }; } /* * Test for constructor Duration(boolean isPositive,BigInteger * years,BigInteger months, BigInteger days,BigInteger hours,BigInteger * minutes,BigDecimal seconds). */ @Test(dataProvider = "legal-bigint-duration") public void checkBigIntegerDurationPos(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes, BigDecimal seconds) { datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); } @DataProvider(name = "illegal-bigint-duration") public Object[][] getIllegalBigIntegerDuration() { return new Object[][] { // is positive, year, month, day, hour, minute, second { true, null, null, null, null, null, null }, { false, null, null, null, null, null, null } }; } /* * Test for constructor Duration(boolean isPositive,BigInteger * years,BigInteger months, BigInteger days,BigInteger hours,BigInteger * minutes,BigDecimal seconds), if all the fields are null should throw * IllegalArgumentException. */ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegal-bigint-duration") public void checkBigIntegerDurationNeg(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes, BigDecimal seconds) { datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); } @DataProvider(name = "legal-millisec-duration") public Object[][] getLegalMilliSecondDuration() { return new Object[][] { { 1000000 }, { 0 }, { Long.MAX_VALUE }, { Long.MIN_VALUE } }; } /* * Test for constructor Duration(long durationInMilliSeconds) */ @Test(dataProvider = "legal-millisec-duration") public void checkMilliSecondDuration(long millisec) { datatypeFactory.newDuration(millisec); } @DataProvider(name = "legal-lexical-duration") public Object[][] getLegalLexicalDuration() { return new Object[][] { { "P1Y1M1DT1H1M1S" }, { "-P1Y1M1DT1H1M1S" } }; } /* * Test for constructor Duration(java.lang.String lexicalRepresentation) */ @Test(dataProvider = "legal-lexical-duration") public void checkLexicalDurationPos(String lexRepresentation) { datatypeFactory.newDuration(lexRepresentation); } @DataProvider(name = "illegal-lexical-duration") public Object[][] getIllegalLexicalDuration() { return new Object[][] { { null }, { "P1Y1M1DT1H1M1S " }, { " P1Y1M1DT1H1M1S" }, { "X1Y1M1DT1H1M1S" }, { "" }, { "P1Y2MT" } // The designator 'T' shall be absent if all of the time items are absent in "PnYnMnDTnHnMnS" }; } /* * Test for constructor Duration(java.lang.String lexicalRepresentation), * null should throw NullPointerException, invalid lex should throw * IllegalArgumentException */ @Test(expectedExceptions = { NullPointerException.class, IllegalArgumentException.class }, dataProvider = "illegal-lexical-duration") public void checkLexicalDurationNeg(String lexRepresentation) { datatypeFactory.newDuration(lexRepresentation); } @DataProvider(name = "equal-duration") public Object[][] getEqualDurations() { return new Object[][] { { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" } }; } /* * Test for compare() both durations valid and equal. */ @Test(dataProvider = "equal-duration") public void checkDurationEqual(String lexRepresentation1, String lexRepresentation2) { Duration duration1 = datatypeFactory.newDuration(lexRepresentation1); Duration duration2 = datatypeFactory.newDuration(lexRepresentation2); assertTrue(duration1.equals(duration2)); } @DataProvider(name = "greater-duration") public Object[][] getGreaterDuration() { return new Object[][] { { "P1Y1M1DT1H1M2S", "P1Y1M1DT1H1M1S" }, { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M2S" }, { "P1Y1M1DT1H1M2S", "-P1Y1M1DT1H1M1S" }, { "-P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M2S" }, }; } /* * Test for compare() both durations valid and lhs > rhs. */ @Test(dataProvider = "greater-duration") public void checkDurationCompare(String lexRepresentation1, String lexRepresentation2) { Duration duration1 = datatypeFactory.newDuration(lexRepresentation1); Duration duration2 = datatypeFactory.newDuration(lexRepresentation2); assertTrue(duration1.compare(duration2) == DatatypeConstants.GREATER); } @DataProvider(name = "not-equal-duration") public Object[][] getNotEqualDurations() { return new Object[][] { { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S" }, { "P2Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" } }; } /* * Test for equals() both durations valid and lhs not equals rhs. */ @Test(dataProvider = "not-equal-duration") public void checkDurationNotEqual(String lexRepresentation1, String lexRepresentation2) { Duration duration1 = datatypeFactory.newDuration(lexRepresentation1); Duration duration2 = datatypeFactory.newDuration(lexRepresentation2); Assert.assertNotEquals(duration1, duration2); } @DataProvider(name = "duration-sign") public Object[][] getDurationAndSign() { return new Object[][] { { "P0Y0M0DT0H0M0S", 0 }, { "P1Y0M0DT0H0M0S", 1 }, { "-P1Y0M0DT0H0M0S", -1 } }; } /* * Test for Duration.getSign(). */ @Test(dataProvider = "duration-sign") public void checkDurationSign(String lexRepresentation, int sign) { Duration duration = datatypeFactory.newDuration(lexRepresentation); assertEquals(duration.getSign(), sign); } /* * Test for Duration.negate(). */ @Test public void checkDurationNegate() { Duration durationPos = datatypeFactory.newDuration("P1Y0M0DT0H0M0S"); Duration durationNeg = datatypeFactory.newDuration("-P1Y0M0DT0H0M0S"); assertEquals(durationPos.negate(), durationNeg); assertEquals(durationNeg.negate(), durationPos); assertEquals(durationPos.negate().negate(), durationPos); } /* * Test for Duration.isShorterThan(Duration) and * Duration.isLongerThan(Duration). */ @Test public void checkDurationShorterLonger() { Duration shorter = datatypeFactory.newDuration("P1Y1M1DT1H1M1S"); Duration longer = datatypeFactory.newDuration("P2Y1M1DT1H1M1S"); assertTrue(shorter.isShorterThan(longer)); assertFalse(longer.isShorterThan(shorter)); assertFalse(shorter.isShorterThan(shorter)); assertTrue(longer.isLongerThan(shorter)); assertFalse(shorter.isLongerThan(longer)); assertFalse(shorter.isLongerThan(shorter)); } /* * Test for Duration.isSet(). */ @Test public void checkDurationIsSet() { Duration duration1 = datatypeFactory.newDuration(true, 1, 1, 1, 1, 1, 1); Duration duration2 = datatypeFactory.newDuration(true, 0, 0, 0, 0, 0, 0); assertTrue(duration1.isSet(YEARS)); assertTrue(duration1.isSet(MONTHS)); assertTrue(duration1.isSet(DAYS)); assertTrue(duration1.isSet(HOURS)); assertTrue(duration1.isSet(MINUTES)); assertTrue(duration1.isSet(SECONDS)); assertTrue(duration2.isSet(YEARS)); assertTrue(duration2.isSet(MONTHS)); assertTrue(duration2.isSet(DAYS)); assertTrue(duration2.isSet(HOURS)); assertTrue(duration2.isSet(MINUTES)); assertTrue(duration2.isSet(SECONDS)); Duration duration66 = datatypeFactory.newDuration(true, null, null, zero, null, null, null); assertFalse(duration66.isSet(YEARS)); assertFalse(duration66.isSet(MONTHS)); assertFalse(duration66.isSet(HOURS)); assertFalse(duration66.isSet(MINUTES)); assertFalse(duration66.isSet(SECONDS)); Duration duration3 = datatypeFactory.newDuration("P1D"); assertFalse(duration3.isSet(YEARS)); assertFalse(duration3.isSet(MONTHS)); assertFalse(duration3.isSet(HOURS)); assertFalse(duration3.isSet(MINUTES)); assertFalse(duration3.isSet(SECONDS)); } /* * Test Duration.isSet(Field) throws NPE if the field parameter is null. */ @Test(expectedExceptions = NullPointerException.class) public void checkDurationIsSetNeg() { Duration duration = datatypeFactory.newDuration(true, 0, 0, 0, 0, 0, 0); duration.isSet(null); } /* * Test for -getField(DatatypeConstants.Field) DatatypeConstants.Field is * null - throws NPE. */ @Test(expectedExceptions = NullPointerException.class) public void checkDurationGetFieldNeg() { Duration duration67 = datatypeFactory.newDuration("P1Y1M1DT1H1M1S"); duration67.getField(null); } @DataProvider(name = "duration-fields") public Object[][] getDurationAndFields() { return new Object[][] { { "P1Y1M1DT1H1M1S", one, one, one, one, one, new BigDecimal(one) }, { "PT1M", null, null, null, null, one, null }, { "P1M", null, one, null, null, null, null } }; } /* * Test for Duration.getField(DatatypeConstants.Field). */ @Test(dataProvider = "duration-fields") public void checkDurationGetField(String lexRepresentation, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes, BigDecimal seconds) { Duration duration = datatypeFactory.newDuration(lexRepresentation); assertEquals(duration.getField(YEARS), years); assertEquals(duration.getField(MONTHS), months); assertEquals(duration.getField(DAYS), days); assertEquals(duration.getField(HOURS), hours); assertEquals(duration.getField(MINUTES), minutes); assertEquals(duration.getField(SECONDS), seconds); } @DataProvider(name = "number-string") public Object[][] getNumberAndString() { return new Object[][] { // is positive, year, month, day, hour, minute, second, lexical { true, 1, 1, 1, 1, 1, 1, "P1Y1M1DT1H1M1S" }, { false, 1, 1, 1, 1, 1, 1, "-P1Y1M1DT1H1M1S" }, { true, 0, 0, 0, 0, 0, 0, "P0Y0M0DT0H0M0S" }, { false, 0, 0, 0, 0, 0, 0, "P0Y0M0DT0H0M0S" } }; } /* * Test for - toString(). */ @Test(dataProvider = "number-string") public void checkDurationToString(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds, String lexical) { Duration duration = datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); assertEquals(duration.toString(), lexical); assertEquals(datatypeFactory.newDuration(duration.toString()), duration); } @DataProvider(name = "duration-field") public Object[][] getDurationAndField() { Function getyears = duration -> duration.getYears(); Function getmonths = duration -> duration.getMonths(); Function getdays = duration -> duration.getDays(); Function gethours = duration -> duration.getHours(); Function getminutes = duration -> duration.getMinutes(); Function getseconds = duration -> duration.getSeconds(); return new Object[][] { { "P1Y1M1DT1H1M1S", getyears, 1 }, { "P1M1DT1H1M1S", getyears, 0 }, { "P1Y1M1DT1H1M1S", getmonths, 1 }, { "P1Y1DT1H1M1S", getmonths, 0 }, { "P1Y1M1DT1H1M1S", getdays, 1 }, { "P1Y1MT1H1M1S", getdays, 0 }, { "P1Y1M1DT1H1M1S", gethours, 1 }, { "P1Y1M1DT1M1S", gethours, 0 }, { "P1Y1M1DT1H1M1S", getminutes, 1 }, { "P1Y1M1DT1H1S", getminutes, 0 }, { "P1Y1M1DT1H1M1S", getseconds, 1 }, { "P1Y1M1DT1H1M", getseconds, 0 }, { "P1Y1M1DT1H1M100000000S", getseconds, 100000000 }, }; } /* * Test for Duration.getYears(), getMonths(), etc. */ @Test(dataProvider = "duration-field") public void checkDurationGetOneField(String lexRepresentation, Function getter, int value) { Duration duration = datatypeFactory.newDuration(lexRepresentation); assertEquals(getter.apply(duration).intValue(), value); } /* * Test for - getField(SECONDS) */ @Test public void checkDurationGetSecondsField() { Duration duration85 = datatypeFactory.newDuration("P1Y1M1DT1H1M100000000S"); assertEquals((duration85.getField(SECONDS)).intValue(), 100000000); } /* * getTimeInMillis(java.util.Calendar startInstant) returns milliseconds * between startInstant and startInstant plus this Duration. */ @Test public void checkDurationGetTimeInMillis() { Duration duration86 = datatypeFactory.newDuration("PT1M1S"); Calendar calendar86 = Calendar.getInstance(); assertEquals(duration86.getTimeInMillis(calendar86), 61000); } /* * getTimeInMillis(java.util.Calendar startInstant) returns milliseconds * between startInstant and startInstant plus this Duration throws NPE if * startInstant parameter is null. */ @Test(expectedExceptions = NullPointerException.class) public void checkDurationGetTimeInMillisNeg() { Duration duration87 = datatypeFactory.newDuration("PT1M1S"); Calendar calendar87 = null; duration87.getTimeInMillis(calendar87); } @DataProvider(name = "duration-for-hash") public Object[][] getDurationsForHash() { return new Object[][] { { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" }, { "P1D", "PT24H" }, { "PT1H", "PT60M" }, { "PT1M", "PT60S" }, { "P1Y", "P12M" } }; } /* * Test for Duration.hashcode(). hashcode() should return same value for * some equal durations. */ @Test(dataProvider = "duration-for-hash") public void checkDurationHashCode(String lexRepresentation1, String lexRepresentation2) { Duration duration1 = datatypeFactory.newDuration(lexRepresentation1); Duration duration2 = datatypeFactory.newDuration(lexRepresentation2); int hash1 = duration1.hashCode(); int hash2 = duration2.hashCode(); assertTrue(hash1 == hash2, " generated hash1 : " + hash1 + " generated hash2 : " + hash2); } @DataProvider(name = "duration-for-add") public Object[][] getDurationsForAdd() { return new Object[][] { // initVal, addVal, resultVal { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S", "P2Y2M2DT2H2M2S" }, { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S", "P0Y0M0DT0H0M0S" }, { "-P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S", "-P2Y2M2DT2H2M2S" }, }; } /* * Test for add(Duration rhs). */ @Test(dataProvider = "duration-for-add") public void checkDurationAdd(String initVal, String addVal, String result) { Duration durationInit = datatypeFactory.newDuration(initVal); Duration durationAdd = datatypeFactory.newDuration(addVal); Duration durationResult = datatypeFactory.newDuration(result); assertEquals(durationInit.add(durationAdd), durationResult); } @DataProvider(name = "duration-for-addneg") public Object[][] getDurationsForAddNeg() { return new Object[][] { // initVal, addVal { "P1Y1M1DT1H1M1S", null }, { "P1Y", "-P1D" }, { "-P1Y", "P1D" }, }; } /* * Test for add(Duration rhs) 'rhs' is null , should throw NPE. "1 year" + * "-1 day" or "-1 year" + "1 day" should throw IllegalStateException */ @Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class }, dataProvider = "duration-for-addneg") public void checkDurationAddNeg(String initVal, String addVal) { Duration durationInit = datatypeFactory.newDuration(initVal); Duration durationAdd = addVal == null ? null : datatypeFactory.newDuration(addVal); durationInit.add(durationAdd); } /* * Test Duration#compare(Duration duration) with large durations. * * Bug # 4972785 UnsupportedOperationException is expected * */ @Test(expectedExceptions = UnsupportedOperationException.class) public void checkDurationCompareLarge() { String duration1Lex = "P100000000000000000000D"; String duration2Lex = "PT2400000000000000000000H"; Duration duration1 = datatypeFactory.newDuration(duration1Lex); Duration duration2 = datatypeFactory.newDuration(duration2Lex); duration1.compare(duration2); } /* * Test Duration#getXMLSchemaType(). * * Bug # 5049544 Duration.getXMLSchemaType shall return the correct result * */ @Test public void checkDurationGetXMLSchemaType() { // DURATION Duration duration = datatypeFactory.newDuration("P1Y1M1DT1H1M1S"); QName duration_xmlSchemaType = duration.getXMLSchemaType(); assertEquals(duration_xmlSchemaType, DatatypeConstants.DURATION, "Expected DatatypeConstants.DURATION, returned " + duration_xmlSchemaType.toString()); // DURATION_DAYTIME Duration duration_dayTime = datatypeFactory.newDuration("P1DT1H1M1S"); QName duration_dayTime_xmlSchemaType = duration_dayTime.getXMLSchemaType(); assertEquals(duration_dayTime_xmlSchemaType, DatatypeConstants.DURATION_DAYTIME, "Expected DatatypeConstants.DURATION_DAYTIME, returned " + duration_dayTime_xmlSchemaType.toString()); // DURATION_YEARMONTH Duration duration_yearMonth = datatypeFactory.newDuration("P1Y1M"); QName duration_yearMonth_xmlSchemaType = duration_yearMonth.getXMLSchemaType(); assertEquals(duration_yearMonth_xmlSchemaType, DatatypeConstants.DURATION_YEARMONTH, "Expected DatatypeConstants.DURATION_YEARMONTH, returned " + duration_yearMonth_xmlSchemaType.toString()); } private final int undef = DatatypeConstants.FIELD_UNDEFINED; private final BigInteger zero = BigInteger.ZERO; private final BigInteger one = BigInteger.ONE; }