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 28var completed = false; 29var testcases; 30var tc = 0; 31 32SECTION = ""; 33VERSION = ""; 34BUGNUMBER = ""; 35 36/* 37 * constant strings 38 */ 39var GLOBAL = "[object global]"; 40var PASSED = " PASSED!" 41var FAILED = " FAILED! expected: "; 42var DEBUG = false; 43 44 45/* 46* Wrapper for test case constructor that doesn't require the SECTION argument. 47 */ 48function AddTestCase( description, expect, actual ) 49{ 50 testcases[tc++] = new TestCase( SECTION, description, expect, actual ); 51} 52 53 54/* 55 * TestCase constructor 56*/ 57function 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*/ 74function 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 99function 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 */ 120function 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 */ 156function writeTestCaseResult( expect, actual, string ) 157{ 158 var passed = getTestCaseResult(expect, actual ); 159 writeFormattedResult( expect, actual, string, passed ); 160 return passed; 161} 162 163 164function 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 173function writeLineToLog( string ) 174{ 175 print( string ); 176} 177 178 179function 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 */ 189function 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*/ 203function 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*/ 218var msPerDay = 86400000; 219var HoursPerDay = 24; 220var MinutesPerHour = 60; 221var SecondsPerMinute = 60; 222var msPerSecond = 1000; 223var msPerMinute = 60000; // msPerSecond * SecondsPerMinute 224var msPerHour = 3600000; // msPerMinute * MinutesPerHour 225var TZ_DIFF = getTimeZoneDiff(); 226var TZ_ADJUST = TZ_DIFF * msPerHour; 227var TIME_1970 = 0; 228var TIME_2000 = 946684800000; 229var TIME_1900 = -2208988800000; 230var UTC_29_FEB_2000 = TIME_2000 + 31*msPerDay + 28*msPerDay; 231var UTC_1_JAN_2005 = TIME_2000 + TimeInYear(2000) + TimeInYear(2001) + 232 TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004); 233var now = new Date(); 234var 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*/ 245function getTimeZoneDiff() 246{ 247 return -((new Date(2000, 1, 1)).getTimezoneOffset())/60; 248} 249 250 251function Day( t) 252{ 253 return ( Math.floor( t/msPerDay ) ); 254} 255 256 257function 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 270function TimeInYear( y ) 271{ 272 return ( DaysInYear(y) * msPerDay ); 273} 274 275 276function DayNumber( t ) 277{ 278 return ( Math.floor( t / msPerDay ) ); 279} 280 281 282function TimeWithinDay( t ) 283{ 284 if ( t < 0 ) {return ( (t%msPerDay) + msPerDay );} 285 else {return ( t % msPerDay );} 286} 287 288 289function YearNumber( t ) 290{ 291} 292 293 294function TimeFromYear( y ) 295{ 296 return ( msPerDay * DayFromYear(y) ); 297} 298 299 300function 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 307function 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 316function 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 344function 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 366function DayWithinYear( t ) 367{ 368 return(Day(t) - DayFromYear(YearFromTime(t)) ); 369} 370 371 372function 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 393function 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 403function HourFromTime( t ) 404{ 405 var h = Math.floor( t / msPerHour )%HoursPerDay; 406 return ( (h<0) ? HoursPerDay + h : h ); 407} 408 409 410function MinFromTime( t ) 411{ 412 var min = Math.floor( t / msPerMinute )%MinutesPerHour; 413 return( (min < 0 ) ? MinutesPerHour + min : min ); 414} 415 416 417function SecFromTime( t ) 418{ 419 var sec = Math.floor( t / msPerSecond )%SecondsPerMinute; 420 return ( (sec < 0 ) ? SecondsPerMinute + sec : sec ); 421} 422 423 424function msFromTime( t ) 425{ 426 var ms = t%msPerSecond; 427 return ( (ms < 0 ) ? msPerSecond + ms : ms ); 428} 429 430 431function LocalTZA() 432{ 433 return ( TZ_DIFF * msPerHour ); 434} 435 436 437function UTC( t ) 438{ 439 return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); 440} 441 442 443function 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 456print( new Date( UTC(dst_start + LocalTZA())) ); 457return UTC(dst_start + LocalTZA()); 458} 459 460function 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} 475function 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. 491function 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} 509function 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 525function LocalTime( t ) 526{ 527 return ( t + LocalTZA() + DaylightSavingTA(t) ); 528} 529 530 531function 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 544function 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 589function 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 605function 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 625function 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 634function 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 653function 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 662function GetContext() 663{ 664 return Packages.com.netscape.javascript.Context.getCurrentContext(); 665} 666 667 668function OptLevel( i ) 669{ 670 i = Number(i); 671 var cx = GetContext(); 672 cx.setOptimizationLevel(i); 673} 674 675/* end of Rhino functions */ 676 677