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 24package datatype; 25 26import java.math.BigDecimal; 27import java.math.BigInteger; 28import java.util.Calendar; 29import java.util.Date; 30import java.util.GregorianCalendar; 31import java.util.TimeZone; 32 33import javax.xml.datatype.DatatypeConfigurationException; 34import javax.xml.datatype.DatatypeConstants; 35import javax.xml.datatype.DatatypeFactory; 36import javax.xml.datatype.Duration; 37import javax.xml.namespace.QName; 38 39import org.testng.Assert; 40import org.testng.AssertJUnit; 41import org.testng.annotations.BeforeMethod; 42import org.testng.annotations.Listeners; 43import org.testng.annotations.Test; 44 45/* 46 * @test 47 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest 48 * @run testng/othervm -DrunSecMngr=true datatype.DurationTest 49 * @run testng/othervm datatype.DurationTest 50 * @summary Test Duration. 51 */ 52@Listeners({jaxp.library.BasePolicy.class}) 53public class DurationTest { 54 55 private final static boolean DEBUG = true; 56 57 protected Duration duration = null; 58 59 @BeforeMethod 60 public void setUp() { 61 try { 62 duration = DatatypeFactory.newInstance().newDuration(100); 63 } catch (DatatypeConfigurationException dce) { 64 dce.printStackTrace(); 65 Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); 66 } 67 } 68 69 @Test 70 public void testDurationSubtract() { 71 try { 72 Duration bigDur = DatatypeFactory.newInstance().newDuration(20000); 73 Duration smallDur = DatatypeFactory.newInstance().newDuration(10000); 74 if (smallDur.subtract(bigDur).getSign() != -1) { 75 Assert.fail("smallDur.subtract(bigDur).getSign() is not -1"); 76 } 77 if (bigDur.subtract(smallDur).getSign() != 1) { 78 Assert.fail("bigDur.subtract(smallDur).getSign() is not 1"); 79 } 80 if (smallDur.subtract(smallDur).getSign() != 0) { 81 Assert.fail("smallDur.subtract(smallDur).getSign() is not 0"); 82 } 83 } catch (DatatypeConfigurationException e) { 84 e.printStackTrace(); 85 } 86 } 87 88 @Test 89 public void testDurationMultiply() { 90 int num = 5000; // millisends. 5 seconds 91 int factor = 2; 92 try { 93 Duration dur = DatatypeFactory.newInstance().newDuration(num); 94 if (dur.multiply(factor).getSeconds() != 10) { 95 Assert.fail("duration.multiply() return wrong value"); 96 } 97 // factor is 2*10^(-1) 98 if (dur.multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 1) { 99 Assert.fail("duration.multiply() return wrong value"); 100 } 101 if (dur.subtract(DatatypeFactory.newInstance().newDuration(1000)).multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 0) { 102 Assert.fail("duration.multiply() return wrong value"); 103 } 104 } catch (DatatypeConfigurationException e) { 105 e.printStackTrace(); 106 } 107 } 108 109 @Test 110 public void testDurationAndCalendar1() { 111 int year = 1; 112 int month = 2; 113 int day = 3; 114 int hour = 4; 115 int min = 5; 116 int sec = 6; 117 String lexicalRepresentation = "P" + year + "Y" + month + "M" + day + "DT" + hour + "H" + min + "M" + sec + "S"; 118 try { 119 Duration dur = DatatypeFactory.newInstance().newDuration(lexicalRepresentation); 120 System.out.println(dur.toString()); 121 AssertJUnit.assertTrue("year should be 1", dur.getYears() == year); 122 AssertJUnit.assertTrue("month should be 2", dur.getMonths() == month); 123 AssertJUnit.assertTrue("day should be 3", dur.getDays() == day); 124 AssertJUnit.assertTrue("hour should be 4", dur.getHours() == hour); 125 AssertJUnit.assertTrue("minute should be 5", dur.getMinutes() == min); 126 AssertJUnit.assertTrue("second should be 6", dur.getSeconds() == sec); 127 } catch (DatatypeConfigurationException e) { 128 e.printStackTrace(); 129 } 130 } 131 132 @Test 133 public void testDurationAndCalendar2() { 134 try { 135 AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S") 136 .getTimeInMillis(new Date()) == 10000); 137 AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S") 138 .getTimeInMillis(new Date()) == -10000); 139 AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S") 140 .getTimeInMillis(new GregorianCalendar()) == 10000); 141 AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S") 142 .getTimeInMillis(new GregorianCalendar()) == -10000); 143 } catch (DatatypeConfigurationException e) { 144 e.printStackTrace(); 145 } 146 } 147 148 @Test 149 public void testDurationAndCalendar3() { 150 try { 151 Calendar cal = new GregorianCalendar(); 152 cal.set(Calendar.SECOND, 59); 153 DatatypeFactory.newInstance().newDuration(10000).addTo(cal); 154 AssertJUnit.assertTrue("sec will be 9", cal.get(Calendar.SECOND) == 9); 155 156 Date date = new Date(); 157 date.setSeconds(59); 158 DatatypeFactory.newInstance().newDuration(10000).addTo(date); 159 AssertJUnit.assertTrue("sec will be 9", date.getSeconds() == 9); 160 } catch (DatatypeConfigurationException e) { 161 e.printStackTrace(); 162 } 163 } 164 165 @Test 166 public void testEqualsWithDifferentObjectParam() { 167 168 AssertJUnit.assertFalse("equals method should return false for any object other than Duration", duration.equals(new Integer(0))); 169 } 170 171 @Test 172 public void testEqualsWithNullObjectParam() { 173 174 AssertJUnit.assertFalse("equals method should return false for null parameter", duration.equals(null)); 175 } 176 177 @Test 178 public void testEqualsWithEqualObjectParam() { 179 try { 180 AssertJUnit.assertTrue("equals method is expected to return true", duration.equals(DatatypeFactory.newInstance().newDuration(100))); 181 } catch (DatatypeConfigurationException dce) { 182 dce.printStackTrace(); 183 Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); 184 } 185 } 186 187 /** 188 * Inspired by CR 5077522 Duration.compare makes mistakes for some values. 189 */ 190 @Test 191 public void testCompareWithInderterminateRelation() { 192 193 final String[][] partialOrder = { // partialOrder 194 { "P1Y", "<>", "P365D" }, { "P1Y", "<>", "P366D" }, { "P1M", "<>", "P28D" }, { "P1M", "<>", "P29D" }, { "P1M", "<>", "P30D" }, { "P1M", "<>", "P31D" }, 195 { "P5M", "<>", "P150D" }, { "P5M", "<>", "P151D" }, { "P5M", "<>", "P152D" }, { "P5M", "<>", "P153D" }, { "PT2419200S", "<>", "P1M" }, 196 { "PT2678400S", "<>", "P1M" }, { "PT31536000S", "<>", "P1Y" }, { "PT31622400S", "<>", "P1Y" }, { "PT525600M", "<>", "P1Y" }, 197 { "PT527040M", "<>", "P1Y" }, { "PT8760H", "<>", "P1Y" }, { "PT8784H", "<>", "P1Y" }, { "P365D", "<>", "P1Y" }, }; 198 199 DatatypeFactory df = null; 200 try { 201 df = DatatypeFactory.newInstance(); 202 } catch (DatatypeConfigurationException ex) { 203 ex.printStackTrace(); 204 Assert.fail(ex.toString()); 205 } 206 207 boolean compareErrors = false; 208 209 for (int valueIndex = 0; valueIndex < partialOrder.length; ++valueIndex) { 210 Duration duration1 = df.newDuration(partialOrder[valueIndex][0]); 211 Duration duration2 = df.newDuration(partialOrder[valueIndex][2]); 212 int cmp = duration1.compare(duration2); 213 int expected = ">".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.GREATER 214 : "<".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.LESSER : "==".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.EQUAL 215 : DatatypeConstants.INDETERMINATE; 216 217 // just note any errors, do not fail until all cases have been 218 // tested 219 if (expected != cmp) { 220 compareErrors = true; 221 System.err.println("returned " + cmp2str(cmp) + " for durations \'" + duration1 + "\' and " + duration2 + "\', but expected " 222 + cmp2str(expected)); 223 } 224 } 225 226 if (compareErrors) { 227 // TODO; fix bug, these tests should pass 228 if (false) { 229 Assert.fail("Errors in comparing indeterminate relations, see Stderr"); 230 } else { 231 System.err.println("Please fix this bug: " + "Errors in comparing indeterminate relations, see Stderr"); 232 } 233 } 234 } 235 236 public static String cmp2str(int cmp) { 237 return cmp == DatatypeConstants.LESSER ? "LESSER" : cmp == DatatypeConstants.GREATER ? "GREATER" : cmp == DatatypeConstants.EQUAL ? "EQUAL" 238 : cmp == DatatypeConstants.INDETERMINATE ? "INDETERMINATE" : "UNDEFINED"; 239 } 240 241 /** 242 * Inspired by CR 6238220 javax.xml.datatype.Duration has no clear 243 * description concerning return values range. 244 */ 245 @Test 246 public void testNormalizedReturnValues() throws Exception { 247 248 final Object[] TEST_VALUES = { 249 // test 61 seconds -> 1 minute, 1 second 250 true, // isPositive, 251 BigInteger.ZERO, // years, 252 BigInteger.ZERO, // months 253 BigInteger.ZERO, // days 254 BigInteger.ZERO, // hours 255 BigInteger.ZERO, // minutes 256 new BigDecimal(61), // seconds 257 61000L, // durationInMilliSeconds, 258 "P0Y0M0DT0H0M61S", // lexicalRepresentation 259 260 // test - 61 seconds -> - 1 minute, 1 second 261 false, // isPositive, 262 BigInteger.ZERO, // years, 263 BigInteger.ZERO, // months 264 BigInteger.ZERO, // days 265 BigInteger.ZERO, // hours 266 BigInteger.ZERO, // minutes 267 new BigDecimal(61), // seconds 268 61000L, // durationInMilliSeconds, 269 "-P0Y0M0DT0H0M61S", // lexicalRepresentation 270 }; 271 272 final Object[] NORM_VALUES = { 273 // test 61 seconds -> 1 minute, 1 second 274 true, // normalized isPositive, 275 BigInteger.ZERO, // normalized years, 276 BigInteger.ZERO, // normalized months 277 BigInteger.ZERO, // normalized days 278 BigInteger.ZERO, // normalized hours 279 BigInteger.ONE, // normalized minutes 280 BigDecimal.ONE, // normalized seconds 281 61000L, // normalized durationInMilliSeconds, 282 "P0Y0M0DT0H1M1.000S", // normalized lexicalRepresentation 283 284 // test - 61 seconds -> - 1 minute, 1 second 285 false, // normalized isPositive, 286 BigInteger.ZERO, // normalized years, 287 BigInteger.ZERO, // normalized months 288 BigInteger.ZERO, // normalized days 289 BigInteger.ZERO, // normalized hours 290 BigInteger.ONE, // normalized minutes 291 BigDecimal.ONE, // normalized seconds 292 61000L, // normalized durationInMilliSeconds, 293 "-P0Y0M0DT0H1M1.000S" // normalized lexicalRepresentation 294 }; 295 296 for (int onValue = 0; onValue < TEST_VALUES.length; onValue += 9) { 297 newDurationTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive, 298 ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized 299 // isPositive, 300 (BigInteger) TEST_VALUES[onValue + 1], // years, 301 (BigInteger) NORM_VALUES[onValue + 1], // normalized years, 302 (BigInteger) TEST_VALUES[onValue + 2], // months 303 (BigInteger) NORM_VALUES[onValue + 2], // normalized months 304 (BigInteger) TEST_VALUES[onValue + 3], // days 305 (BigInteger) NORM_VALUES[onValue + 3], // normalized days 306 (BigInteger) TEST_VALUES[onValue + 4], // hours 307 (BigInteger) NORM_VALUES[onValue + 4], // normalized hours 308 (BigInteger) TEST_VALUES[onValue + 5], // minutes 309 (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes 310 (BigDecimal) TEST_VALUES[onValue + 6], // seconds 311 (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds 312 ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds, 313 ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized 314 // durationInMilliSeconds, 315 (String) TEST_VALUES[onValue + 8], // lexicalRepresentation 316 (String) NORM_VALUES[onValue + 8]); // normalized 317 // lexicalRepresentation 318 319 newDurationDayTimeTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive, 320 ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized 321 // isPositive, 322 BigInteger.ZERO, // years, 323 BigInteger.ZERO, // normalized years, 324 BigInteger.ZERO, // months 325 BigInteger.ZERO, // normalized months 326 (BigInteger) TEST_VALUES[onValue + 3], // days 327 (BigInteger) NORM_VALUES[onValue + 3], // normalized days 328 (BigInteger) TEST_VALUES[onValue + 4], // hours 329 (BigInteger) NORM_VALUES[onValue + 4], // normalized hours 330 (BigInteger) TEST_VALUES[onValue + 5], // minutes 331 (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes 332 (BigDecimal) TEST_VALUES[onValue + 6], // seconds 333 (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds 334 ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds, 335 ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized 336 // durationInMilliSeconds, 337 (String) TEST_VALUES[onValue + 8], // lexicalRepresentation 338 (String) NORM_VALUES[onValue + 8]); // normalized 339 // lexicalRepresentation 340 } 341 } 342 343 private void newDurationTester(boolean isPositive, boolean normalizedIsPositive, BigInteger years, BigInteger normalizedYears, BigInteger months, 344 BigInteger normalizedMonths, BigInteger days, BigInteger normalizedDays, BigInteger hours, BigInteger normalizedHours, BigInteger minutes, 345 BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds, 346 String lexicalRepresentation, String normalizedLexicalRepresentation) { 347 348 DatatypeFactory datatypeFactory = null; 349 try { 350 datatypeFactory = DatatypeFactory.newInstance(); 351 } catch (DatatypeConfigurationException ex) { 352 ex.printStackTrace(); 353 Assert.fail(ex.toString()); 354 } 355 356 // create 4 Durations using the 4 different constructors 357 358 Duration durationBigInteger = datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); 359 durationAssertEquals(durationBigInteger, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), 360 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), 361 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); 362 363 Duration durationInt = datatypeFactory.newDuration(isPositive, years.intValue(), months.intValue(), days.intValue(), hours.intValue(), 364 minutes.intValue(), seconds.intValue()); 365 durationAssertEquals(durationInt, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), 366 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), 367 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); 368 369 Duration durationMilliseconds = datatypeFactory.newDuration(durationInMilliSeconds); 370 durationAssertEquals(durationMilliseconds, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), 371 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), 372 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); 373 374 Duration durationLexical = datatypeFactory.newDuration(lexicalRepresentation); 375 durationAssertEquals(durationLexical, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), 376 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), 377 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); 378 } 379 380 private void newDurationDayTimeTester(boolean isPositive, boolean normalizedIsPositive, BigInteger years, BigInteger normalizedYears, BigInteger months, 381 BigInteger normalizedMonths, BigInteger days, BigInteger normalizedDays, BigInteger hours, BigInteger normalizedHours, BigInteger minutes, 382 BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds, 383 String lexicalRepresentation, String normalizedLexicalRepresentation) { 384 385 DatatypeFactory datatypeFactory = null; 386 try { 387 datatypeFactory = DatatypeFactory.newInstance(); 388 } catch (DatatypeConfigurationException ex) { 389 ex.printStackTrace(); 390 Assert.fail(ex.toString()); 391 } 392 393 // create 4 dayTime Durations using the 4 different constructors 394 395 Duration durationDayTimeBigInteger = datatypeFactory.newDurationDayTime(isPositive, days, hours, minutes, seconds.toBigInteger()); 396 durationAssertEquals(durationDayTimeBigInteger, DatatypeConstants.DURATION_DAYTIME, normalizedIsPositive, normalizedYears.intValue(), 397 normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), 398 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); 399 400 /* 401 * Duration durationDayTimeInt = datatypeFactory.newDurationDayTime( 402 * isPositive, days.intValue(), hours.intValue(), minutes.intValue(), 403 * seconds.intValue()); Duration durationDayTimeMilliseconds = 404 * datatypeFactory.newDurationDayTime( durationInMilliSeconds); Duration 405 * durationDayTimeLexical = datatypeFactory.newDurationDayTime( 406 * lexicalRepresentation); 407 * Duration durationYearMonthBigInteger = 408 * datatypeFactory.newDurationYearMonth( isPositive, years, months); 409 * Duration durationYearMonthInt = datatypeFactory.newDurationYearMonth( 410 * isPositive, years.intValue(), months.intValue()); Duration 411 * durationYearMonthMilliseconds = datatypeFactory.newDurationYearMonth( 412 * durationInMilliSeconds); Duration durationYearMonthLexical = 413 * datatypeFactory.newDurationYearMonth( lexicalRepresentation) ; 414 */ 415 416 } 417 418 private void durationAssertEquals(Duration duration, QName xmlSchemaType, boolean isPositive, int years, int months, int days, int hours, int minutes, 419 int seconds, long milliseconds, String lexical) { 420 421 final TimeZone GMT = TimeZone.getTimeZone("GMT"); 422 final GregorianCalendar EPOCH = new GregorianCalendar(GMT); 423 EPOCH.clear(); 424 425 if (DEBUG) { 426 System.out.println("Testing Duration: " + duration.toString()); 427 } 428 429 // sign 430 if (DEBUG) { 431 boolean actual = (duration.getSign() == 1) ? true : false; 432 System.out.println("sign:"); 433 System.out.println(" expected: \"" + isPositive + "\""); 434 System.out.println(" actual: \"" + actual + "\""); 435 } 436 437 if (DEBUG) { 438 System.out.println("years:"); 439 System.out.println(" expected: \"" + years + "\""); 440 System.out.println(" actual: \"" + duration.getYears() + "\""); 441 } 442 443 if (DEBUG) { 444 System.out.println("months:"); 445 System.out.println(" expected: \"" + months + "\""); 446 System.out.println(" actual: \"" + duration.getMonths() + "\""); 447 } 448 449 if (DEBUG) { 450 System.out.println("days:"); 451 System.out.println(" expected: \"" + days + "\""); 452 System.out.println(" actual: \"" + duration.getDays() + "\""); 453 } 454 455 if (DEBUG) { 456 System.out.println("hours:"); 457 System.out.println(" expected: \"" + hours + "\""); 458 System.out.println(" actual: \"" + duration.getHours() + "\""); 459 } 460 461 if (DEBUG) { 462 System.out.println("minutes:"); 463 System.out.println(" expected: \"" + minutes + "\""); 464 System.out.println(" actual: \"" + duration.getMinutes() + "\""); 465 } 466 467 if (DEBUG) { 468 System.out.println("seconds:"); 469 System.out.println(" expected: \"" + seconds + "\""); 470 System.out.println(" actual: \"" + duration.getSeconds() + "\""); 471 } 472 473 if (DEBUG) { 474 System.out.println("milliseconds:"); 475 System.out.println(" expected: \"" + milliseconds + "\""); 476 System.out.println(" actual: \"" + duration.getTimeInMillis(EPOCH) + "\""); 477 } 478 479 if (DEBUG) { 480 System.out.println("lexical:"); 481 System.out.println(" expected: \"" + lexical + "\""); 482 System.out.println(" actual: \"" + duration.toString() + "\""); 483 } 484 485 } 486} 487