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