8190835: Subtraction with two javax.xml.datatype.Duration gives incorrect result
Reviewed-by: lancea
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Fri Jun 29 10:41:10 2018 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Fri Jun 29 10:13:24 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -98,6 +98,7 @@
* @author Kohsuke Kawaguchi
* @author Joseph Fialli
* @see XMLGregorianCalendar#add(Duration)
+ * @LastModified: June 2018
*/
class DurationImpl
extends Duration
@@ -1603,9 +1604,10 @@
touched = true;
// compute the number of unit that needs to be borrowed.
- BigDecimal borrow =
- buf[i].abs().divide(
+ // scale should be 0 in all cases
+ BigDecimal borrow = buf[i].abs().divide(
FACTORS[i - 1],
+ 0,
RoundingMode.UP);
if (buf[i].signum() > 0) {
borrow = borrow.negate();
--- a/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java Fri Jun 29 10:41:10 2018 +0200
+++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java Fri Jun 29 10:13:24 2018 -0700
@@ -39,11 +39,13 @@
import org.testng.Assert;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/*
* @test
+ * @bug 8190835
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true datatype.DurationTest
* @run testng/othervm datatype.DurationTest
@@ -66,6 +68,61 @@
}
}
+ /*
+ DataProvider: for testDurationSubtract1
+ Data: minuend, subtrahend, expected result
+ */
+ @DataProvider(name = "DurationSubtract1")
+ public Object[][] getSubtract1() {
+
+ return new Object[][]{
+ {"P2Y2M", "P1Y5M", "P9M"},
+ {"P2DT2H", "P1DT12H", "PT14H"},
+ {"P2DT2H10M", "P1DT2H25M", "PT23H45M"},
+ {"PT2H10M", "PT1H25M", "PT45M"},
+ {"PT2H10M20S", "PT1H25M35S", "PT44M45S"},
+ {"PT2H10M20.25S", "PT1H25M35.45S", "PT44M44.8S"},
+ // 8190835 test case
+ {"PT2M3.123S", "PT1M10.123S", "PT53S"}
+ };
+ }
+
+ @DataProvider(name = "DurationSubtract2")
+ public Object[][] getSubtract2() {
+
+ return new Object[][]{
+ {"P2Y20D", "P1Y125D"},
+ {"P2M20D", "P1M25D"}
+ };
+ }
+
+ /*
+ * Verifies valid substraction operations.
+ */
+ @Test(dataProvider = "DurationSubtract1")
+ public void testDurationSubtract1(String t1, String t2, String e) throws Exception {
+ DatatypeFactory factory = DatatypeFactory.newInstance();
+ Duration dt1 = factory.newDuration(t1);
+ Duration dt2 = factory.newDuration(t2);
+
+ Duration result = dt1.subtract(dt2);
+ Duration expected = factory.newDuration(e);
+ Assert.assertTrue(result.equals(expected), "The result should be " + e);
+
+ }
+
+ /*
+ * Verifies invalid substraction operations. These operations are invalid
+ * since days in a month are indeterminate.
+ */
+ @Test(dataProvider = "DurationSubtract2", expectedExceptions = IllegalStateException.class)
+ public void testDurationSubtract2(String t1, String t2) throws Exception {
+ DatatypeFactory factory = DatatypeFactory.newInstance();
+ Duration dt1 = factory.newDuration(t1);
+ Duration dt2 = factory.newDuration(t2);
+ Duration result = dt1.subtract(dt2);
+ }
+
@Test
public void testDurationSubtract() {
try {