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