1var completed = false; 2var testcases; 3var tc = 0; 4 5SECTION = ""; 6VERSION = ""; 7BUGNUMBER = ""; 8EXCLUDE = ""; 9BUGNUMBER = ""; 10 11 12TZ_DIFF = -8; 13 14var TT = ""; 15var TT_ = ""; 16var BR = ""; 17var NBSP = " "; 18var CR = "\n"; 19var FONT = ""; 20var FONT_ = ""; 21var FONT_RED = ""; 22var FONT_GREEN = ""; 23var B = ""; 24var B_ = "" 25var H2 = ""; 26var H2_ = ""; 27var HR = ""; 28var DEBUG = false; 29 30 31var PASSED = " PASSED!" 32var FAILED = " FAILED! expected: "; 33function test() { 34 for ( tc=0; tc < testcases.length; tc++ ) { 35 testcases[tc].passed = writeTestCaseResult( 36 testcases[tc].expect, 37 testcases[tc].actual, 38 testcases[tc].description +" = "+ 39 testcases[tc].actual ); 40 41 testcases[tc].reason += ( testcases[tc].passed ) ? "" : "wrong value "; 42 } 43 stopTest(); 44 return ( testcases ); 45} 46 47function TestCase( n, d, e, a ) { 48 this.name = n; 49 this.description = d; 50 this.expect = e; 51 this.actual = a; 52 this.passed = true; 53 this.reason = ""; 54 this.bugnumber = BUGNUMBER; 55 56 this.passed = getTestCaseResult( this.expect, this.actual ); 57 if ( DEBUG ) { 58 writeLineToLog( "added " + this.description ); 59 } 60} 61function startTest() { 62 // JavaScript 1.3 is supposed to be compliant ecma version 1.0 63 if ( VERSION == "ECMA_1" ) { 64 version ( "130" ); 65 } 66 if ( VERSION == "JS_13" ) { 67 version ( "130" ); 68 } 69 if ( VERSION == "JS_12" ) { 70 version ( "120" ); 71 } 72 if ( VERSION == "JS_11" ) { 73 version ( "110" ); 74 } 75 // for ecma version 2.0, we will leave the javascript version to 76 // the default ( for now ). 77 writeHeaderToLog( SECTION + " "+ TITLE); 78 testcases = new Array(); 79 tc = 0; 80 81} 82function getTestCaseResult( expect, actual ) { 83 // because ( NaN == NaN ) always returns false, need to do 84 // a special compare to see if we got the right result. 85 if ( actual != actual ) { 86 if ( typeof actual == "object" ) { 87 actual = "NaN object"; 88 } else { 89 actual = "NaN number"; 90 } 91 } 92 if ( expect != expect ) { 93 if ( typeof expect == "object" ) { 94 expect = "NaN object"; 95 } else { 96 expect = "NaN number"; 97 } 98 } 99 100 var passed = ( expect == actual ) ? true : false; 101 102 // if both objects are numbers 103 // need to replace w/ IEEE standard for rounding 104 if ( !passed 105 && typeof(actual) == "number" 106 && typeof(expect) == "number" 107 ) { 108 if ( Math.abs(actual-expect) < 0.0000001 ) { 109 passed = true; 110 } 111 } 112 113 // verify type is the same 114 if ( typeof(expect) != typeof(actual) ) { 115 passed = false; 116 } 117 118 return passed; 119} 120function writeTestCaseResult( expect, actual, string ) { 121 var passed = getTestCaseResult( expect, actual ); 122 writeFormattedResult( expect, actual, string, passed ); 123 return passed; 124} 125function writeFormattedResult( expect, actual, string, passed ) { 126 var s = TT + string ; 127 128 for ( k = 0; 129 k < (60 - string.length >= 0 ? 60 - string.length : 5) ; 130 k++ ) { 131 } 132 133 s += B ; 134 s += ( passed ) ? FONT_GREEN + NBSP + PASSED : FONT_RED + NBSP + FAILED + expect + TT_ ; 135 136 writeLineToLog( s + FONT_ + B_ + TT_ ); 137 138 return passed; 139} 140 141function writeLineToLog( string ) { 142 print( string + BR + CR ); 143} 144function writeHeaderToLog( string ) { 145 print( H2 + string + H2_ ); 146} 147function stopTest() 148{ 149 var sizeTag = "<#TEST CASES SIZE>"; 150 var doneTag = "<#TEST CASES DONE>"; 151 var beginTag = "<#TEST CASE "; 152 var endTag = ">"; 153 154 print(sizeTag); 155 print(testcases.length); 156 for (tc = 0; tc < testcases.length; tc++) 157 { 158 print(beginTag + 'PASSED' + endTag); 159 print(testcases[tc].passed); 160 print(beginTag + 'NAME' + endTag); 161 print(testcases[tc].name); 162 print(beginTag + 'EXPECTED' + endTag); 163 print(testcases[tc].expect); 164 print(beginTag + 'ACTUAL' + endTag); 165 print(testcases[tc].actual); 166 print(beginTag + 'DESCRIPTION' + endTag); 167 print(testcases[tc].description); 168 print(beginTag + 'REASON' + endTag); 169 print(( testcases[tc].passed ) ? "" : "wrong value "); 170 print(beginTag + 'BUGNUMBER' + endTag); 171 print( BUGNUMBER ); 172 } 173 print(doneTag); 174 print( HR ); 175 gc(); 176} 177function getFailedCases() { 178 for ( var i = 0; i < testcases.length; i++ ) { 179 if ( ! testcases[i].passed ) { 180 print( testcases[i].description +" = " +testcases[i].actual +" expected: "+ testcases[i].expect ); 181 } 182 } 183} 184function err( msg, page, line ) { 185 testcases[tc].actual = "error"; 186 testcases[tc].reason = msg; 187 writeTestCaseResult( testcases[tc].expect, 188 testcases[tc].actual, 189 testcases[tc].description +" = "+ testcases[tc].actual + 190 ": " + testcases[tc].reason ); 191 stopTest(); 192 return true; 193} 194 195/** 196 * Type Conversion functions used by Type Conversion 197 * 198 */ 199 200 201 202 /* 203 * Date functions used by tests in Date suite 204 * 205 */ 206var msPerDay = 86400000; 207var HoursPerDay = 24; 208var MinutesPerHour = 60; 209var SecondsPerMinute = 60; 210var msPerSecond = 1000; 211var msPerMinute = 60000; // msPerSecond * SecondsPerMinute 212var msPerHour = 3600000; // msPerMinute * MinutesPerHour 213 214var TIME_1970 = 0; 215var TIME_2000 = 946684800000; 216var TIME_1900 = -2208988800000; 217 218function Day( t ) { 219 return ( Math.floor(t/msPerDay ) ); 220} 221function DaysInYear( y ) { 222 if ( y % 4 != 0 ) { 223 return 365; 224 } 225 if ( (y % 4 == 0) && (y % 100 != 0) ) { 226 return 366; 227 } 228 if ( (y % 100 == 0) && (y % 400 != 0) ) { 229 return 365; 230 } 231 if ( (y % 400 == 0) ){ 232 return 366; 233 } else { 234 return "ERROR: DaysInYear(" + y + ") case not covered"; 235 } 236} 237function TimeInYear( y ) { 238 return ( DaysInYear(y) * msPerDay ); 239} 240function DayNumber( t ) { 241 return ( Math.floor( t / msPerDay ) ); 242} 243function TimeWithinDay( t ) { 244 if ( t < 0 ) { 245 return ( (t % msPerDay) + msPerDay ); 246 } else { 247 return ( t % msPerDay ); 248 } 249} 250function YearNumber( t ) { 251} 252function TimeFromYear( y ) { 253 return ( msPerDay * DayFromYear(y) ); 254} 255function DayFromYear( y ) { 256 return ( 365*(y-1970) + 257 Math.floor((y-1969)/4) - 258 Math.floor((y-1901)/100) + 259 Math.floor((y-1601)/400) ); 260} 261function InLeapYear( t ) { 262 if ( DaysInYear(YearFromTime(t)) == 365 ) { 263 return 0; 264 } 265 if ( DaysInYear(YearFromTime(t)) == 366 ) { 266 return 1; 267 } else { 268 return "ERROR: InLeapYear("+t+") case not covered"; 269 } 270} 271function YearFromTime( t ) { 272 t = Number( t ); 273 var sign = ( t < 0 ) ? -1 : 1; 274 var year = ( sign < 0 ) ? 1969 : 1970; 275 for ( var timeToTimeZero = t; ; ) { 276 // subtract the current year's time from the time that's left. 277 timeToTimeZero -= sign * TimeInYear(year) 278 279 // if there's less than the current year's worth of time left, then break. 280 if ( sign < 0 ) { 281 if ( sign * timeToTimeZero <= 0 ) { 282 break; 283 } else { 284 year += sign; 285 } 286 } else { 287 if ( sign * timeToTimeZero < 0 ) { 288 break; 289 } else { 290 year += sign; 291 } 292 } 293 } 294 return ( year ); 295} 296function MonthFromTime( t ) { 297 // i know i could use switch but i'd rather not until it's part of ECMA 298 var day = DayWithinYear( t ); 299 var leap = InLeapYear(t); 300 301 if ( (0 <= day) && (day < 31) ) { 302 return 0; 303 } 304 if ( (31 <= day) && (day < (59+leap)) ) { 305 return 1; 306 } 307 if ( ((59+leap) <= day) && (day < (90+leap)) ) { 308 return 2; 309 } 310 if ( ((90+leap) <= day) && (day < (120+leap)) ) { 311 return 3; 312 } 313 if ( ((120+leap) <= day) && (day < (151+leap)) ) { 314 return 4; 315 } 316 if ( ((151+leap) <= day) && (day < (181+leap)) ) { 317 return 5; 318 } 319 if ( ((181+leap) <= day) && (day < (212+leap)) ) { 320 return 6; 321 } 322 if ( ((212+leap) <= day) && (day < (243+leap)) ) { 323 return 7; 324 } 325 if ( ((243+leap) <= day) && (day < (273+leap)) ) { 326 return 8; 327 } 328 if ( ((273+leap) <= day) && (day < (304+leap)) ) { 329 return 9; 330 } 331 if ( ((304+leap) <= day) && (day < (334+leap)) ) { 332 return 10; 333 } 334 if ( ((334+leap) <= day) && (day < (365+leap)) ) { 335 return 11; 336 } else { 337 return "ERROR: MonthFromTime("+t+") not known"; 338 } 339} 340function DayWithinYear( t ) { 341 return( Day(t) - DayFromYear(YearFromTime(t))); 342} 343function DateFromTime( t ) { 344 var day = DayWithinYear(t); 345 var month = MonthFromTime(t); 346 347 if ( month == 0 ) { 348 return ( day + 1 ); 349 } 350 if ( month == 1 ) { 351 return ( day - 30 ); 352 } 353 if ( month == 2 ) { 354 return ( day - 58 - InLeapYear(t) ); 355 } 356 if ( month == 3 ) { 357 return ( day - 89 - InLeapYear(t)); 358 } 359 if ( month == 4 ) { 360 return ( day - 119 - InLeapYear(t)); 361 } 362 if ( month == 5 ) { 363 return ( day - 150- InLeapYear(t)); 364 } 365 if ( month == 6 ) { 366 return ( day - 180- InLeapYear(t)); 367 } 368 if ( month == 7 ) { 369 return ( day - 211- InLeapYear(t)); 370 } 371 if ( month == 8 ) { 372 return ( day - 242- InLeapYear(t)); 373 } 374 if ( month == 9 ) { 375 return ( day - 272- InLeapYear(t)); 376 } 377 if ( month == 10 ) { 378 return ( day - 303- InLeapYear(t)); 379 } 380 if ( month == 11 ) { 381 return ( day - 333- InLeapYear(t)); 382 } 383 384 return ("ERROR: DateFromTime("+t+") not known" ); 385} 386function WeekDay( t ) { 387 var weekday = (Day(t)+4) % 7; 388 return( weekday < 0 ? 7 + weekday : weekday ); 389} 390 391// missing daylight savins time adjustment 392 393function HourFromTime( t ) { 394 var h = Math.floor( t / msPerHour ) % HoursPerDay; 395 return ( (h<0) ? HoursPerDay + h : h ); 396} 397function MinFromTime( t ) { 398 var min = Math.floor( t / msPerMinute ) % MinutesPerHour; 399 return( ( min < 0 ) ? MinutesPerHour + min : min ); 400} 401function SecFromTime( t ) { 402 var sec = Math.floor( t / msPerSecond ) % SecondsPerMinute; 403 return ( (sec < 0 ) ? SecondsPerMinute + sec : sec ); 404} 405function msFromTime( t ) { 406 var ms = t % msPerSecond; 407 return ( (ms < 0 ) ? msPerSecond + ms : ms ); 408} 409function LocalTZA() { 410 return ( TZ_DIFF * msPerHour ); 411} 412function UTC( t ) { 413 return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); 414} 415function DaylightSavingTA( t ) { 416 t = t - LocalTZA(); 417 418 var dst_start = GetSecondSundayInMarch(t) + 2*msPerHour; 419 var dst_end = GetFirstSundayInNovember(t)+ 2*msPerHour; 420 421 if ( t >= dst_start && t < dst_end ) { 422 return msPerHour; 423 } else { 424 return 0; 425 } 426 427 // Daylight Savings Time starts on the first Sunday in April at 2:00AM in 428 // PST. Other time zones will need to override this function. 429 430 print( new Date( UTC(dst_start + LocalTZA())) ); 431 432 return UTC(dst_start + LocalTZA()); 433} 434 435function GetFirstSundayInApril( t ) { 436 var year = YearFromTime(t); 437 var leap = InLeapYear(t); 438 439 var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) + 440 TimeInMonth(2,leap); 441 442 for ( var first_sunday = april; WeekDay(first_sunday) > 0; 443 first_sunday += msPerDay ) 444 { 445 ; 446 } 447 448 return first_sunday; 449} 450function GetLastSundayInOctober( t ) { 451 var year = YearFromTime(t); 452 var leap = InLeapYear(t); 453 454 for ( var oct = TimeFromYear(year), m = 0; m < 9; m++ ) { 455 oct += TimeInMonth(m, leap); 456 } 457 for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0; 458 last_sunday -= msPerDay ) 459 { 460 ; 461 } 462 return last_sunday; 463} 464 465// Added these two functions because DST rules changed for the US. 466function GetSecondSundayInMarch( t ) { 467 var year = YearFromTime(t); 468 var leap = InLeapYear(t); 469 470 var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap); 471 472 var sundayCount = 0; 473 var flag = true; 474 for ( var second_sunday = march; flag; second_sunday += msPerDay ) 475 { 476 if (WeekDay(second_sunday) == 0) { 477 if(++sundayCount == 2) 478 flag = false; 479 } 480 } 481 482 return second_sunday; 483} 484function GetFirstSundayInNovember( t ) { 485 var year = YearFromTime(t); 486 var leap = InLeapYear(t); 487 488 for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) { 489 nov += TimeInMonth(m, leap); 490 } 491 for ( var first_sunday = nov; WeekDay(first_sunday) > 0; 492 first_sunday += msPerDay ) 493 { 494 ; 495 } 496 return first_sunday; 497} 498function LocalTime( t ) { 499 return ( t + LocalTZA() + DaylightSavingTA(t) ); 500} 501function MakeTime( hour, min, sec, ms ) { 502 if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) { 503 return Number.NaN; 504 } 505 506 hour = ToInteger(hour); 507 min = ToInteger( min); 508 sec = ToInteger( sec); 509 ms = ToInteger( ms ); 510 511 return( (hour*msPerHour) + (min*msPerMinute) + 512 (sec*msPerSecond) + ms ); 513} 514function MakeDay( year, month, date ) { 515 if ( isNaN(year) || isNaN(month) || isNaN(date) ) { 516 return Number.NaN; 517 } 518 year = ToInteger(year); 519 month = ToInteger(month); 520 date = ToInteger(date ); 521 522 var sign = ( year < 1970 ) ? -1 : 1; 523 var t = ( year < 1970 ) ? 1 : 0; 524 var y = ( year < 1970 ) ? 1969 : 1970; 525 526 var result5 = year + Math.floor( month/12 ); 527 var result6 = month % 12; 528 529 if ( year < 1970 ) { 530 for ( y = 1969; y >= year; y += sign ) { 531 t += sign * TimeInYear(y); 532 } 533 } else { 534 for ( y = 1970 ; y < year; y += sign ) { 535 t += sign * TimeInYear(y); 536 } 537 } 538 539 var leap = InLeapYear( t ); 540 541 for ( var m = 0; m < month; m++ ) { 542 t += TimeInMonth( m, leap ); 543 } 544 545 if ( YearFromTime(t) != result5 ) { 546 return Number.NaN; 547 } 548 if ( MonthFromTime(t) != result6 ) { 549 return Number.NaN; 550 } 551 if ( DateFromTime(t) != 1 ) { 552 return Number.NaN; 553 } 554 555 return ( (Day(t)) + date - 1 ); 556} 557function TimeInMonth( month, leap ) { 558 // september april june november 559 // jan 0 feb 1 mar 2 apr 3 may 4 june 5 jul 6 560 // aug 7 sep 8 oct 9 nov 10 dec 11 561 562 if ( month == 3 || month == 5 || month == 8 || month == 10 ) { 563 return ( 30*msPerDay ); 564 } 565 566 // all the rest 567 if ( month == 0 || month == 2 || month == 4 || month == 6 || 568 month == 7 || month == 9 || month == 11 ) { 569 return ( 31*msPerDay ); 570 } 571 572 // save february 573 return ( (leap == 0) ? 28*msPerDay : 29*msPerDay ); 574} 575function MakeDate( day, time ) { 576 if ( day == Number.POSITIVE_INFINITY || 577 day == Number.NEGATIVE_INFINITY || 578 day == Number.NaN ) { 579 return Number.NaN; 580 } 581 if ( time == Number.POSITIVE_INFINITY || 582 time == Number.POSITIVE_INFINITY || 583 day == Number.NaN) { 584 return Number.NaN; 585 } 586 return ( day * msPerDay ) + time; 587} 588function TimeClip( t ) { 589 if ( isNaN( t ) ) { 590 return ( Number.NaN ); 591 } 592 if ( Math.abs( t ) > 8.64e15 ) { 593 return ( Number.NaN ); 594 } 595 596 return ( ToInteger( t ) ); 597} 598function ToInteger( t ) { 599 t = Number( t ); 600 601 if ( isNaN( t ) ){ 602 return ( Number.NaN ); 603 } 604 if ( t == 0 || t == -0 || 605 t == Number.POSITIVE_INFINITY || t == Number.NEGATIVE_INFINITY ) { 606 return 0; 607 } 608 609 var sign = ( t < 0 ) ? -1 : 1; 610 611 return ( sign * Math.floor( Math.abs( t ) ) ); 612} 613function Enumerate ( o ) { 614 var properties = new Array(); 615 for ( p in o ) { 616 properties[ properties.length ] = new Array( p, o[p] ); 617 } 618 return properties; 619} 620function AddTestCase( description, expect, actual ) { 621 testcases[tc++] = new TestCase( SECTION, description, expect, actual ); 622} 623function getFailedCases() { 624 for ( var i = 0; i < testcases.length; i++ ) { 625 if ( ! testcases[i].passed ) { 626 print( testcases[i].description +" = " +testcases[i].actual +" expected: "+ testcases[i].expect ); 627 } 628 } 629} 630