Home | History | Annotate | Download | only in js1_6
      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
      2  *
      3  * ***** BEGIN LICENSE BLOCK *****
      4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
      5  *
      6  * The contents of this file are subject to the Mozilla Public License Version
      7  * 1.1 (the "License"); you may not use this file except in compliance with
      8  * the License. You may obtain a copy of the License at
      9  * http://www.mozilla.org/MPL/
     10  *
     11  * Software distributed under the License is distributed on an "AS IS" basis,
     12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     13  * for the specific language governing rights and limitations under the
     14  * License.
     15  *
     16  * The Original Code is Mozilla Communicator client code, released
     17  * March 31, 1998.
     18  *
     19  * The Initial Developer of the Original Code is
     20  * Netscape Communications Corporation.
     21  * Portions created by the Initial Developer are Copyright (C) 1998
     22  * the Initial Developer. All Rights Reserved.
     23  *
     24  * Contributor(s):
     25  *   Rob Ginda rginda (at) netscape.com
     26  *   Bob Clary bob (at) bclary.com
     27  *
     28  * Alternatively, the contents of this file may be used under the terms of
     29  * either the GNU General Public License Version 2 or later (the "GPL"), or
     30  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
     31  * in which case the provisions of the GPL or the LGPL are applicable instead
     32  * of those above. If you wish to allow use of your version of this file only
     33  * under the terms of either the GPL or the LGPL, and not to allow others to
     34  * use your version of this file under the terms of the MPL, indicate your
     35  * decision by deleting the provisions above and replace them with the notice
     36  * and other provisions required by the GPL or the LGPL. If you do not delete
     37  * the provisions above, a recipient may use your version of this file under
     38  * the terms of any one of the MPL, the GPL or the LGPL.
     39  *
     40  * ***** END LICENSE BLOCK ***** */
     41 
     42 var FAILED = "FAILED!: ";
     43 var STATUS = "STATUS: ";
     44 var BUGNUMBER = "BUGNUMBER: ";
     45 var VERBOSE = false;
     46 var SECT_PREFIX = 'Section ';
     47 var SECT_SUFFIX = ' of test -';
     48 var callStack = new Array();
     49 
     50 function writeLineToLog( string ) {
     51     print( string + "\n");
     52 }
     53 /*
     54  * The test driver searches for such a phrase in the test output.
     55  * If such phrase exists, it will set n as the expected exit code.
     56  */
     57 function expectExitCode(n)
     58 {
     59 
     60     writeLineToLog('--- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE ' + n + ' ---');
     61 
     62 }
     63 
     64 /*
     65  * Statuses current section of a test
     66  */
     67 function inSection(x)
     68 {
     69 
     70     return SECT_PREFIX + x + SECT_SUFFIX;
     71 
     72 }
     73 
     74 /*
     75  * Some tests need to know if we are in Rhino as opposed to SpiderMonkey
     76  */
     77 function inRhino()
     78 {
     79     return (typeof defineClass == "function");
     80 }
     81 
     82 /*
     83  * Report a failure in the 'accepted' manner
     84  */
     85 function reportFailure (msg)
     86 {
     87     var lines = msg.split ("\n");
     88     var l;
     89     var funcName = currentFunc();
     90     var prefix = (funcName) ? "[reported from " + funcName + "] ": "";
     91 
     92     for (var i=0; i<lines.length; i++)
     93         writeLineToLog (FAILED + prefix + lines[i]);
     94 
     95 }
     96 
     97 /*
     98  * Print a non-failure message.
     99  */
    100 function printStatus (msg)
    101 {
    102     msg = String(msg);
    103     msg = msg.toString();
    104     var lines = msg.split ("\n");
    105     var l;
    106 
    107     for (var i=0; i<lines.length; i++)
    108         writeLineToLog (STATUS + lines[i]);
    109 
    110 }
    111 
    112 /*
    113  * Print a bugnumber message.
    114  */
    115 function printBugNumber (num)
    116 {
    117 
    118     writeLineToLog (BUGNUMBER + num);
    119 
    120 }
    121 
    122 /*
    123  * Compare expected result to actual result, if they differ (in value and/or
    124  * type) report a failure.  If description is provided, include it in the
    125  * failure report.
    126  */
    127 function reportCompare (expected, actual, description)
    128 {
    129     var expected_t = typeof expected;
    130     var actual_t = typeof actual;
    131     var output = "";
    132 
    133     if ((VERBOSE) && (typeof description != "undefined"))
    134         printStatus ("Comparing '" + description + "'");
    135 
    136     if (expected_t != actual_t)
    137         output += "Type mismatch, expected type " + expected_t +
    138             ", actual type " + actual_t + "\n";
    139     else if (VERBOSE)
    140         printStatus ("Expected type '" + actual_t + "' matched actual " +
    141                      "type '" + expected_t + "'");
    142 
    143     if (expected != actual)
    144         output += "Expected value '" + expected + "', Actual value '" + actual +
    145             "'\n";
    146     else if (VERBOSE)
    147         printStatus ("Expected value '" + actual + "' matched actual " +
    148                      "value '" + expected + "'");
    149 
    150     if (output != "")
    151     {
    152         if (typeof description != "undefined")
    153             reportFailure (description);
    154         reportFailure (output);
    155     }
    156     return (output == ""); // true if passed
    157 }
    158 
    159 /*
    160  * Puts funcName at the top of the call stack.  This stack is used to show
    161  * a function-reported-from field when reporting failures.
    162  */
    163 function enterFunc (funcName)
    164 {
    165 
    166     if (!funcName.match(/\(\)$/))
    167         funcName += "()";
    168 
    169     callStack.push(funcName);
    170 
    171 }
    172 
    173 /*
    174  * Pops the top funcName off the call stack.  funcName is optional, and can be
    175  * used to check push-pop balance.
    176  */
    177 function exitFunc (funcName)
    178 {
    179     var lastFunc = callStack.pop();
    180 
    181     if (funcName)
    182     {
    183         if (!funcName.match(/\(\)$/))
    184             funcName += "()";
    185 
    186         if (lastFunc != funcName)
    187             reportFailure ("Test driver failure, expected to exit function '" +
    188                            funcName + "' but '" + lastFunc + "' came off " +
    189                            "the stack");
    190     }
    191 
    192 }
    193 
    194 /*
    195  * Peeks at the top of the call stack.
    196  */
    197 function currentFunc()
    198 {
    199 
    200     return callStack[callStack.length - 1];
    201 
    202 }
    203 
    204 /*
    205   Calculate the "order" of a set of data points {X: [], Y: []}
    206   by computing successive "derivatives" of the data until
    207   the data is exhausted or the derivative is linear.
    208 */
    209 function BigO(data)
    210 {
    211   var order = 0;
    212   var origLength = data.X.length;
    213 
    214   while (data.X.length > 2)
    215   {
    216     var lr = new LinearRegression(data);
    217     if (lr.b > 1e-6)
    218     {
    219       // only increase the order if the slope
    220       // is "great" enough
    221       order++;
    222     }
    223 
    224     if (lr.r > 0.98 || lr.Syx < 1 || lr.b < 1e-6)
    225     {
    226       // terminate if close to a line lr.r
    227       // small error lr.Syx
    228       // small slope lr.b
    229       break;
    230     }
    231     data = dataDeriv(data);
    232   }
    233 
    234   if (2 == origLength - order)
    235   {
    236     order = Number.POSITIVE_INFINITY;
    237   }
    238   return order;
    239 
    240   function LinearRegression(data)
    241     {
    242       /*
    243         y = a + bx
    244         for data points (Xi, Yi); 0 <= i < n
    245 
    246         b = (n*SUM(XiYi) - SUM(Xi)*SUM(Yi))/(n*SUM(Xi*Xi) - SUM(Xi)*SUM(Xi))
    247         a = (SUM(Yi) - b*SUM(Xi))/n
    248       */
    249       var i;
    250 
    251       if (data.X.length != data.Y.length)
    252       {
    253         throw 'LinearRegression: data point length mismatch';
    254       }
    255       if (data.X.length < 3)
    256       {
    257         throw 'LinearRegression: data point length < 2';
    258       }
    259       var n = data.X.length;
    260       var X = data.X;
    261       var Y = data.Y;
    262 
    263       this.Xavg = 0;
    264       this.Yavg = 0;
    265 
    266       var SUM_X  = 0;
    267       var SUM_XY = 0;
    268       var SUM_XX = 0;
    269       var SUM_Y  = 0;
    270       var SUM_YY = 0;
    271 
    272       for (i = 0; i < n; i++)
    273       {
    274           SUM_X  += X[i];
    275           SUM_XY += X[i]*Y[i];
    276           SUM_XX += X[i]*X[i];
    277           SUM_Y  += Y[i];
    278           SUM_YY += Y[i]*Y[i];
    279       }
    280 
    281       this.b = (n * SUM_XY - SUM_X * SUM_Y)/(n * SUM_XX - SUM_X * SUM_X);
    282       this.a = (SUM_Y - this.b * SUM_X)/n;
    283 
    284       this.Xavg = SUM_X/n;
    285       this.Yavg = SUM_Y/n;
    286 
    287       var SUM_Ydiff2 = 0;
    288       var SUM_Xdiff2 = 0;
    289       var SUM_XdiffYdiff = 0;
    290 
    291       for (i = 0; i < n; i++)
    292       {
    293         var Ydiff = Y[i] - this.Yavg;
    294         var Xdiff = X[i] - this.Xavg;
    295 
    296         SUM_Ydiff2 += Ydiff * Ydiff;
    297         SUM_Xdiff2 += Xdiff * Xdiff;
    298         SUM_XdiffYdiff += Xdiff * Ydiff;
    299       }
    300 
    301       var Syx2 = (SUM_Ydiff2 - Math.pow(SUM_XdiffYdiff/SUM_Xdiff2, 2))/(n - 2);
    302       var r2   = Math.pow((n*SUM_XY - SUM_X * SUM_Y), 2) /
    303         ((n*SUM_XX - SUM_X*SUM_X)*(n*SUM_YY-SUM_Y*SUM_Y));
    304 
    305       this.Syx = Math.sqrt(Syx2);
    306       this.r = Math.sqrt(r2);
    307 
    308     }
    309 
    310   function dataDeriv(data)
    311     {
    312       if (data.X.length != data.Y.length)
    313       {
    314         throw 'length mismatch';
    315       }
    316       var length = data.X.length;
    317 
    318       if (length < 2)
    319       {
    320         throw 'length ' + length + ' must be >= 2';
    321       }
    322       var X = data.X;
    323       var Y = data.Y;
    324 
    325       var deriv = {X: [], Y: [] };
    326 
    327       for (var i = 0; i < length - 1; i++)
    328       {
    329         deriv.X[i] = (X[i] + X[i+1])/2;
    330         deriv.Y[i] = (Y[i+1] - Y[i])/(X[i+1] - X[i]);
    331       }
    332       return deriv;
    333     }
    334 
    335 }
    336 
    337 /* JavaScriptOptions
    338    encapsulate the logic for setting and retrieving the values
    339    of the javascript options.
    340 
    341    Note: in shell, options() takes an optional comma delimited list
    342    of option names, toggles the values for each option and returns the
    343    list of option names which were set before the call.
    344    If no argument is passed to options(), it returns the current
    345    options with value true.
    346 
    347    Usage;
    348 
    349    // create and initialize object.
    350    jsOptions = new JavaScriptOptions();
    351 
    352    // set a particular option
    353    jsOptions.setOption(name, boolean);
    354 
    355    // reset all options to their original values.
    356    jsOptions.reset();
    357 */
    358 
    359 function JavaScriptOptions()
    360 {
    361   this.orig   = {};
    362   this.orig.strict = this.strict = false;
    363   this.orig.werror = this.werror = false;
    364 
    365   this.privileges = 'UniversalXPConnect';
    366 
    367   if (typeof options == 'function')
    368   {
    369     // shell
    370     var optString = options();
    371     if (optString)
    372     {
    373       var optList = optString.split(',');
    374       for (iOpt = 0; i < optList.length; iOpt++)
    375       {
    376         optName = optList[iOpt];
    377         this[optName] = true;
    378       }
    379     }
    380   }
    381   else if (typeof document != 'undefined')
    382   {
    383     // browser
    384     netscape.security.PrivilegeManager.enablePrivilege(this.privileges);
    385 
    386     var preferences = Components.classes['@mozilla.org/preferences;1'];
    387     if (!preferences)
    388     {
    389       throw 'JavaScriptOptions: unable to get @mozilla.org/preference;1';
    390     }
    391 
    392     var prefService = preferences.
    393       getService(Components.interfaces.nsIPrefService);
    394 
    395     if (!prefService)
    396     {
    397       throw 'JavaScriptOptions: unable to get nsIPrefService';
    398     }
    399 
    400     var pref = prefService.getBranch('');
    401 
    402     if (!pref)
    403     {
    404       throw 'JavaScriptOptions: unable to get prefService branch';
    405     }
    406 
    407     try
    408     {
    409         this.orig.strict = this.strict =
    410             pref.getBoolPref('javascript.options.strict');
    411     }
    412     catch(e)
    413     {
    414     }
    415 
    416     try
    417     {
    418         this.orig.werror = this.werror =
    419             pref.getBoolPref('javascript.options.werror');
    420     }
    421     catch(e)
    422     {
    423     }
    424   }
    425 }
    426 
    427 JavaScriptOptions.prototype.setOption =
    428 function (optionName, optionValue)
    429 {
    430   if (typeof options == 'function')
    431   {
    432     // shell
    433     if (this[optionName] != optionValue)
    434     {
    435       options(optionName);
    436     }
    437   }
    438   else if (typeof document != 'undefined')
    439   {
    440     // browser
    441     netscape.security.PrivilegeManager.enablePrivilege(this.privileges);
    442 
    443     var preferences = Components.classes['@mozilla.org/preferences;1'];
    444     if (!preferences)
    445     {
    446       throw 'setOption: unable to get @mozilla.org/preference;1';
    447     }
    448 
    449     var prefService = preferences.
    450     getService(Components.interfaces.nsIPrefService);
    451 
    452     if (!prefService)
    453     {
    454       throw 'setOption: unable to get nsIPrefService';
    455     }
    456 
    457     var pref = prefService.getBranch('');
    458 
    459     if (!pref)
    460     {
    461       throw 'setOption: unable to get prefService branch';
    462     }
    463 
    464     pref.setBoolPref('javascript.options.' + optionName, optionValue);
    465   }
    466 
    467   this[optionName] = optionValue;
    468 
    469   return;
    470 }
    471 
    472 
    473 JavaScriptOptions.prototype.reset = function ()
    474 {
    475   this.setOption('strict', this.orig.strict);
    476   this.setOption('werror', this.orig.werror);
    477 }
    478