Home | History | Annotate | Download | only in RegExp
      1 /*
      2 * The contents of this file are subject to the Netscape Public
      3 * License Version 1.1 (the "License"); you may not use this file
      4 * except in compliance with the License. You may obtain a copy of
      5 * the License at http://www.mozilla.org/NPL/
      6 *
      7 * Software distributed under the License is distributed on an "AS  IS"
      8 * basis, WITHOUT WARRANTY OF ANY KIND, either expressed
      9 * or implied. See the License for the specific language governing
     10 * rights and limitations under the License.
     11 *
     12 * The Original Code is mozilla.org code.
     13 *
     14 * The Initial Developer of the Original Code is Netscape
     15 * Communications Corporation.  Portions created by Netscape are
     16 * Copyright (C) 1998 Netscape Communications Corporation.
     17 * All Rights Reserved.
     18 *
     19 * Contributor(s): pschwartau (at) netscape.com
     20 * Date: 07 February 2001
     21 *
     22 * Functionality common to RegExp testing -
     23 */
     24 //-------------------------------------------------------------------------------------------------
     25 var MSG_PATTERN = '\nregexp = ';
     26 var MSG_STRING = '\nstring = ';
     27 var MSG_EXPECT = '\nExpect: ';
     28 var MSG_ACTUAL = '\nActual: ';
     29 var ERR_LENGTH = '\nERROR !!! match arrays have different lengths:';
     30 var ERR_MATCH = '\nERROR !!! regexp failed to give expected match array:';
     31 var ERR_NO_MATCH = '\nERROR !!! regexp FAILED to match anything !!!';
     32 var ERR_UNEXP_MATCH = '\nERROR !!! regexp MATCHED when we expected it to fail !!!';
     33 var CHAR_LBRACKET = '[';
     34 var CHAR_RBRACKET = ']';
     35 var CHAR_QT_DBL = '"';
     36 var CHAR_QT = "'";
     37 var CHAR_NL = '\n';
     38 var CHAR_COMMA = ',';
     39 var CHAR_SPACE = ' ';
     40 var TYPE_STRING = typeof 'abc';
     41 
     42 
     43 
     44 function testRegExp(statuses, patterns, strings, actualmatches, expectedmatches)
     45 {
     46   var status = '';
     47   var pattern = new RegExp();
     48   var string = '';
     49   var actualmatch = new Array();
     50   var expectedmatch = new Array();
     51   var state = '';
     52   var lActual = -1;
     53   var lExpect = -1;
     54 
     55 
     56   for (var i=0; i != patterns.length; i++)
     57   {
     58     status = statuses[i];
     59     pattern = patterns[i];
     60     string = strings[i];
     61     actualmatch=actualmatches[i];
     62     expectedmatch=expectedmatches[i];
     63     state = getState(status, pattern, string);
     64 
     65 
     66     if(actualmatch)
     67     {
     68       if(expectedmatch)
     69       {
     70         // expectedmatch and actualmatch are arrays -
     71         lExpect = expectedmatch.length;
     72         lActual = actualmatch.length;
     73 
     74         if (lActual != lExpect)
     75         {
     76           reportFailure(
     77                         state + ERR_LENGTH +
     78                         MSG_EXPECT + formatArray(expectedmatch) +
     79                         MSG_ACTUAL + formatArray(actualmatch) +
     80                         CHAR_NL
     81                        );
     82           continue;
     83         }
     84 
     85         // OK, the arrays have same length -
     86         if (formatArray(expectedmatch) != formatArray(actualmatch))
     87         {
     88           reportFailure(
     89                         state + ERR_MATCH +
     90                         MSG_EXPECT + formatArray(expectedmatch) +
     91                         MSG_ACTUAL + formatArray(actualmatch) +
     92                         CHAR_NL
     93                        );
     94         }
     95 
     96       }
     97       else //expectedmatch is null - that is, we did not expect a match -
     98       {
     99         reportFailure(
    100                       state + ERR_UNEXP_MATCH +
    101                       MSG_EXPECT + expectedmatch +
    102                       MSG_ACTUAL + formatArray(actualmatch) +
    103                       CHAR_NL
    104                      );
    105       }
    106 
    107     }
    108     else // actualmatch is null
    109     {
    110       if (expectedmatch)
    111       {
    112         reportFailure(
    113                       state + ERR_NO_MATCH +
    114                       MSG_EXPECT + formatArray(expectedmatch) +
    115                       MSG_ACTUAL + actualmatch +
    116                       CHAR_NL
    117                      );
    118       }
    119       else // we did not expect a match
    120       {
    121         // Being ultra-cautious. Presumably expectedmatch===actualmatch===null
    122         reportCompare (expectedmatch, actualmatch, state);
    123       }
    124     }
    125   }
    126 }
    127 
    128 
    129 function getState(status, pattern, string)
    130 {
    131   /*
    132    * Escape \n's, etc. to make them LITERAL in the presentation string.
    133    * We don't have to worry about this in |pattern|; such escaping is
    134    * done automatically by pattern.toString(), invoked implicitly below.
    135    *
    136    * One would like to simply do: string = string.replace(/(\s)/g, '\$1').
    137    * However, the backreference $1 is not a literal string value,
    138    * so this method doesn't work.
    139    *
    140    * Also tried string = string.replace(/(\s)/g, escape('$1'));
    141    * but this just inserts the escape of the literal '$1', i.e. '%241'.
    142    */
    143   string = string.replace(/\n/g, '\\n');
    144   string = string.replace(/\r/g, '\\r');
    145   string = string.replace(/\t/g, '\\t');
    146   string = string.replace(/\v/g, '\\v');
    147   string = string.replace(/\f/g, '\\f');
    148 
    149   return (status + MSG_PATTERN + pattern + MSG_STRING + singleQuote(string));
    150 }
    151 
    152 
    153 /*
    154  * If available, arr.toSource() gives more detail than arr.toString()
    155  *
    156  * var arr = Array(1,2,'3');
    157  *
    158  * arr.toSource()
    159  * [1, 2, "3"]
    160  *
    161  * arr.toString()
    162  * 1,2,3
    163  *
    164  * But toSource() doesn't exist in Rhino, so use our own imitation, below -
    165  *
    166  */
    167 function formatArray(arr)
    168 {
    169   try
    170   {
    171     return arr.toSource();
    172   }
    173   catch(e)
    174   {
    175     return toSource(arr);
    176   }
    177 }
    178 
    179 
    180 /*
    181  * Imitate SpiderMonkey's arr.toSource() method:
    182  *
    183  * a) Double-quote each array element that is of string type
    184  * b) Represent |undefined| and |null| by empty strings
    185  * c) Delimit elements by a comma + single space
    186  * d) Do not add delimiter at the end UNLESS the last element is |undefined|
    187  * e) Add square brackets to the beginning and end of the string
    188  */
    189 function toSource(arr)
    190 {
    191   var delim = CHAR_COMMA + CHAR_SPACE;
    192   var elt = '';
    193   var ret = '';
    194   var len = arr.length;
    195 
    196   for (i=0; i<len; i++)
    197   {
    198     elt = arr[i];
    199 
    200     switch(true)
    201     {
    202       case (typeof elt === TYPE_STRING) :
    203         ret += doubleQuote(elt);
    204         break;
    205 
    206       case (elt === undefined || elt === null) :
    207         break; // add nothing but the delimiter, below -
    208 
    209       default:
    210         ret += elt.toString();
    211     }
    212 
    213     if ((i < len-1) || (elt === undefined))
    214       ret += delim;
    215   }
    216 
    217   return  CHAR_LBRACKET + ret + CHAR_RBRACKET;
    218 }
    219 
    220 
    221 function doubleQuote(text)
    222 {
    223   return CHAR_QT_DBL + text + CHAR_QT_DBL;
    224 }
    225 
    226 
    227 function singleQuote(text)
    228 {
    229   return CHAR_QT + text + CHAR_QT;
    230 }
    231