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