8190835: Subtraction with two javax.xml.datatype.Duration gives incorrect result
authorjoehw
Fri, 29 Jun 2018 10:13:24 -0700
changeset 50899 4fa199e67e41
parent 50898 12133a6e2613
child 50900 f651ae122ff7
child 56814 97522a3141c2
8190835: Subtraction with two javax.xml.datatype.Duration gives incorrect result Reviewed-by: lancea
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java
test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java
--- 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 {