1 /* The contents of this file are subject to the Netscape Public 2 * License Version 1.1 (the "License"); you may not use this file 3 * except in compliance with the License. You may obtain a copy of 4 * the License at http://www.mozilla.org/NPL/ 5 * 6 * Software distributed under the License is distributed on an "AS 7 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 8 * implied. See the License for the specific language governing 9 * rights and limitations under the License. 10 * 11 * The Original Code is Mozilla Communicator client code, released March 12 * 31, 1998. 13 * 14 * The Initial Developer of the Original Code is Netscape Communications 15 * Corporation. Portions created by Netscape are 16 * Copyright (C) 1998 Netscape Communications Corporation. All 17 * Rights Reserved. 18 * 19 * Contributor(s): 20 * 21 */ 22 /* 23 * JavaScript shared functions file for running the tests in either 24 * stand-alone JavaScript engine. To run a test, first load this file, 25 * then load the test script. 26 */ 27 28 var completed = false; 29 var testcases; 30 var tc = 0; 31 32 SECTION = ""; 33 VERSION = ""; 34 BUGNUMBER = ""; 35 36 /* 37 * constant strings 38 */ 39 var GLOBAL = "[object global]"; 40 var PASSED = " PASSED!" 41 var FAILED = " FAILED! expected: "; 42 var DEBUG = false; 43 44 45 /* 46 * Wrapper for test case constructor that doesn't require the SECTION argument. 47 */ 48 function AddTestCase( description, expect, actual ) 49 { 50 testcases[tc++] = new TestCase( SECTION, description, expect, actual ); 51 } 52 53 54 /* 55 * TestCase constructor 56 */ 57 function TestCase( n, d, e, a ) 58 { 59 this.name = n; 60 this.description = d; 61 this.expect = e; 62 this.actual = a; 63 this.passed = true; 64 this.reason = ""; 65 this.bugnumber = BUGNUMBER; 66 this.passed = getTestCaseResult( this.expect, this.actual ); 67 if ( DEBUG ) {writeLineToLog("added " + this.description);} 68 } 69 70 71 /* 72 * Set up test environment. 73 */ 74 function startTest() 75 { 76 if ( version ) 77 { 78 // JavaScript 1.3 is supposed to be compliant ECMA version 1.0 79 if (VERSION == "ECMA_1" ) {version ("130");} 80 if (VERSION == "JS_1.3" ) {version ( "130");} 81 if (VERSION == "JS_1.2" ) {version ( "120");} 82 if (VERSION == "JS_1.1" ) {version( "110");} 83 84 // for ECMA version 2.0, we will leave the JavaScript version 85 // to the default ( for now ). 86 } 87 88 // print out bugnumber 89 if ( BUGNUMBER ) 90 { 91 writeLineToLog ("BUGNUMBER: " + BUGNUMBER ); 92 } 93 94 testcases = new Array(); 95 tc = 0; 96 } 97 98 99 function test() 100 { 101 for ( tc=0; tc < testcases.length; tc++ ) 102 { 103 testcases[tc].passed = writeTestCaseResult( 104 testcases[tc].expect, 105 testcases[tc].actual, 106 testcases[tc].description +" = "+ testcases[tc].actual ); 107 108 testcases[tc].reason += ( testcases[tc].passed ) ? "" : "wrong value "; 109 } 110 111 stopTest(); 112 return ( testcases ); 113 } 114 115 116 /* 117 * Compare expected result to the actual result and figure out whether 118 * the test case passed. 119 */ 120 function getTestCaseResult(expect, actual ) 121 { 122 //because ( NaN == NaN ) always returns false, need to do 123 //a special compare to see if we got the right result. 124 if ( actual != actual ) 125 { 126 if ( typeof actual == "object" ) {actual = "NaN object";} 127 else {actual = "NaN number";} 128 } 129 130 if ( expect != expect ) 131 { 132 if ( typeof expect == "object" ) {expect = "NaN object";} 133 else {expect = "NaN number";} 134 } 135 136 var passed = ( expect == actual ) ? true : false; 137 138 // if both objects are numbers, need to replace w/ IEEE standard for rounding 139 if ( !passed && typeof(actual) == "number" && typeof(expect) == "number" ) 140 { 141 if ( Math.abs(actual-expect) < 0.0000001 ) {passed = true;} 142 } 143 144 //verify type is the same 145 if ( typeof(expect) != typeof(actual) ) {passed = false;} 146 147 return passed; 148 } 149 150 151 /* 152 * Begin printing functions. These functions use the shell's print function. 153 * When running tests in the browser, override these functions with functions 154 * that use document.write. 155 */ 156 function writeTestCaseResult( expect, actual, string ) 157 { 158 var passed = getTestCaseResult(expect, actual ); 159 writeFormattedResult( expect, actual, string, passed ); 160 return passed; 161 } 162 163 164 function writeFormattedResult( expect, actual, string, passed ) 165 { 166 var s = string ; 167 s += ( passed ) ? PASSED : FAILED + expect; 168 writeLineToLog( s); 169 return passed; 170 } 171 172 173 function writeLineToLog( string ) 174 { 175 print( string ); 176 } 177 178 179 function writeHeaderToLog( string ) 180 { 181 print( string ); 182 } 183 /* End of printing functions */ 184 185 186 /* 187 * When running in the shell, run the garbage collector after the test has completed. 188 */ 189 function stopTest() 190 { 191 var gc; 192 if ( gc != undefined ) 193 { 194 gc(); 195 } 196 } 197 198 199 /* 200 * Convenience function for displaying failed test cases. 201 * Useful when running tests manually. 202 */ 203 function getFailedCases() 204 { 205 for (var i = 0; i < testcases.length; i++ ) 206 { 207 if ( !testcases[i].passed ) 208 { 209 print( testcases[i].description + " = " + testcases[i].actual + " expected: " + testcases[i].expect ); 210 } 211 } 212 } 213 214 215 /* 216 * Date constants and functions used by tests in Date suite 217 */ 218 var msPerDay = 86400000; 219 var HoursPerDay = 24; 220 var MinutesPerHour = 60; 221 var SecondsPerMinute = 60; 222 var msPerSecond = 1000; 223 var msPerMinute = 60000; // msPerSecond * SecondsPerMinute 224 var msPerHour = 3600000; // msPerMinute * MinutesPerHour 225 var TZ_DIFF = getTimeZoneDiff(); 226 var TZ_ADJUST = TZ_DIFF * msPerHour; 227 var TIME_1970 = 0; 228 var TIME_2000 = 946684800000; 229 var TIME_1900 = -2208988800000; 230 var UTC_29_FEB_2000 = TIME_2000 + 31*msPerDay + 28*msPerDay; 231 var UTC_1_JAN_2005 = TIME_2000 + TimeInYear(2000) + TimeInYear(2001) + 232 TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004); 233 var now = new Date(); 234 var TIME_NOW = now.valueOf(); //valueOf() is to accurate to the millisecond 235 //Date.parse() is accurate only to the second 236 237 238 239 /* 240 * Originally, the test suite used a hard-coded value TZ_DIFF = -8. 241 * But that was only valid for testers in the Pacific Standard Time Zone! 242 * We calculate the proper number dynamically for any tester. We just 243 * have to be careful to use a date not subject to Daylight Savings Time... 244 */ 245 function getTimeZoneDiff() 246 { 247 return -((new Date(2000, 1, 1)).getTimezoneOffset())/60; 248 } 249 250 251 function Day( t) 252 { 253 return ( Math.floor( t/msPerDay ) ); 254 } 255 256 257 function DaysInYear( y ) 258 { 259 if ( y % 4 != 0 ) {return 365;} 260 261 if ( (y%4 == 0) && (y%100 != 0) ) {return 366;} 262 263 if ( (y%100 == 0) && (y%400 != 0) ) {return 365;} 264 265 if ( (y%400 == 0)){return 366;} 266 else {return "ERROR: DaysInYear(" + y + ") case not covered";} 267 } 268 269 270 function TimeInYear( y ) 271 { 272 return ( DaysInYear(y) * msPerDay ); 273 } 274 275 276 function DayNumber( t ) 277 { 278 return ( Math.floor( t / msPerDay ) ); 279 } 280 281 282 function TimeWithinDay( t ) 283 { 284 if ( t < 0 ) {return ( (t%msPerDay) + msPerDay );} 285 else {return ( t % msPerDay );} 286 } 287 288 289 function YearNumber( t ) 290 { 291 } 292 293 294 function TimeFromYear( y ) 295 { 296 return ( msPerDay * DayFromYear(y) ); 297 } 298 299 300 function DayFromYear( y ) 301 { 302 return ( 365*(y-1970) + Math.floor((y-1969)/4) - Math.floor((y-1901)/100) 303 + Math.floor((y-1601)/400) ); 304 } 305 306 307 function InLeapYear( t ) 308 { 309 if ( DaysInYear(YearFromTime(t)) == 365 ) {return 0;} 310 311 if ( DaysInYear(YearFromTime(t)) == 366 ) {return 1;} 312 else {return "ERROR: InLeapYear(" + t + ") case not covered";} 313 } 314 315 316 function YearFromTime( t ) 317 { 318 t =Number( t ); 319 var sign = ( t < 0 ) ? -1 : 1; 320 var year = ( sign < 0 ) ? 1969 : 1970; 321 322 for (var timeToTimeZero = t; ; ) 323 { 324 // subtract the current year's time from the time that's left. 325 timeToTimeZero -= sign * TimeInYear(year) 326 327 // if there's less than the current year's worth of time left, then break. 328 if ( sign < 0 ) 329 { 330 if ( sign * timeToTimeZero <= 0 ) {break;} 331 else {year += sign;} 332 } 333 else 334 { 335 if ( sign * timeToTimeZero < 0 ) {break;} 336 else {year += sign;} 337 } 338 } 339 340 return ( year ); 341 } 342 343 344 function MonthFromTime( t ) 345 { 346 var day = DayWithinYear( t ); 347 var leap = InLeapYear(t); 348 349 // I know I could use switch but I'd rather not until it's part of ECMA 350 if ( (0 <= day) && (day < 31) ) {return 0;} 351 if ( (31 <= day) && (day < (59+leap) )) {return 1;} 352 if ( ((59+leap) <= day) && (day < (90+leap) )) {return 2;} 353 if ( ((90+leap) <= day) && (day < (120+leap) )) {return 3;} 354 if ( ((120+leap) <= day) && (day < (151+leap) )) {return 4;} 355 if ( ((151+leap) <= day) && (day < (181+leap) )) {return 5;} 356 if ( ((181+leap) <= day) && (day < (212+leap) )) {return 6;} 357 if ( ((212+leap) <= day) && (day < (243+leap)) ) {return 7;} 358 if ( ((243+leap) <= day) && (day < (273+leap) )) {return 8;} 359 if ( ((273+leap) <= day) && (day < (304+leap)) ) {return 9;} 360 if ( ((304+leap) <= day) && (day < (334+leap)) ) {return 10;} 361 if ( ((334+leap) <= day) && (day < (365+leap)) ) {return 11;} 362 else {return "ERROR: MonthFromTime(" + t + ") not known";} 363 } 364 365 366 function DayWithinYear( t ) 367 { 368 return(Day(t) - DayFromYear(YearFromTime(t)) ); 369 } 370 371 372 function DateFromTime( t ) 373 { 374 var day = DayWithinYear(t); 375 var month = MonthFromTime(t); 376 377 if ( month == 0) {return ( day + 1 );} 378 if ( month == 1) {return ( day - 30 );} 379 if ( month == 2) {return ( day - 58 - InLeapYear(t) );} 380 if ( month == 3) {return ( day - 89 - InLeapYear(t));} 381 if ( month == 4) {return ( day - 119 - InLeapYear(t));} 382 if ( month == 5) {return ( day - 150 - InLeapYear(t));} 383 if ( month == 6) {return ( day - 180 - InLeapYear(t));} 384 if ( month == 7) {return ( day - 211 - InLeapYear(t));} 385 if ( month == 8) {return ( day - 242 - InLeapYear(t));} 386 if ( month == 9) {return ( day - 272 - InLeapYear(t));} 387 if ( month == 10) {return ( day - 303 - InLeapYear(t));} 388 if ( month == 11) {return ( day - 333 - InLeapYear(t));} 389 return ("ERROR: DateFromTime("+t+") not known" ); 390 } 391 392 393 function WeekDay( t ) 394 { 395 var weekday = (Day(t)+4)%7; 396 return( weekday < 0 ? 7+weekday : weekday ); 397 } 398 399 400 // missing daylight savings time adjustment 401 402 403 function HourFromTime( t ) 404 { 405 var h = Math.floor( t / msPerHour )%HoursPerDay; 406 return ( (h<0) ? HoursPerDay + h : h ); 407 } 408 409 410 function MinFromTime( t ) 411 { 412 var min = Math.floor( t / msPerMinute )%MinutesPerHour; 413 return( (min < 0 ) ? MinutesPerHour + min : min ); 414 } 415 416 417 function SecFromTime( t ) 418 { 419 var sec = Math.floor( t / msPerSecond )%SecondsPerMinute; 420 return ( (sec < 0 ) ? SecondsPerMinute + sec : sec ); 421 } 422 423 424 function msFromTime( t ) 425 { 426 var ms = t%msPerSecond; 427 return ( (ms < 0 ) ? msPerSecond + ms : ms ); 428 } 429 430 431 function LocalTZA() 432 { 433 return ( TZ_DIFF * msPerHour ); 434 } 435 436 437 function UTC( t ) 438 { 439 return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); 440 } 441 442 443 function DaylightSavingTA( t ) 444 { 445 t = t - LocalTZA(); 446 447 var dst_start = GetSecondSundayInMarch(t) + 2*msPerHour; 448 var dst_end = GetFirstSundayInNovember(t) + 2*msPerHour; 449 450 if ( t >= dst_start && t < dst_end ) {return msPerHour;} 451 else {return 0;} 452 453 // Daylight Savings Time starts on the first Sunday in April at 2:00AM in PST. 454 // Other time zones will need to override this function. 455 456 print( new Date( UTC(dst_start + LocalTZA())) ); 457 return UTC(dst_start + LocalTZA()); 458 } 459 460 function GetFirstSundayInApril( t ) { 461 var year = YearFromTime(t); 462 var leap = InLeapYear(t); 463 464 var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) + 465 TimeInMonth(2,leap); 466 467 for ( var first_sunday = april; WeekDay(first_sunday) > 0; 468 first_sunday += msPerDay ) 469 { 470 ; 471 } 472 473 return first_sunday; 474 } 475 function GetLastSundayInOctober( t ) { 476 var year = YearFromTime(t); 477 var leap = InLeapYear(t); 478 479 for ( var oct = TimeFromYear(year), m = 0; m < 9; m++ ) { 480 oct += TimeInMonth(m, leap); 481 } 482 for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0; 483 last_sunday -= msPerDay ) 484 { 485 ; 486 } 487 return last_sunday; 488 } 489 490 // Added these two functions because DST rules changed for the US. 491 function GetSecondSundayInMarch( t ) { 492 var year = YearFromTime(t); 493 var leap = InLeapYear(t); 494 495 var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap); 496 497 var sundayCount = 0; 498 var flag = true; 499 for ( var second_sunday = march; flag; second_sunday += msPerDay ) 500 { 501 if (WeekDay(second_sunday) == 0) { 502 if(++sundayCount == 2) 503 flag = false; 504 } 505 } 506 507 return second_sunday; 508 } 509 function GetFirstSundayInNovember( t ) { 510 var year = YearFromTime(t); 511 var leap = InLeapYear(t); 512 513 for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) { 514 nov += TimeInMonth(m, leap); 515 } 516 for ( var first_sunday = nov; WeekDay(first_sunday) > 0; 517 first_sunday += msPerDay ) 518 { 519 ; 520 } 521 return first_sunday; 522 } 523 524 525 function LocalTime( t ) 526 { 527 return ( t + LocalTZA() + DaylightSavingTA(t) ); 528 } 529 530 531 function MakeTime( hour, min, sec, ms ) 532 { 533 if ( isNaN(hour) || isNaN(min) || isNaN(sec) || isNaN(ms) ){return Number.NaN;} 534 535 hour = ToInteger(hour); 536 min = ToInteger( min); 537 sec = ToInteger( sec); 538 ms = ToInteger( ms ); 539 540 return( (hour*msPerHour) + (min*msPerMinute) + (sec*msPerSecond) + ms ); 541 } 542 543 544 function MakeDay( year, month, date ) 545 { 546 if ( isNaN(year) || isNaN(month) || isNaN(date)) {return Number.NaN;} 547 548 year = ToInteger(year); 549 month = ToInteger(month); 550 date = ToInteger(date ); 551 552 var sign = ( year < 1970 ) ? -1 : 1; 553 var t = ( year < 1970 ) ? 1 : 0; 554 var y = ( year < 1970 ) ? 1969 : 1970; 555 556 var result5 = year + Math.floor( month/12 ); 557 var result6= month%12; 558 559 if ( year < 1970 ) 560 { 561 for ( y = 1969; y >= year; y += sign ) 562 { 563 t += sign * TimeInYear(y); 564 } 565 } 566 else 567 { 568 for ( y = 1970 ; y < year; y += sign ) 569 { 570 t += sign * TimeInYear(y); 571 } 572 } 573 574 var leap = InLeapYear( t ); 575 576 for ( var m = 0; m < month; m++) 577 { 578 t += TimeInMonth( m, leap ); 579 } 580 581 if ( YearFromTime(t) != result5 ) {return Number.NaN;} 582 if ( MonthFromTime(t) != result6 ) {return Number.NaN;} 583 if ( DateFromTime(t) != 1 ){return Number.NaN;} 584 585 return ( (Day(t)) + date - 1 ); 586 } 587 588 589 function TimeInMonth( month, leap ) 590 { 591 // Jan 0 Feb 1 Mar 2 Apr 3 May 4 June 5 Jul 6 Aug 7 Sep 8 Oct 9 Nov 10 Dec11 592 593 // April June September November 594 if ( month == 3 || month == 5 || month == 8 || month == 10 ) {return ( 30*msPerDay );} 595 596 // all the rest 597 if ( month == 0 || month == 2 || month == 4 || month == 6 || 598 month == 7 || month == 9 || month == 11 ) {return ( 31*msPerDay );} 599 600 // save February 601 return ( (leap == 0) ? 28*msPerDay : 29*msPerDay ); 602 } 603 604 605 function MakeDate( day, time ) 606 { 607 if (day == Number.POSITIVE_INFINITY || 608 day == Number.NEGATIVE_INFINITY || 609 day == Number.NaN ) 610 { 611 return Number.NaN; 612 } 613 614 if ( time == Number.POSITIVE_INFINITY || 615 time == Number.POSITIVE_INFINITY || 616 day == Number.NaN) 617 { 618 return Number.NaN; 619 } 620 621 return ( day * msPerDay ) + time; 622 } 623 624 625 function TimeClip( t ) 626 { 627 if ( isNaN( t )) {return ( Number.NaN);} 628 if ( Math.abs( t ) > 8.64e15 ) {return ( Number.NaN);} 629 630 return ( ToInteger( t ) ); 631 } 632 633 634 function ToInteger( t ) 635 { 636 t = Number( t ); 637 638 if ( isNaN( t )) {return ( Number.NaN);} 639 640 if ( t == 0 || t == -0 || 641 t == Number.POSITIVE_INFINITY || 642 t == Number.NEGATIVE_INFINITY) 643 { 644 return 0; 645 } 646 647 var sign = ( t < 0 ) ? -1 : 1; 648 649 return ( sign * Math.floor( Math.abs( t ) ) ); 650 } 651 652 653 function Enumerate( o ) 654 { 655 var p; 656 for ( p in o ) {print( p + ": " + o[p] );} 657 } 658 659 660 /* these functions are useful for running tests manually in Rhino */ 661 662 function GetContext() 663 { 664 return Packages.com.netscape.javascript.Context.getCurrentContext(); 665 } 666 667 668 function OptLevel( i ) 669 { 670 i = Number(i); 671 var cx = GetContext(); 672 cx.setOptimizationLevel(i); 673 } 674 675 /* end of Rhino functions */ 676 677