Addendum to 605640: remove print function from shell.as as that will prevent some...
[tamarin-stm.git] / test / acceptance / shell.as
blob85936b6dc20df06cdaf968eedd99e25fdd03df03
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is [Open Source Virtual Machine.].
16 * The Initial Developer of the Original Code is
17 * Adobe System Incorporated.
18 * Portions created by the Initial Developer are Copyright (C) 2005-2006
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Adobe AS3 Team
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * JavaScript shared functions file for running the tests in either
39 * stand-alone JavaScript engine. To run a test, first load this file,
40 * then load the test script.
43 // import flash.system in order to determine what we are being run in
44 import flash.system.Capabilities;
45 var playerType:String = Capabilities.playerType;
48 var completed = false;
49 var testcases;
50 var tc = 0;
51 //var version; // ISSUE:: need to know why we need to comment this out
53 SECTION = "";
54 VERSION = "";
55 var BUGNUMBER = "";
56 var STATUS = "STATUS: ";
58 // constant strings
60 var GLOBAL = "[object global]";
61 var PASSED = " PASSED!"
62 var FAILED = " FAILED! expected: ";
63 var PACKAGELIST = "{public,$1$private}::";
64 var TYPEERROR = "TypeError: Error #";
65 var REFERENCEERROR = "ReferenceError: Error #";
66 var RANGEERROR = "RangeError: Error #";
67 var URIERROR = "URIError: Error #";
68 var EVALERROR = "EvalError: Error #";
69 var VERIFYERROR = "VerifyError: Error #";
70 var VERBOSE = true;
72 var DEBUG = false;
74 function typeError( str ){
75 return str.slice(0,TYPEERROR.length+4);
78 function referenceError( str ){
79 return str.slice(0,REFERENCEERROR.length+4);
81 function rangeError( str ){
82 return str.slice(0,RANGEERROR.length+4);
84 function uriError( str ){
85 return str.slice(0,URIERROR.length+4);
88 function evalError( str ){
89 return str.slice(0,EVALERROR.length+4);
92 function verifyError( str ){
93 return str.slice(0,VERIFYERROR.length+4);
96 // wrapper for test cas constructor that doesn't require the SECTION
97 // argument.
100 function AddTestCase( description, expect, actual ) {
101 testcases[tc++] = new TestCase( SECTION, description, expect, actual );
105 // TestCase constructor
108 function TestCase( n, d, e, a ) {
109 this.name = n;
110 this.description = d;
111 this.expect = e;
112 this.actual = a;
113 this.passed = "";
114 this.reason = "";
115 //this.bugnumber = BUGNUMBER;
117 this.passed = getTestCaseResult( this.expect, this.actual );
118 if ( DEBUG ) {
119 writeLineToLog( "added " + this.description );
124 // Set up test environment.
127 function startTest() {
128 // print out bugnumber
129 /*if ( BUGNUMBER ) {
130 writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
133 testcases = new Array();
134 tc = 0;
137 function checkReason(passed) {
138 var reason;
139 if (passed == 'true') {
140 reason = "";
141 } else if (passed == 'false') {
142 reason = "wrong value";
143 } else if (passed == 'type error') {
144 reason = "type error";
146 return reason;
150 function test(... rest:Array) {
152 if( rest.length == 0 ){
153 // no args sent, use default test
154 for ( tc=0; tc < testcases.length; tc++ ) {
155 testcases[tc].passed = writeTestCaseResult(
156 testcases[tc].expect,
157 testcases[tc].actual,
158 testcases[tc].description +" = "+ testcases[tc].actual );
159 testcases[tc].reason += checkReason(testcases[tc].passed);
161 } else {
162 // we need to use a specialized call to writeTestCaseResult
163 if( rest[0] == "no actual" ){
164 for ( tc=0; tc < testcases.length; tc++ ) {
165 testcases[tc].passed = writeTestCaseResult(
166 testcases[tc].expect,
167 testcases[tc].actual,
168 testcases[tc].description );
169 testcases[tc].reason += checkReason(testcases[tc].passed);
173 stopTest();
174 return ( testcases );
178 // Compare expected result to the actual result and figure out whether
179 // the test case passed.
181 function getTestCaseResult(expect,actual) {
182 // because ( NaN == NaN ) always returns false, need to do
183 // a special compare to see if we got the right result.
184 if ( actual != actual ) {
185 if ( typeof actual == "object" ) {
186 actual = "NaN object";
187 } else {
188 actual = "NaN number";
191 if ( expect != expect ) {
192 if ( typeof expect == "object" ) {
193 expect = "NaN object";
194 } else {
195 expect = "NaN number";
198 var passed="";
199 if (expect == actual) {
200 if ( typeof(expect) != typeof(actual) ){
201 passed = "type error";
202 } else {
203 passed = "true";
205 } else { //expect != actual
206 passed = "false";
207 // if both objects are numbers
208 // need to replace w/ IEEE standard for rounding
209 if (typeof(actual) == "number" && typeof(expect) == "number") {
210 if ( Math.abs(actual-expect) < 0.0000001 ) {
211 passed = "true";
215 return passed;
218 // Begin printing functions. These functions use the shell's
219 // print function. When running tests in the browser, these
220 // functions, override these functions with functions that use
221 // document.write.
223 function writeTestCaseResult( expect, actual, string ) {
224 var passed = getTestCaseResult(expect,actual);
225 var s = string;
226 if (passed == "true") {
227 s += PASSED;
228 } else if (passed == "false") {
229 s += FAILED + expect;
230 } else if (passed == "type error") {
231 s += FAILED + expect + " Type Mismatch - Expected Type: "+ typeof(expect) + ", Result Type: "+ typeof(actual);
232 } else { //should never happen
233 s += FAILED + " UNEXPECTED ERROR - see shell.as:writeTestCaseResult()"
236 if (playerType == 'AVMPlus') {
237 writeLineToLog(s);
238 } else { // not running in avm, so must in ATS
239 // instead of passing the expected and actual to the ATS and having
240 // the ATS do the comparison, we are passing the pass / fail string
241 // so that we are guarenteed that test results are the same in the avm
242 // and in the ATS
243 addToATS(string + PASSED, s, string);
245 return passed;
249 function addToATS(expected, actual, description) {
250 // Testcase Description
251 this[fileName+"Str"].push(description);
253 // Testcase Actual Values returned
254 this[fileName].push(actual);
256 // Testcase Expected Values Return
257 this[fileName+"Ans"].push(expected);
261 //redundant, but leaving in in case its used elsewhere
263 function writeFormattedResult( expect, actual, string, passed ) {
264 var s = string ;
265 s += ( passed ) ? PASSED : FAILED + expect;
266 writeLineToLog( s);
267 return passed;
271 function writeLineToLog( string ) {
272 _print( string );
274 function writeHeaderToLog( string ) {
275 _print( string );
277 // end of print functions
279 function as3Enabled():Boolean {
280 // return whether the test was compiled with -AS3
281 return ((new Boolean()).valueOf != Boolean.prototype.valueOf)
285 // When running in the shell, run the garbage collector after the
286 // test has completed.
288 function stopTest(){
289 // Call ATS Function if not running in AVM
290 if (playerType != 'AVMPlus') {
293 ATS.testOver2(this[fileName+"Str"],this[fileName+"Ans"],this[fileName],fileName);
294 } catch ( e ) {
300 // Date functions used by tests in Date suite
302 // Originally, the test suite used a hard-coded value TZ_DIFF = -8.
303 // But that was only valid for testers in the Pacific Standard Time Zone!
304 // We calculate the proper number dynamically for any tester. We just
305 // have to be careful not to use a date subject to Daylight Savings Time...
307 function getTimeZoneDiff()
309 return -((new Date(2000, 1, 1)).getTimezoneOffset())/60;
312 var msPerDay = 86400000;
313 var HoursPerDay = 24;
314 var MinutesPerHour = 60;
315 var SecondsPerMinute = 60;
316 var msPerSecond = 1000;
317 var msPerMinute = 60000; // msPerSecond * SecondsPerMinute
318 var msPerHour = 3600000; // msPerMinute * MinutesPerHour
319 var TZ_DIFF = getTimeZoneDiff(); // offset of tester's timezone from UTC
320 var TZ_PST = -8; // offset of Pacific Standard Time from UTC
321 var PST_DIFF = TZ_DIFF - TZ_PST; // offset of tester's timezone from PST
322 var TIME_1970 = 0;
323 var TIME_2000 = 946684800000;
324 var TIME_1900 = -2208988800000;
325 var now = new Date();
326 var TZ_DIFF = getTimeZoneDiff();
327 var TZ_ADJUST = TZ_DIFF * msPerHour;
328 var UTC_29_FEB_2000 = TIME_2000 + 31*msPerDay + 28*msPerDay;
329 var UTC_1_JAN_2005 = TIME_2000 + TimeInYear(2000) + TimeInYear(2001) +
330 TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004);
331 var TIME_NOW = now.valueOf();
337 // Date test "ResultArrays" are hard-coded for Pacific Standard Time.
338 // We must adjust them for the tester's own timezone -
340 function adjustResultArray(ResultArray, msMode)
342 // If the tester's system clock is in PST, no need to continue -
343 if (!PST_DIFF) {return;}
345 // The date testcases instantiate Date objects in two different ways:
347 // millisecond mode: e.g. dt = new Date(10000000);
348 // year-month-day mode: dt = new Date(2000, 5, 1, ...);
350 // In the first case, the date is measured from Time 0 in Greenwich (i.e. UTC).
351 // In the second case, it is measured with reference to the tester's local timezone.
353 // In the first case we must correct those values expected for local measurements,
354 // like dt.getHours() etc. No correction is necessary for dt.getUTCHours() etc.
356 // In the second case, it is exactly the other way around -
358 var t;
359 if (msMode)
361 // The hard-coded UTC milliseconds from Time 0 derives from a UTC date.
362 // Shift to the right by the offset between UTC and the tester.
363 t = ResultArray[TIME] + TZ_DIFF*msPerHour;
365 // Use our date arithmetic functions to determine the local hour, day, etc.
366 ResultArray[HOURS] = HourFromTime(t);
367 ResultArray[DAY] = WeekDay(t);
368 ResultArray[DATE] = DateFromTime(t);
369 ResultArray[MONTH] = MonthFromTime(t);
370 ResultArray[YEAR] = YearFromTime(t);
372 else
374 // The hard-coded UTC milliseconds from Time 0 derives from a PST date.
375 // Shift to the left by the offset between PST and the tester.
376 t = ResultArray[TIME] - PST_DIFF*msPerHour;
378 // Use our date arithmetic functions to determine the UTC hour, day, etc.
379 ResultArray[TIME] = t;
380 ResultArray[UTC_HOURS] = HourFromTime(t);
381 ResultArray[UTC_DAY] = WeekDay(t);
382 ResultArray[UTC_DATE] = DateFromTime(t);
383 ResultArray[UTC_MONTH] = MonthFromTime(t);
384 ResultArray[UTC_YEAR] = YearFromTime(t);
389 function Day( t ) {
390 return ( Math.floor(t/msPerDay ) );
392 function DaysInYear( y ) {
393 if ( y % 4 != 0 ) {
394 return 365;
396 if ( (y % 4 == 0) && (y % 100 != 0) ) {
397 return 366;
399 if ( (y % 100 == 0) && (y % 400 != 0) ) {
400 return 365;
402 if ( (y % 400 == 0) ){
403 return 366;
404 } else {
405 _print("ERROR: DaysInYear(" + y + ") case not covered");
406 return Math.NaN; //"ERROR: DaysInYear(" + y + ") case not covered";
409 function TimeInYear( y ) {
410 return ( DaysInYear(y) * msPerDay );
412 function DayNumber( t ) {
413 return ( Math.floor( t / msPerDay ) );
415 function TimeWithinDay( t ) {
416 if ( t < 0 ) {
417 return ( (t % msPerDay) + msPerDay );
418 } else {
419 return ( t % msPerDay );
422 function YearNumber( t ) {
424 function TimeFromYear( y ) {
425 return ( msPerDay * DayFromYear(y) );
427 function DayFromYear( y ) {
428 return ( 365*(y-1970) +
429 Math.floor((y-1969)/4) -
430 Math.floor((y-1901)/100) +
431 Math.floor((y-1601)/400) );
433 function InLeapYear( t ) {
434 if ( DaysInYear(YearFromTime(t)) == 365 ) {
435 return 0;
437 if ( DaysInYear(YearFromTime(t)) == 366 ) {
438 return 1;
439 } else {
440 return "ERROR: InLeapYear("+ t + ") case not covered";
443 function YearFromTime( t ) {
444 t = Number( t );
445 var sign = ( t < 0 ) ? -1 : 1;
446 var year = ( sign < 0 ) ? 1969 : 1970;
448 for ( var timeToTimeZero = t; ; ) {
449 // subtract the current year's time from the time that's left.
450 timeToTimeZero -= sign * TimeInYear(year)
451 if (isNaN(timeToTimeZero))
452 return NaN;
454 // if there's less than the current year's worth of time left, then break.
455 if ( sign < 0 ) {
456 if ( sign * timeToTimeZero <= 0 ) {
457 break;
458 } else {
459 year += sign;
461 } else {
462 if ( sign * timeToTimeZero < 0 ) {
463 break;
464 } else {
465 year += sign;
469 return ( year );
471 function MonthFromTime( t ) {
472 // i know i could use switch but i'd rather not until it's part of ECMA
473 var day = DayWithinYear( t );
474 var leap = InLeapYear(t);
476 if ( (0 <= day) && (day < 31) ) {
477 return 0;
479 if ( (31 <= day) && (day < (59+leap)) ) {
480 return 1;
482 if ( ((59+leap) <= day) && (day < (90+leap)) ) {
483 return 2;
485 if ( ((90+leap) <= day) && (day < (120+leap)) ) {
486 return 3;
488 if ( ((120+leap) <= day) && (day < (151+leap)) ) {
489 return 4;
491 if ( ((151+leap) <= day) && (day < (181+leap)) ) {
492 return 5;
494 if ( ((181+leap) <= day) && (day < (212+leap)) ) {
495 return 6;
497 if ( ((212+leap) <= day) && (day < (243+leap)) ) {
498 return 7;
500 if ( ((243+leap) <= day) && (day < (273+leap)) ) {
501 return 8;
503 if ( ((273+leap) <= day) && (day < (304+leap)) ) {
504 return 9;
506 if ( ((304+leap) <= day) && (day < (334+leap)) ) {
507 return 10;
509 if ( ((334+leap) <= day) && (day < (365+leap)) ) {
510 return 11;
511 } else {
512 return "ERROR: MonthFromTime("+t+") not known";
515 function DayWithinYear( t ) {
516 return( Day(t) - DayFromYear(YearFromTime(t)));
518 function DateFromTime( t ) {
519 var day = DayWithinYear(t);
520 var month = MonthFromTime(t);
521 if ( month == 0 ) {
522 return ( day + 1 );
524 if ( month == 1 ) {
525 return ( day - 30 );
527 if ( month == 2 ) {
528 return ( day - 58 - InLeapYear(t) );
530 if ( month == 3 ) {
531 return ( day - 89 - InLeapYear(t));
533 if ( month == 4 ) {
534 return ( day - 119 - InLeapYear(t));
536 if ( month == 5 ) {
537 return ( day - 150- InLeapYear(t));
539 if ( month == 6 ) {
540 return ( day - 180- InLeapYear(t));
542 if ( month == 7 ) {
543 return ( day - 211- InLeapYear(t));
545 if ( month == 8 ) {
546 return ( day - 242- InLeapYear(t));
548 if ( month == 9 ) {
549 return ( day - 272- InLeapYear(t));
551 if ( month == 10 ) {
552 return ( day - 303- InLeapYear(t));
554 if ( month == 11 ) {
555 return ( day - 333- InLeapYear(t));
558 return ("ERROR: DateFromTime("+t+") not known" );
560 function WeekDay( t ) {
561 var weekday = (Day(t)+4) % 7;
562 return( weekday < 0 ? 7 + weekday : weekday );
565 // missing daylight savins time adjustment
567 function HourFromTime( t ) {
568 var h = Math.floor( t / msPerHour ) % HoursPerDay;
569 return ( (h<0) ? HoursPerDay + h : h );
571 function MinFromTime( t ) {
572 var min = Math.floor( t / msPerMinute ) % MinutesPerHour;
573 return( ( min < 0 ) ? MinutesPerHour + min : min );
575 function SecFromTime( t ) {
576 var sec = Math.floor( t / msPerSecond ) % SecondsPerMinute;
577 return ( (sec < 0 ) ? SecondsPerMinute + sec : sec );
579 function msFromTime( t ) {
580 var ms = t % msPerSecond;
581 return ( (ms < 0 ) ? msPerSecond + ms : ms );
583 function LocalTZA() {
584 return ( TZ_DIFF * msPerHour );
586 function UTC( t ) {
587 return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) );
590 function DaylightSavingTA( t ) {
591 var dst_start;
592 var dst_end;
593 // Windows fix for 2007 DST change made all previous years follow new DST rules
594 // check to see if 3/13/2006 12pm getHours is 12 or 13
595 var dstPrev:Boolean=(new Date(1142269200000).getHours()==13);
596 if (TZ_DIFF<=-4 && TZ_DIFF>=-8) {
597 if (dstPrev || YearFromTime(t)>=2007) {
598 dst_start = GetSecondSundayInMarch(t) + 2*msPerHour;
599 dst_end = GetFirstSundayInNovember(t) + 2*msPerHour;
600 } else {
601 dst_start = GetFirstSundayInApril(t) + 2*msPerHour;
602 dst_end = GetLastSundayInOctober(t) + 2*msPerHour;
604 } else {
605 dst_start = GetLastSundayInMarch(t) + 2*msPerHour;
606 dst_end = GetLastSundayInOctober(t) + 2*msPerHour;
608 if ( t >= dst_start && t < dst_end ) {
609 return msPerHour;
610 } else {
611 return 0;
615 // Daylight Savings Time starts on the second Sunday in March at 2:00AM in
616 // PST. Other time zones will need to override this function.
617 _print( new Date( UTC(dst_start + LocalTZA())) );
619 return UTC(dst_start + LocalTZA());
621 function GetLastSundayInMarch(t) {
622 var year = YearFromTime(t);
623 var leap = InLeapYear(t);
624 var march = TimeFromYear(year) + TimeInMonth(0,leap) + TimeInMonth(1,leap)-LocalTZA()+2*msPerHour;
625 var sunday;
626 for( sunday=march;WeekDay(sunday)>0;sunday +=msPerDay ){;}
627 var last_sunday;
628 while (true) {
629 sunday=sunday+7*msPerDay;
630 if (MonthFromTime(sunday)>2)
631 break;
632 last_sunday=sunday;
634 return last_sunday;
636 function GetSecondSundayInMarch(t ) {
637 var year = YearFromTime(t);
638 var leap = InLeapYear(t);
639 var march = TimeFromYear(year) + TimeInMonth(0,leap) + TimeInMonth(1,leap)-LocalTZA()+2*msPerHour;
641 for ( var first_sunday = march; WeekDay(first_sunday) >0;
642 first_sunday +=msPerDay )
646 second_sunday=first_sunday+7*msPerDay;
647 return second_sunday;
652 function GetFirstSundayInNovember( t ) {
653 var year = YearFromTime(t);
654 var leap = InLeapYear(t);
655 var nov,m;
656 for ( nov = TimeFromYear(year), m = 0; m < 10; m++ ) {
657 nov += TimeInMonth(m, leap);
659 nov=nov-LocalTZA()+2*msPerHour;
660 for ( var first_sunday = nov; WeekDay(first_sunday) > 0;
661 first_sunday += msPerDay )
665 return first_sunday;
667 function GetFirstSundayInApril( t ) {
668 var year = YearFromTime(t);
669 var leap = InLeapYear(t);
670 var apr,m;
671 for ( apr = TimeFromYear(year), m = 0; m < 3; m++ ) {
672 apr += TimeInMonth(m, leap);
674 apr=apr-LocalTZA()+2*msPerHour;
676 for ( var first_sunday = apr; WeekDay(first_sunday) > 0;
677 first_sunday += msPerDay )
681 return first_sunday;
683 function GetLastSundayInOctober(t) {
684 var year = YearFromTime(t);
685 var leap = InLeapYear(t);
686 var oct,m;
687 for (oct = TimeFromYear(year), m = 0; m < 9; m++ ) {
688 oct += TimeInMonth(m, leap);
690 oct=oct-LocalTZA()+2*msPerHour;
691 var sunday;
692 for( sunday=oct;WeekDay(sunday)>0;sunday +=msPerDay ){;}
693 var last_sunday;
694 while (true) {
695 last_sunday=sunday;
696 sunday=sunday+7*msPerDay;
697 if (MonthFromTime(sunday)>9)
698 break;
700 return last_sunday;
702 function LocalTime( t ) {
703 return ( t + LocalTZA() + DaylightSavingTA(t) );
705 function MakeTime( hour, min, sec, ms ) {
706 if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) {
707 return Number.NaN;
710 hour = ToInteger(hour);
711 min = ToInteger( min);
712 sec = ToInteger( sec);
713 ms = ToInteger( ms );
715 return( (hour*msPerHour) + (min*msPerMinute) +
716 (sec*msPerSecond) + ms );
718 function MakeDay( year, month, date ) {
719 if ( isNaN(year) || isNaN(month) || isNaN(date) ) {
720 return Number.NaN;
722 year = ToInteger(year);
723 month = ToInteger(month);
724 date = ToInteger(date );
726 var sign = ( year < 1970 ) ? -1 : 1;
727 var t = ( year < 1970 ) ? 1 : 0;
728 var y = ( year < 1970 ) ? 1969 : 1970;
730 var result5 = year + Math.floor( month/12 );
731 var result6 = month % 12;
733 if ( year < 1970 ) {
734 for ( y = 1969; y >= year; y += sign ) {
735 t += sign * TimeInYear(y);
737 } else {
738 for ( y = 1970 ; y < year; y += sign ) {
739 t += sign * TimeInYear(y);
743 var leap = InLeapYear( t );
745 for ( var m = 0; m < month; m++ ) {
746 t += TimeInMonth( m, leap );
749 if ( YearFromTime(t) != result5 ) {
750 return Number.NaN;
752 if ( MonthFromTime(t) != result6 ) {
753 return Number.NaN;
755 if ( DateFromTime(t) != 1 ) {
756 return Number.NaN;
759 return ( (Day(t)) + date - 1 );
761 function TimeInMonth( month, leap ) {
762 // september april june november
763 // jan 0 feb 1 mar 2 apr 3 may 4 june 5 jul 6
764 // aug 7 sep 8 oct 9 nov 10 dec 11
766 if ( month == 3 || month == 5 || month == 8 || month == 10 ) {
767 return ( 30*msPerDay );
770 // all the rest
771 if ( month == 0 || month == 2 || month == 4 || month == 6 ||
772 month == 7 || month == 9 || month == 11 ) {
773 return ( 31*msPerDay );
776 // save february
777 return ( (leap == 0) ? 28*msPerDay : 29*msPerDay );
779 function MakeDate( day, time ) {
780 if ( day == Number.POSITIVE_INFINITY ||
781 day == Number.NEGATIVE_INFINITY ||
782 day == Number.NaN ) {
783 return Number.NaN;
785 if ( time == Number.POSITIVE_INFINITY ||
786 time == Number.POSITIVE_INFINITY ||
787 day == Number.NaN) {
788 return Number.NaN;
790 return ( day * msPerDay ) + time;
794 // Compare 2 dates, they are considered equal if the difference is less than 1 second
795 function compareDate(d1, d2) {
796 //Dates may be off by a second
797 if (d1 == d2) {
798 return true;
799 } else if (Math.abs(new Date(d1) - new Date(d2)) <= 1000) {
800 return true;
801 } else {
802 return false;
806 function TimeClip( t ) {
807 if ( isNaN( t ) ) {
808 return ( Number.NaN );
810 if ( Math.abs( t ) > 8.64e15 ) {
811 return ( Number.NaN );
814 return ( ToInteger( t ) );
816 function ToInteger( t ) {
817 t = Number( t );
819 if ( isNaN( t ) ){
820 return ( Number.NaN );
822 if ( t == 0 || t == -0 ||
823 t == Number.POSITIVE_INFINITY || t == Number.NEGATIVE_INFINITY ) {
824 return 0;
827 var sign = ( t < 0 ) ? -1 : 1;
829 return ( sign * Math.floor( Math.abs( t ) ) );
831 function Enumerate ( o ) {
832 var p;
833 for ( p in o ) {
834 _print( p +": " + o[p] );
840 function START(summary)
842 // print out bugnumber
844 /*if ( BUGNUMBER ) {
845 writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
847 XML.setSettings (null);
848 testcases = new Array();
850 // text field for results
851 tc = 0;
852 /*this.addChild ( tf );
853 tf.x = 30;
854 tf.y = 50;
855 tf.width = 200;
856 tf.height = 400;*/
858 _print(summary);
859 var summaryParts = summary.split(" ");
860 _print("section: " + summaryParts[0] + "!");
861 //fileName = summaryParts[0];
865 function BUG(bug)
867 printBugNumber(bug);
870 function reportFailure (section, msg)
872 print(FAILED + inSection(section)+"\n"+msg);
873 /*var lines = msg.split ("\n");
874 for (var i=0; i<lines.length; i++)
875 print(FAILED + lines[i]);
879 function TEST(section, expected, actual)
881 AddTestCase(section, expected, actual);
884 function myGetNamespace (obj, ns) {
885 if (ns != undefined) {
886 return obj.namespace(ns);
887 } else {
888 return obj.namespace();
892 function TEST_XML(section, expected, actual)
894 var actual_t = typeof actual;
895 var expected_t = typeof expected;
897 if (actual_t != "xml") {
898 // force error on type mismatch
899 TEST(section, new XML(), actual);
900 return;
903 if (expected_t == "string") {
905 TEST(section, expected, actual.toXMLString());
906 } else if (expected_t == "number") {
908 TEST(section, String(expected), actual.toXMLString());
909 } else {
910 reportFailure ("Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string");
914 function SHOULD_THROW(section)
916 reportFailure(section, "Expected to generate exception, actual behavior: no exception was thrown");
919 function END()
921 test();
924 function NL()
926 //return java.lang.System.getProperty("line.separator");
927 return "\n";
930 function printBugNumber (num)
932 //writeLineToLog (BUGNUMBER + num);
935 function toPrinted(value)
937 if (typeof value == "xml") {
938 return value.toXMLString();
939 } else {
940 return String(value);
944 function grabError(err, str) {
945 var typeIndex = str.indexOf("Error:");
946 var type = str.substr(0, typeIndex + 5);
947 if (type == "TypeError") {
948 AddTestCase("Asserting for TypeError", true, (err is TypeError));
949 } else if (type == "ArgumentError") {
950 AddTestCase("Asserting for ArgumentError", true, (err is ArgumentError));
952 var numIndex = str.indexOf("Error #");
953 var num;
954 if (numIndex >= 0) {
955 num = str.substr(numIndex, 11);
956 } else {
957 num = str;
959 return num;
962 function AddErrorTest(desc:String, expectedErr:String, testFunc:Function) {
963 actualErr = null;
964 try {
965 testFunc();
966 } catch (e) {
967 actualErr = e;
969 grabError(actualErr, expectedErr);
970 AddTestCase(desc, expectedErr, actualErr.toString().substr(0, expectedErr.length));
973 var cnNoObject = 'Unexpected Error!!! Parameter to this function must be an object';
974 var cnNoClass = 'Unexpected Error!!! Cannot find Class property';
975 var cnObjectToString = Object.prototype.toString;
977 // checks that it's safe to call findType()
978 function getJSType(obj)
980 if (isObject(obj))
981 return findType(obj);
982 return cnNoObject;
986 // checks that it's safe to call findType()
987 function getJSClass(obj)
989 if (isObject(obj))
990 return findClass(findType(obj));
991 return cnNoObject;
993 function isObject(obj)
995 return obj instanceof Object;
998 function findType(obj)
1000 return cnObjectToString.apply(obj);
1002 // given '[object Number]', return 'Number'
1003 function findClass(sType)
1005 var re = /^\[.*\s+(\w+)\s*\]$/;
1006 var a = sType.match(re);
1008 if (a && a[1])
1009 return a[1];
1010 return cnNoClass;
1012 function inSection(x) {
1013 return "Section "+x+" of test -";
1015 function printStatus (msg)
1017 var lines = msg.split ("\n");
1018 var l;
1020 for (var i=0; i<lines.length; i++)
1021 _print(STATUS + lines[i]);
1024 function reportCompare (expected, actual, description)
1026 AddTestCase(description, expected, actual);
1028 var expected_t = typeof expected;
1029 var actual_t = typeof actual;
1030 var output = "";
1031 if ((VERBOSE) && (typeof description != "undefined"))
1032 printStatus ("Comparing '" + description + "'");
1034 if (expected_t != actual_t)
1035 output += "Type mismatch, expected type " + expected_t +
1036 ", actual type " + actual_t + "\n";
1037 else if (VERBOSE)
1038 printStatus ("Expected type '" + actual_t + "' matched actual " +
1039 "type '" + expected_t + "'");
1041 if (expected != actual)
1042 output += "Expected value '" + expected + "', Actual value '" + actual +
1043 "'\n";
1044 else if (VERBOSE)
1045 printStatus ("Expected value '" + actual + "' matched actual " +
1046 "value '" + expected + "'");
1048 if (output != "")
1050 if (typeof description != "undefined")
1051 reportFailure (description);
1052 reportFailure (output);
1054 stopTest();
1057 // encapsulate output in shell
1058 function _print(s) {
1059 trace(s);
1060 // trace(s);
1063 // workaround for Debugger vm where error contains more details
1064 function parseError(error,len) {
1065 if (error.length>len) {
1066 error=error.substring(0,len);
1068 return error;
1071 // helper function for api versioning tests
1072 function versionTest(testFunc, desc, expected) {
1073 var result;
1074 try {
1075 result = testFunc();
1076 } catch (e) {
1077 // Get the error type and code, but not desc if its a debug build
1078 result = e.toString().substring(0,e.toString().indexOf(':')+13);
1080 AddTestCase(desc, expected, result);
1083 // Helper functions for tests from spidermonkey (JS1_5 and greater)
1085 Calculate the "order" of a set of data points {X: [], Y: []}
1086 by computing successive "derivatives" of the data until
1087 the data is exhausted or the derivative is linear.
1089 function BigO(data) {
1090 var order = 0;
1091 var origLength = data.X.length;
1093 while (data.X.length > 2) {
1094 var lr = new LinearRegression(data);
1095 if (lr.b > 1e-6) {
1096 // only increase the order if the slope
1097 // is "great" enough
1098 order++;
1101 if (lr.r > 0.98 || lr.Syx < 1 || lr.b < 1e-6) {
1102 // terminate if close to a line lr.r
1103 // small error lr.Syx
1104 // small slope lr.b
1105 break;
1107 data = dataDeriv(data);
1110 if (2 == origLength - order) {
1111 order = Number.POSITIVE_INFINITY;
1113 return order;
1115 function LinearRegression(data) {
1117 y = a + bx
1118 for data points (Xi, Yi); 0 <= i < n
1120 b = (n*SUM(XiYi) - SUM(Xi)*SUM(Yi))/(n*SUM(Xi*Xi) - SUM(Xi)*SUM(Xi))
1121 a = (SUM(Yi) - b*SUM(Xi))/n
1123 var i;
1125 if (data.X.length != data.Y.length) {
1126 throw 'LinearRegression: data point length mismatch';
1128 if (data.X.length < 3) {
1129 throw 'LinearRegression: data point length < 2';
1131 var n = data.X.length;
1132 var X = data.X;
1133 var Y = data.Y;
1135 this.Xavg = 0;
1136 this.Yavg = 0;
1138 var SUM_X = 0;
1139 var SUM_XY = 0;
1140 var SUM_XX = 0;
1141 var SUM_Y = 0;
1142 var SUM_YY = 0;
1144 for (i = 0; i < n; i++) {
1145 SUM_X += X[i];
1146 SUM_XY += X[i] * Y[i];
1147 SUM_XX += X[i] * X[i];
1148 SUM_Y += Y[i];
1149 SUM_YY += Y[i] * Y[i];
1152 this.b = (n * SUM_XY - SUM_X * SUM_Y) / (n * SUM_XX - SUM_X * SUM_X);
1153 this.a = (SUM_Y - this.b * SUM_X) / n;
1155 this.Xavg = SUM_X / n;
1156 this.Yavg = SUM_Y / n;
1158 var SUM_Ydiff2 = 0;
1159 var SUM_Xdiff2 = 0;
1160 var SUM_XdiffYdiff = 0;
1162 for (i = 0; i < n; i++) {
1163 var Ydiff = Y[i] - this.Yavg;
1164 var Xdiff = X[i] - this.Xavg;
1166 SUM_Ydiff2 += Ydiff * Ydiff;
1167 SUM_Xdiff2 += Xdiff * Xdiff;
1168 SUM_XdiffYdiff += Xdiff * Ydiff;
1171 var Syx2 = (SUM_Ydiff2 - Math.pow(SUM_XdiffYdiff / SUM_Xdiff2, 2)) / (n - 2);
1172 var r2 = Math.pow((n * SUM_XY - SUM_X * SUM_Y), 2) / ((n * SUM_XX - SUM_X * SUM_X) * (n * SUM_YY - SUM_Y * SUM_Y));
1174 this.Syx = Math.sqrt(Syx2);
1175 this.r = Math.sqrt(r2);
1179 function dataDeriv(data) {
1180 if (data.X.length != data.Y.length) {
1181 throw 'length mismatch';
1183 var length = data.X.length;
1185 if (length < 2) {
1186 throw 'length ' + length + ' must be >= 2';
1188 var X = data.X;
1189 var Y = data.Y;
1191 var deriv = {
1192 X: [],
1193 Y: []
1196 for (var i = 0; i < length - 1; i++) {
1197 deriv.X[i] = (X[i] + X[i + 1]) / 2;
1198 deriv.Y[i] = (Y[i + 1] - Y[i]) / (X[i + 1] - X[i]);
1200 return deriv;
1203 return 0;
1207 * Date: 07 February 2001
1209 * Functionality common to Array testing -
1211 //-----------------------------------------------------------------------------
1213 var gTestsubsuite = 'Expressions';
1215 var CHAR_LBRACKET = '[';
1216 var CHAR_RBRACKET = ']';
1217 var CHAR_QT_DBL = '"';
1218 var CHAR_QT = "'";
1219 var CHAR_NL = '\n';
1220 var CHAR_COMMA = ',';
1221 var CHAR_SPACE = ' ';
1222 var TYPE_STRING = typeof 'abc';
1226 * If available, arr.toSource() gives more detail than arr.toString()
1228 * var arr = Array(1,2,'3');
1230 * arr.toSource()
1231 * [1, 2, "3"]
1233 * arr.toString()
1234 * 1,2,3
1236 * But toSource() doesn't exist in Rhino, so use our own imitation, below -
1239 function formatArray(arr)
1243 return arr.toSource();
1245 catch(e)
1247 return toSource(arr);
1254 * Imitate SpiderMonkey's arr.toSource() method:
1256 * a) Double-quote each array element that is of string type
1257 * b) Represent |undefined| and |null| by empty strings
1258 * c) Delimit elements by a comma + single space
1259 * d) Do not add delimiter at the end UNLESS the last element is |undefined|
1260 * e) Add square brackets to the beginning and end of the string
1262 function toSource(arr)
1264 var delim = CHAR_COMMA + CHAR_SPACE;
1265 var elt = '';
1266 var ret = '';
1267 var len = arr.length;
1269 for (i=0; i<len; i++)
1271 elt = arr[i];
1273 switch(true)
1275 case (typeof elt === TYPE_STRING) :
1276 ret += doubleQuote(elt);
1277 break;
1279 case (elt === undefined || elt === null) :
1280 break; // add nothing but the delimiter, below -
1282 default:
1283 ret += elt.toString();
1286 if ((i < len-1) || (elt === undefined))
1287 ret += delim;
1290 return CHAR_LBRACKET + ret + CHAR_RBRACKET;
1294 function doubleQuote(text)
1296 return CHAR_QT_DBL + text + CHAR_QT_DBL;
1300 function singleQuote(text)
1302 return CHAR_QT + text + CHAR_QT;