2007-05-19 20:05:05 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
|
|
* March 31, 1998.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Rob Ginda rginda@netscape.com
|
|
|
|
* Bob Clary bob@bclary.com
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2007-07-12 17:49:30 +00:00
|
|
|
// Spidermonkey shell now defaults to 1.8, so set the basic version to
|
|
|
|
// 1.5 for backwards compatibility.
|
|
|
|
|
|
|
|
if (typeof version != 'undefined')
|
|
|
|
{
|
|
|
|
version(150);
|
|
|
|
}
|
|
|
|
|
2007-05-19 20:05:05 +00:00
|
|
|
var STATUS = "STATUS: ";
|
|
|
|
var VERBOSE = false;
|
|
|
|
var SECT_PREFIX = 'Section ';
|
2007-05-26 00:19:18 +00:00
|
|
|
var SECT_SUFFIX = ' of test - ';
|
2007-05-19 20:05:05 +00:00
|
|
|
var callStack = new Array();
|
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
var gTestfile;
|
|
|
|
var gTestPath;
|
2008-04-10 20:35:58 +00:00
|
|
|
var gTestsuite;
|
|
|
|
var gTestsubsuite;
|
2007-05-26 00:19:18 +00:00
|
|
|
var gDelayTestDriverEnd = false;
|
|
|
|
|
|
|
|
var gTestcases = new Array();
|
|
|
|
var gTc = gTestcases.length;
|
|
|
|
var BUGNUMBER = '';
|
|
|
|
var summary = '';
|
|
|
|
var description = '';
|
|
|
|
var expected = '';
|
|
|
|
var actual = '';
|
|
|
|
var msg = '';
|
|
|
|
|
|
|
|
var SECTION = "";
|
|
|
|
var VERSION = "";
|
|
|
|
var BUGNUMBER = "";
|
|
|
|
|
2007-05-19 20:05:05 +00:00
|
|
|
/*
|
2007-05-26 00:19:18 +00:00
|
|
|
* constant strings
|
2007-05-19 20:05:05 +00:00
|
|
|
*/
|
2008-09-21 19:25:11 +00:00
|
|
|
var GLOBAL = this + '';
|
2008-04-25 17:52:13 +00:00
|
|
|
var PASSED = " PASSED! ";
|
|
|
|
var FAILED = " FAILED! ";
|
2007-05-26 00:19:18 +00:00
|
|
|
|
|
|
|
var DEBUG = false;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
var DESCRIPTION;
|
|
|
|
var EXPECTED;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
/*
|
|
|
|
* wrapper for test case constructor that doesn't require the SECTION
|
|
|
|
* argument.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function AddTestCase( description, expect, actual ) {
|
|
|
|
new TestCase( SECTION, description, expect, actual );
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-05-26 00:19:18 +00:00
|
|
|
* Set up test environment.
|
|
|
|
*
|
2007-05-19 20:05:05 +00:00
|
|
|
*/
|
2007-05-26 00:19:18 +00:00
|
|
|
function startTest() {
|
|
|
|
// print out bugnumber
|
|
|
|
|
|
|
|
if ( BUGNUMBER ) {
|
|
|
|
print ("BUGNUMBER: " + BUGNUMBER );
|
|
|
|
}
|
|
|
|
if ( typeof version != 'function') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// JavaScript 1.3 is supposed to be compliant ecma version 1.0
|
|
|
|
if ( VERSION == "ECMA_1" ) {
|
|
|
|
version ( "130" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.8" || gTestsuite == 'js1_8') {
|
|
|
|
version ( "180" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.7" || gTestsuite == 'js1_7') {
|
|
|
|
version ( "170" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.6" || gTestsuite == 'js1_6') {
|
|
|
|
version ( "160" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.5" || gTestsuite == 'js1_5') {
|
|
|
|
version ( "150" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.4" || gTestsuite == 'js1_4') {
|
|
|
|
version ( "140" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.3" || gTestsuite == 'js1_3') {
|
|
|
|
version ( "130" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.2" || gTestsuite == 'js1_2') {
|
|
|
|
version ( "120" );
|
|
|
|
}
|
|
|
|
else if ( VERSION == "JS_1.1" || gTestsuite == 'js1_1') {
|
|
|
|
version ( "110" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function TestCase(n, d, e, a)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
this.path = (typeof gTestPath == 'undefined') ?
|
|
|
|
(gTestsuite + '/' + gTestsubsuite + '/' + gTestfile) :
|
|
|
|
gTestPath;
|
|
|
|
this.file = gTestfile;
|
|
|
|
this.name = n;
|
|
|
|
this.description = d;
|
|
|
|
this.expect = e;
|
|
|
|
this.actual = a;
|
|
|
|
this.passed = getTestCaseResult(e, a);
|
|
|
|
this.reason = '';
|
|
|
|
this.bugnumber = typeof(BUGNUMER) != 'undefined' ? BUGNUMBER : '';
|
|
|
|
this.type = (typeof window == 'undefined' ? 'shell' : 'browser');
|
|
|
|
gTestcases[gTc++] = this;
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
TestCase.prototype.dump = function () {
|
2007-07-12 17:49:30 +00:00
|
|
|
dump('\njstest: ' + this.path + ' ' +
|
2007-05-26 00:19:18 +00:00
|
|
|
'bug: ' + this.bugnumber + ' ' +
|
|
|
|
'result: ' + (this.passed ? 'PASSED':'FAILED') + ' ' +
|
|
|
|
'type: ' + this.type + ' ' +
|
|
|
|
'description: ' + toPrinted(this.description) + ' ' +
|
2008-06-25 22:14:01 +00:00
|
|
|
// 'expected: ' + toPrinted(this.expect) + ' ' +
|
|
|
|
// 'actual: ' + toPrinted(this.actual) + ' ' +
|
2007-05-26 00:19:18 +00:00
|
|
|
'reason: ' + toPrinted(this.reason) + '\n');
|
|
|
|
};
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
/*
|
|
|
|
* The test driver searches for such a phrase in the test output.
|
|
|
|
* If such phrase exists, it will set n as the expected exit code.
|
|
|
|
*/
|
|
|
|
function expectExitCode(n)
|
|
|
|
{
|
|
|
|
print('--- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE ' + n + ' ---');
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-05-26 00:19:18 +00:00
|
|
|
* Statuses current section of a test
|
2007-05-19 20:05:05 +00:00
|
|
|
*/
|
2007-05-26 00:19:18 +00:00
|
|
|
function inSection(x)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
return SECT_PREFIX + x + SECT_SUFFIX;
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report a failure in the 'accepted' manner
|
|
|
|
*/
|
|
|
|
function reportFailure (msg)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var lines = msg.split ("\n");
|
|
|
|
var l;
|
|
|
|
var funcName = currentFunc();
|
|
|
|
var prefix = (funcName) ? "[reported from " + funcName + "] ": "";
|
|
|
|
|
|
|
|
for (var i=0; i<lines.length; i++)
|
|
|
|
print (FAILED + prefix + lines[i]);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print a non-failure message.
|
|
|
|
*/
|
|
|
|
function printStatus (msg)
|
|
|
|
{
|
|
|
|
/* js1_6 had...
|
2007-05-26 00:19:18 +00:00
|
|
|
msg = String(msg);
|
|
|
|
msg = msg.toString();
|
2007-05-19 20:05:05 +00:00
|
|
|
*/
|
2007-05-26 00:19:18 +00:00
|
|
|
msg = msg.toString();
|
|
|
|
var lines = msg.split ("\n");
|
|
|
|
var l;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
for (var i=0; i<lines.length; i++)
|
|
|
|
print (STATUS + lines[i]);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print a bugnumber message.
|
|
|
|
*/
|
|
|
|
function printBugNumber (num)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
BUGNUMBER = num;
|
|
|
|
print ('BUGNUMBER: ' + num);
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
function toPrinted(value)
|
|
|
|
{
|
|
|
|
if (typeof value == "xml")
|
|
|
|
{
|
|
|
|
value = value.toXMLString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value = String(value);
|
|
|
|
}
|
2008-07-02 11:00:03 +00:00
|
|
|
value = value.replace(/\\n/g, 'NL')
|
|
|
|
.replace(/\n/g, 'NL')
|
|
|
|
.replace(/\\r/g, 'CR')
|
|
|
|
.replace(/[^\x20-\x7E]+/g, escapeString);
|
2007-05-26 00:19:18 +00:00
|
|
|
return value;
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
2008-07-02 11:00:03 +00:00
|
|
|
function escapeString (str)
|
|
|
|
{
|
|
|
|
var a, b, c, d;
|
|
|
|
var len = str.length;
|
|
|
|
var result = "";
|
|
|
|
var digits = ["0", "1", "2", "3", "4", "5", "6", "7",
|
|
|
|
"8", "9", "A", "B", "C", "D", "E", "F"];
|
|
|
|
|
|
|
|
for (var i=0; i<len; i++)
|
|
|
|
{
|
|
|
|
var ch = str.charCodeAt(i);
|
|
|
|
|
|
|
|
a = digits[ch & 0xf];
|
|
|
|
ch >>= 4;
|
|
|
|
b = digits[ch & 0xf];
|
|
|
|
ch >>= 4;
|
|
|
|
|
|
|
|
if (ch)
|
|
|
|
{
|
|
|
|
c = digits[ch & 0xf];
|
|
|
|
ch >>= 4;
|
|
|
|
d = digits[ch & 0xf];
|
|
|
|
|
|
|
|
result += "\\u" + d + c + b + a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result += "\\x" + b + a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
JavaScript Tests - bug 452598, bug 458838, bug 469347, bug 473117, bug 473271, bug 479198, bug 482349, bug 482594, bug 482783, bug 483103, bug 483103, bug 483723, bug 483962, bug 484104, bug 484151, bug 484332, bug 484334, bug 484495, bug 484599, bug 484693, bug 484751, bug 485790, bug 485889, bug 486578, bug 487134, bug 487845, bug 487845, bug 491965, bug 491989, bug 492124, bug 492599, bug 493255 by Andreas Gal, Jeff Walden, David Mandelin, Jacob Bramley, Graydon Hoare, Jason Orendorff, Brendan Eich, Ben Turner, Vladimir Vukicevic, Blake Kaplan.
2009-06-01 23:40:42 +00:00
|
|
|
/*
|
|
|
|
* assertEq(actual, expected)
|
|
|
|
* Throw if the two arguments are not ===
|
|
|
|
* see https://bugzilla.mozilla.org/show_bug.cgi?id=480199
|
|
|
|
*/
|
|
|
|
if (typeof assertEq == 'undefined')
|
|
|
|
{
|
|
|
|
var assertEq =
|
|
|
|
function (actual, expected)
|
|
|
|
{
|
|
|
|
if (actual !== expected)
|
|
|
|
{
|
|
|
|
throw new TypeError('Assertion failed: got "' + actual + '", expected "' + expected);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2007-05-19 20:05:05 +00:00
|
|
|
/*
|
|
|
|
* Compare expected result to actual result, if they differ (in value and/or
|
2007-05-26 00:19:18 +00:00
|
|
|
* type) report a failure. If description is provided, include it in the
|
2007-05-19 20:05:05 +00:00
|
|
|
* failure report.
|
|
|
|
*/
|
2007-06-05 18:31:53 +00:00
|
|
|
function reportCompare (expected, actual, description) {
|
2007-05-26 00:19:18 +00:00
|
|
|
var expected_t = typeof expected;
|
|
|
|
var actual_t = typeof actual;
|
|
|
|
var output = "";
|
2008-07-02 11:00:03 +00:00
|
|
|
|
|
|
|
if (typeof description == "undefined")
|
|
|
|
{
|
|
|
|
description = '';
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
printStatus ("Comparing '" + description + "'");
|
2008-07-02 11:00:03 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
|
|
|
|
if (expected_t != actual_t)
|
|
|
|
{
|
|
|
|
output += "Type mismatch, expected type " + expected_t +
|
|
|
|
", actual type " + actual_t + " ";
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
2007-06-05 18:31:53 +00:00
|
|
|
printStatus ("Expected type '" + expected_t + "' matched actual " +
|
|
|
|
"type '" + actual_t + "'");
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (expected != actual)
|
|
|
|
{
|
|
|
|
output += "Expected value '" + toPrinted(expected) +
|
|
|
|
"', Actual value '" + toPrinted(actual) + "' ";
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
2007-06-05 18:31:53 +00:00
|
|
|
printStatus ("Expected value '" + toPrinted(expected) +
|
|
|
|
"' matched actual value '" + toPrinted(actual) + "'");
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var testcase = new TestCase(gTestfile, description, expected, actual);
|
|
|
|
testcase.reason = output;
|
2008-07-02 11:00:03 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
if (testcase.passed)
|
|
|
|
{
|
2008-07-02 11:00:03 +00:00
|
|
|
print(PASSED + description);
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-07-02 11:00:03 +00:00
|
|
|
reportFailure (description + " : " + output);
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return testcase.passed;
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
2007-06-05 18:31:53 +00:00
|
|
|
/*
|
|
|
|
* Attempt to match a regular expression describing the result to
|
|
|
|
* the actual result, if they differ (in value and/or
|
|
|
|
* type) report a failure. If description is provided, include it in the
|
|
|
|
* failure report.
|
|
|
|
*/
|
|
|
|
function reportMatch (expectedRegExp, actual, description) {
|
|
|
|
var expected_t = "string";
|
|
|
|
var actual_t = typeof actual;
|
|
|
|
var output = "";
|
|
|
|
|
2008-07-02 11:00:03 +00:00
|
|
|
if (typeof description == "undefined")
|
|
|
|
{
|
|
|
|
description = '';
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
2007-06-05 18:31:53 +00:00
|
|
|
printStatus ("Comparing '" + description + "'");
|
2008-07-02 11:00:03 +00:00
|
|
|
}
|
2007-06-05 18:31:53 +00:00
|
|
|
|
|
|
|
if (expected_t != actual_t)
|
|
|
|
{
|
|
|
|
output += "Type mismatch, expected type " + expected_t +
|
|
|
|
", actual type " + actual_t + " ";
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
|
|
|
printStatus ("Expected type '" + expected_t + "' matched actual " +
|
|
|
|
"type '" + actual_t + "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var matches = expectedRegExp.test(actual);
|
|
|
|
if (!matches)
|
|
|
|
{
|
|
|
|
output += "Expected match to '" + toPrinted(expectedRegExp) +
|
|
|
|
"', Actual value '" + toPrinted(actual) + "' ";
|
|
|
|
}
|
|
|
|
else if (VERBOSE)
|
|
|
|
{
|
|
|
|
printStatus ("Expected match to '" + toPrinted(expectedRegExp) +
|
|
|
|
"' matched actual value '" + toPrinted(actual) + "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var testcase = new TestCase(gTestfile, description, true, matches);
|
|
|
|
testcase.reason = output;
|
|
|
|
|
|
|
|
if (testcase.passed)
|
|
|
|
{
|
2008-07-02 11:00:03 +00:00
|
|
|
print(PASSED + description);
|
2007-06-05 18:31:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-07-02 11:00:03 +00:00
|
|
|
reportFailure (description + " : " + output);
|
2007-06-05 18:31:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return testcase.passed;
|
|
|
|
}
|
|
|
|
|
2007-05-19 20:05:05 +00:00
|
|
|
/*
|
|
|
|
* Puts funcName at the top of the call stack. This stack is used to show
|
|
|
|
* a function-reported-from field when reporting failures.
|
|
|
|
*/
|
|
|
|
function enterFunc (funcName)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
if (!funcName.match(/\(\)$/))
|
|
|
|
funcName += "()";
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
callStack.push(funcName);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pops the top funcName off the call stack. funcName is optional, and can be
|
|
|
|
* used to check push-pop balance.
|
|
|
|
*/
|
|
|
|
function exitFunc (funcName)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var lastFunc = callStack.pop();
|
|
|
|
|
|
|
|
if (funcName)
|
|
|
|
{
|
|
|
|
if (!funcName.match(/\(\)$/))
|
|
|
|
funcName += "()";
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
if (lastFunc != funcName)
|
|
|
|
reportCompare(funcName, lastFunc, "Test driver failure wrong exit function ");
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Peeks at the top of the call stack.
|
|
|
|
*/
|
|
|
|
function currentFunc()
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
return callStack[callStack.length - 1];
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Calculate the "order" of a set of data points {X: [], Y: []}
|
|
|
|
by computing successive "derivatives" of the data until
|
|
|
|
the data is exhausted or the derivative is linear.
|
|
|
|
*/
|
|
|
|
function BigO(data)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var order = 0;
|
|
|
|
var origLength = data.X.length;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
while (data.X.length > 2)
|
|
|
|
{
|
|
|
|
var lr = new LinearRegression(data);
|
|
|
|
if (lr.b > 1e-6)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
// only increase the order if the slope
|
|
|
|
// is "great" enough
|
|
|
|
order++;
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
|
|
|
|
if (lr.r > 0.98 || lr.Syx < 1 || lr.b < 1e-6)
|
|
|
|
{
|
|
|
|
// terminate if close to a line lr.r
|
|
|
|
// small error lr.Syx
|
|
|
|
// small slope lr.b
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
data = dataDeriv(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (2 == origLength - order)
|
|
|
|
{
|
|
|
|
order = Number.POSITIVE_INFINITY;
|
|
|
|
}
|
|
|
|
return order;
|
|
|
|
|
|
|
|
function LinearRegression(data)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
y = a + bx
|
|
|
|
for data points (Xi, Yi); 0 <= i < n
|
|
|
|
|
|
|
|
b = (n*SUM(XiYi) - SUM(Xi)*SUM(Yi))/(n*SUM(Xi*Xi) - SUM(Xi)*SUM(Xi))
|
|
|
|
a = (SUM(Yi) - b*SUM(Xi))/n
|
|
|
|
*/
|
|
|
|
var i;
|
|
|
|
|
|
|
|
if (data.X.length != data.Y.length)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
throw 'LinearRegression: data point length mismatch';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
if (data.X.length < 3)
|
|
|
|
{
|
|
|
|
throw 'LinearRegression: data point length < 2';
|
|
|
|
}
|
|
|
|
var n = data.X.length;
|
|
|
|
var X = data.X;
|
|
|
|
var Y = data.Y;
|
|
|
|
|
|
|
|
this.Xavg = 0;
|
|
|
|
this.Yavg = 0;
|
|
|
|
|
|
|
|
var SUM_X = 0;
|
|
|
|
var SUM_XY = 0;
|
|
|
|
var SUM_XX = 0;
|
|
|
|
var SUM_Y = 0;
|
|
|
|
var SUM_YY = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
SUM_X += X[i];
|
|
|
|
SUM_XY += X[i]*Y[i];
|
|
|
|
SUM_XX += X[i]*X[i];
|
|
|
|
SUM_Y += Y[i];
|
|
|
|
SUM_YY += Y[i]*Y[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
this.b = (n * SUM_XY - SUM_X * SUM_Y)/(n * SUM_XX - SUM_X * SUM_X);
|
|
|
|
this.a = (SUM_Y - this.b * SUM_X)/n;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
this.Xavg = SUM_X/n;
|
|
|
|
this.Yavg = SUM_Y/n;
|
|
|
|
|
|
|
|
var SUM_Ydiff2 = 0;
|
|
|
|
var SUM_Xdiff2 = 0;
|
|
|
|
var SUM_XdiffYdiff = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var Ydiff = Y[i] - this.Yavg;
|
|
|
|
var Xdiff = X[i] - this.Xavg;
|
|
|
|
|
|
|
|
SUM_Ydiff2 += Ydiff * Ydiff;
|
|
|
|
SUM_Xdiff2 += Xdiff * Xdiff;
|
|
|
|
SUM_XdiffYdiff += Xdiff * Ydiff;
|
|
|
|
}
|
|
|
|
|
|
|
|
var Syx2 = (SUM_Ydiff2 - Math.pow(SUM_XdiffYdiff/SUM_Xdiff2, 2))/(n - 2);
|
|
|
|
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));
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
this.Syx = Math.sqrt(Syx2);
|
|
|
|
this.r = Math.sqrt(r2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function dataDeriv(data)
|
|
|
|
{
|
|
|
|
if (data.X.length != data.Y.length)
|
|
|
|
{
|
|
|
|
throw 'length mismatch';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
var length = data.X.length;
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
if (length < 2)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
throw 'length ' + length + ' must be >= 2';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
var X = data.X;
|
|
|
|
var Y = data.Y;
|
|
|
|
|
|
|
|
var deriv = {X: [], Y: [] };
|
|
|
|
|
|
|
|
for (var i = 0; i < length - 1; i++)
|
|
|
|
{
|
|
|
|
deriv.X[i] = (X[i] + X[i+1])/2;
|
|
|
|
deriv.Y[i] = (Y[i+1] - Y[i])/(X[i+1] - X[i]);
|
|
|
|
}
|
|
|
|
return deriv;
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2008-04-10 20:35:58 +00:00
|
|
|
return 0;
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function compareSource(expect, actual, summary)
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
// compare source
|
|
|
|
var expectP = expect.
|
|
|
|
replace(/([(){},.:\[\]])/mg, ' $1 ').
|
|
|
|
replace(/(\w+)/mg, ' $1 ').
|
|
|
|
replace(/<(\/)? (\w+) (\/)?>/mg, '<$1$2$3>').
|
|
|
|
replace(/\s+/mg, ' ').
|
|
|
|
replace(/new (\w+)\s*\(\s*\)/mg, 'new $1');
|
|
|
|
|
|
|
|
var actualP = actual.
|
|
|
|
replace(/([(){},.:\[\]])/mg, ' $1 ').
|
|
|
|
replace(/(\w+)/mg, ' $1 ').
|
|
|
|
replace(/<(\/)? (\w+) (\/)?>/mg, '<$1$2$3>').
|
|
|
|
replace(/\s+/mg, ' ').
|
|
|
|
replace(/new (\w+)\s*\(\s*\)/mg, 'new $1');
|
|
|
|
|
|
|
|
print('expect:\n' + expectP);
|
|
|
|
print('actual:\n' + actualP);
|
|
|
|
|
|
|
|
reportCompare(expectP, actualP, summary);
|
|
|
|
|
|
|
|
// actual must be compilable if expect is?
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var expectCompile = 'No Error';
|
|
|
|
var actualCompile;
|
|
|
|
|
|
|
|
eval(expect);
|
2007-05-19 20:05:05 +00:00
|
|
|
try
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
eval(actual);
|
|
|
|
actualCompile = 'No Error';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
catch(ex1)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
actualCompile = ex1 + '';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
reportCompare(expectCompile, actualCompile,
|
2007-06-05 18:31:53 +00:00
|
|
|
summary + ': compile actual');
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
catch(ex)
|
|
|
|
{
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function optionsInit() {
|
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
// record initial values to support resetting
|
|
|
|
// options to their initial values
|
|
|
|
options.initvalues = {};
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
// record values in a stack to support pushing
|
|
|
|
// and popping options
|
|
|
|
options.stackvalues = [];
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
var optionNames = options().split(',');
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
for (var i = 0; i < optionNames.length; i++)
|
|
|
|
{
|
|
|
|
var optionName = optionNames[i];
|
|
|
|
if (optionName)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
options.initvalues[optionName] = '';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function optionsClear() {
|
2007-05-26 00:19:18 +00:00
|
|
|
|
|
|
|
// turn off current settings
|
|
|
|
var optionNames = options().split(',');
|
|
|
|
for (var i = 0; i < optionNames.length; i++)
|
|
|
|
{
|
|
|
|
var optionName = optionNames[i];
|
|
|
|
if (optionName)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
options(optionName);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function optionsPush()
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var optionsframe = {};
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
options.stackvalues.push(optionsframe);
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
var optionNames = options().split(',');
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
for (var i = 0; i < optionNames.length; i++)
|
|
|
|
{
|
|
|
|
var optionName = optionNames[i];
|
|
|
|
if (optionName)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
optionsframe[optionName] = '';
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
optionsClear();
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function optionsPop()
|
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
var optionsframe = options.stackvalues.pop();
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
optionsClear();
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
for (optionName in optionsframe)
|
|
|
|
{
|
|
|
|
options(optionName);
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function optionsReset() {
|
|
|
|
|
2009-02-21 00:57:04 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
optionsClear();
|
2007-05-26 00:19:18 +00:00
|
|
|
|
2009-02-21 00:57:04 +00:00
|
|
|
// turn on initial settings
|
|
|
|
for (optionName in options.initvalues)
|
|
|
|
{
|
|
|
|
options(optionName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(ex)
|
2007-05-26 00:19:18 +00:00
|
|
|
{
|
2009-02-21 00:57:04 +00:00
|
|
|
print('optionsReset: caught ' + ex);
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
2009-02-21 00:57:04 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof options == 'function')
|
|
|
|
{
|
|
|
|
optionsInit();
|
|
|
|
optionsClear();
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTestCaseResult(expected, actual)
|
|
|
|
{
|
2008-11-27 10:29:34 +00:00
|
|
|
if (typeof expected != typeof actual)
|
|
|
|
return false;
|
|
|
|
if (typeof expected != 'number')
|
|
|
|
// Note that many tests depend on the use of '==' here, not '==='.
|
|
|
|
return actual == expected;
|
|
|
|
|
|
|
|
// Distinguish NaN from other values. Using x != x comparisons here
|
|
|
|
// works even if tests redefine isNaN.
|
|
|
|
if (actual != actual)
|
|
|
|
return expected != expected;
|
|
|
|
if (expected != expected)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Tolerate a certain degree of error.
|
|
|
|
if (actual != expected)
|
|
|
|
return Math.abs(actual - expected) <= 1E-10;
|
|
|
|
|
|
|
|
// Here would be a good place to distinguish 0 and -0, if we wanted
|
|
|
|
// to. However, doing so would introduce a number of failures in
|
|
|
|
// areas where they don't seem important. For example, the WeekDay
|
|
|
|
// function in ECMA-262 returns -0 for Sundays before the epoch, but
|
|
|
|
// the Date functions in SpiderMonkey specified in terms of WeekDay
|
|
|
|
// often don't. This seems unimportant.
|
|
|
|
return true;
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof dump == 'undefined')
|
|
|
|
{
|
|
|
|
if (typeof window == 'undefined' &&
|
|
|
|
typeof print == 'function')
|
|
|
|
{
|
|
|
|
dump = print;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dump = (function () {});
|
|
|
|
}
|
|
|
|
}
|
2007-05-19 20:05:05 +00:00
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
function test() {
|
|
|
|
for ( gTc=0; gTc < gTestcases.length; gTc++ ) {
|
|
|
|
// temporary hack to work around some unknown issue in 1.7
|
|
|
|
try
|
|
|
|
{
|
|
|
|
gTestcases[gTc].passed = writeTestCaseResult(
|
|
|
|
gTestcases[gTc].expect,
|
|
|
|
gTestcases[gTc].actual,
|
|
|
|
gTestcases[gTc].description +" = "+ gTestcases[gTc].actual );
|
|
|
|
gTestcases[gTc].reason += ( gTestcases[gTc].passed ) ? "" : "wrong value ";
|
|
|
|
}
|
|
|
|
catch(e)
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
print('test(): empty testcase for gTc = ' + gTc + ' ' + e);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
}
|
|
|
|
stopTest();
|
|
|
|
return ( gTestcases );
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
/*
|
|
|
|
* Begin printing functions. These functions use the shell's
|
|
|
|
* print function. When running tests in the browser, these
|
|
|
|
* functions, override these functions with functions that use
|
|
|
|
* document.write.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function writeTestCaseResult( expect, actual, string ) {
|
|
|
|
var passed = getTestCaseResult( expect, actual );
|
|
|
|
writeFormattedResult( expect, actual, string, passed );
|
|
|
|
return passed;
|
|
|
|
}
|
|
|
|
function writeFormattedResult( expect, actual, string, passed ) {
|
2008-04-25 17:52:13 +00:00
|
|
|
var s = ( passed ? PASSED : FAILED ) + string + ' expected: ' + expect;
|
|
|
|
print(s);
|
2007-05-26 00:19:18 +00:00
|
|
|
return passed;
|
|
|
|
}
|
|
|
|
|
|
|
|
function writeHeaderToLog( string ) {
|
|
|
|
print( string );
|
|
|
|
}
|
|
|
|
/* end of print functions */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When running in the shell, run the garbage collector after the
|
|
|
|
* test has completed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function stopTest() {
|
|
|
|
var gc;
|
|
|
|
if ( gc != undefined ) {
|
|
|
|
gc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convenience function for displaying failed test cases. Useful
|
|
|
|
* when running tests manually.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function getFailedCases() {
|
|
|
|
for ( var i = 0; i < gTestcases.length; i++ ) {
|
|
|
|
if ( ! gTestcases[i].passed ) {
|
|
|
|
print( gTestcases[i].description + " = " +gTestcases[i].actual +
|
|
|
|
" expected: " + gTestcases[i].expect );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function jsTestDriverEnd()
|
|
|
|
{
|
|
|
|
// gDelayTestDriverEnd is used to
|
|
|
|
// delay collection of the test result and
|
|
|
|
// signal to Spider so that tests can continue
|
|
|
|
// to run after page load has fired. They are
|
|
|
|
// responsible for setting gDelayTestDriverEnd = true
|
|
|
|
// then when completed, setting gDelayTestDriverEnd = false
|
|
|
|
// then calling jsTestDriverEnd()
|
|
|
|
|
|
|
|
if (gDelayTestDriverEnd)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
optionsReset();
|
|
|
|
}
|
|
|
|
catch(ex)
|
|
|
|
{
|
|
|
|
dump('jsTestDriverEnd ' + ex);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i = 0; i < gTestcases.length; i++)
|
|
|
|
{
|
|
|
|
gTestcases[i].dump();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-09-17 10:41:19 +00:00
|
|
|
function jit(on)
|
|
|
|
{
|
|
|
|
if (on && !options().match(/jit/))
|
|
|
|
{
|
|
|
|
options('jit');
|
|
|
|
}
|
|
|
|
else if (!on && options().match(/jit/))
|
|
|
|
{
|
|
|
|
options('jit');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-26 00:19:18 +00:00
|
|
|
/*
|
|
|
|
* Some tests need to know if we are in Rhino as opposed to SpiderMonkey
|
|
|
|
*/
|
|
|
|
function inRhino()
|
2007-05-19 20:05:05 +00:00
|
|
|
{
|
2007-05-26 00:19:18 +00:00
|
|
|
return (typeof defineClass == "function");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* these functions are useful for running tests manually in Rhino */
|
|
|
|
|
|
|
|
function GetContext() {
|
|
|
|
return Packages.com.netscape.javascript.Context.getCurrentContext();
|
|
|
|
}
|
|
|
|
function OptLevel( i ) {
|
|
|
|
i = Number(i);
|
|
|
|
var cx = GetContext();
|
|
|
|
cx.setOptimizationLevel(i);
|
2007-05-19 20:05:05 +00:00
|
|
|
}
|
2007-05-26 00:19:18 +00:00
|
|
|
/* end of Rhino functions */
|
|
|
|
|
|
|
|
|