source: webkit/trunk/Source/JavaScriptCore/testRegExp.cpp@ 131088

Last change on this file since 131088 was 131088, checked in by [email protected], 13 years ago

Removed ASSERT_CLASS_FITS_IN_CELL
https://bugs.webkit.org/show_bug.cgi?id=97634

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore:

Our collector now supports arbitrarily sized objects, so the ASSERT is not needed.

  • API/JSCallbackFunction.cpp:
  • API/JSCallbackObject.cpp:
  • heap/MarkedSpace.h:
  • jsc.cpp:
  • runtime/Arguments.cpp:
  • runtime/ArrayConstructor.cpp:
  • runtime/ArrayPrototype.cpp:
  • runtime/BooleanConstructor.cpp:
  • runtime/BooleanObject.cpp:
  • runtime/BooleanPrototype.cpp:
  • runtime/DateConstructor.cpp:
  • runtime/DatePrototype.cpp:
  • runtime/Error.cpp:
  • runtime/ErrorConstructor.cpp:
  • runtime/ErrorPrototype.cpp:
  • runtime/FunctionConstructor.cpp:
  • runtime/FunctionPrototype.cpp:
  • runtime/InternalFunction.cpp:
  • runtime/JSActivation.cpp:
  • runtime/JSArray.cpp:
  • runtime/JSBoundFunction.cpp:
  • runtime/JSFunction.cpp:
  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalThis.cpp:
  • runtime/JSNameScope.cpp:
  • runtime/JSNotAnObject.cpp:
  • runtime/JSONObject.cpp:
  • runtime/JSObject.cpp:
  • runtime/JSPropertyNameIterator.cpp:
  • runtime/JSScope.cpp:
  • runtime/JSWithScope.cpp:
  • runtime/JSWrapperObject.cpp:
  • runtime/MathObject.cpp:
  • runtime/NameConstructor.cpp:
  • runtime/NamePrototype.cpp:
  • runtime/NativeErrorConstructor.cpp:
  • runtime/NativeErrorPrototype.cpp:
  • runtime/NumberConstructor.cpp:
  • runtime/NumberObject.cpp:
  • runtime/NumberPrototype.cpp:
  • runtime/ObjectConstructor.cpp:
  • runtime/ObjectPrototype.cpp:
  • runtime/RegExpConstructor.cpp:
  • runtime/RegExpMatchesArray.cpp:
  • runtime/RegExpObject.cpp:
  • runtime/RegExpPrototype.cpp:
  • runtime/StringConstructor.cpp:
  • runtime/StringObject.cpp:
  • runtime/StringPrototype.cpp:
  • testRegExp.cpp: Removed the ASSERT.

Source/WebCore:

  • bindings/js/JSDOMWindowShell.cpp:

(WebCore):

  • bindings/js/JSImageConstructor.cpp:

(WebCore):

  • bindings/js/JSNodeFilterCondition.cpp:

(WebCore):

  • bindings/js/JSWorkerContextBase.cpp:

(WebCore):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateImplementation):

  • bindings/scripts/test/JS/JSFloat64Array.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestEventConstructor.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestEventTarget.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestException.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestInterface.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestNamedConstructor.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestNode.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestObj.cpp:

(WebCore):

  • bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:

(WebCore):

  • bridge/runtime_method.cpp:

(JSC):

  • Property svn:eol-style set to native
File size: 14.1 KB
Line 
1/*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include "config.h"
22#include "RegExp.h"
23
24#include <wtf/CurrentTime.h>
25#include "InitializeThreading.h"
26#include "JSGlobalObject.h"
27#include <errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <wtf/text/StringBuilder.h>
32
33#if !OS(WINDOWS)
34#include <unistd.h>
35#endif
36
37#if HAVE(SYS_TIME_H)
38#include <sys/time.h>
39#endif
40
41#if COMPILER(MSVC) && !OS(WINCE)
42#include <crtdbg.h>
43#include <mmsystem.h>
44#include <windows.h>
45#endif
46
47#if PLATFORM(QT)
48#include <QCoreApplication>
49#include <QDateTime>
50#endif
51
52const int MaxLineLength = 100 * 1024;
53
54using namespace JSC;
55using namespace WTF;
56
57struct CommandLine {
58 CommandLine()
59 : interactive(false)
60 , verbose(false)
61 {
62 }
63
64 bool interactive;
65 bool verbose;
66 Vector<String> arguments;
67 Vector<String> files;
68};
69
70class StopWatch {
71public:
72 void start();
73 void stop();
74 long getElapsedMS(); // call stop() first
75
76private:
77 double m_startTime;
78 double m_stopTime;
79};
80
81void StopWatch::start()
82{
83 m_startTime = currentTime();
84}
85
86void StopWatch::stop()
87{
88 m_stopTime = currentTime();
89}
90
91long StopWatch::getElapsedMS()
92{
93 return static_cast<long>((m_stopTime - m_startTime) * 1000);
94}
95
96struct RegExpTest {
97 RegExpTest()
98 : offset(0)
99 , result(0)
100 {
101 }
102
103 String subject;
104 int offset;
105 int result;
106 Vector<int, 32> expectVector;
107};
108
109class GlobalObject : public JSGlobalObject {
110private:
111 GlobalObject(JSGlobalData&, Structure*, const Vector<String>& arguments);
112
113public:
114 typedef JSGlobalObject Base;
115
116 static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
117 {
118 GlobalObject* globalObject = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
119 globalData.heap.addFinalizer(globalObject, destroy);
120 return globalObject;
121 }
122
123 static const ClassInfo s_info;
124
125 static const bool needsDestructor = false;
126
127 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
128 {
129 return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
130 }
131
132protected:
133 void finishCreation(JSGlobalData& globalData, const Vector<String>& arguments)
134 {
135 Base::finishCreation(globalData);
136 UNUSED_PARAM(arguments);
137 }
138};
139
140COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
141
142const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
143
144GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
145 : JSGlobalObject(globalData, structure)
146{
147 finishCreation(globalData, arguments);
148}
149
150// Use SEH for Release builds only to get rid of the crash report dialog
151// (luckily the same tests fail in Release and Debug builds so far). Need to
152// be in a separate main function because the realMain function requires object
153// unwinding.
154
155#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
156#define TRY __try {
157#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
158#else
159#define TRY
160#define EXCEPT(x)
161#endif
162
163int realMain(int argc, char** argv);
164
165int main(int argc, char** argv)
166{
167#if OS(WINDOWS)
168#if !OS(WINCE)
169 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
170 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
171 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
172 ::SetErrorMode(0);
173#endif
174
175#if defined(_DEBUG)
176 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
177 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
178 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
179 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
180 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
181 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
182#endif
183
184 timeBeginPeriod(1);
185#endif
186
187#if PLATFORM(QT)
188 QCoreApplication app(argc, argv);
189#endif
190
191 // Initialize JSC before getting JSGlobalData.
192 JSC::initializeThreading();
193
194 // We can't use destructors in the following code because it uses Windows
195 // Structured Exception Handling
196 int res = 0;
197 TRY
198 res = realMain(argc, argv);
199 EXCEPT(res = 3)
200 return res;
201}
202
203static bool testOneRegExp(JSGlobalData& globalData, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
204{
205 bool result = true;
206 Vector<int, 32> outVector;
207 outVector.resize(regExpTest->expectVector.size());
208 int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, outVector);
209
210 if (matchResult != regExpTest->result) {
211 result = false;
212 if (verbose)
213 printf("Line %d: results mismatch - expected %d got %d\n", lineNumber, regExpTest->result, matchResult);
214 } else if (matchResult != -1) {
215 if (outVector.size() != regExpTest->expectVector.size()) {
216 result = false;
217 if (verbose)
218 printf("Line %d: output vector size mismatch - expected %lu got %lu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
219 } else if (outVector.size() % 2) {
220 result = false;
221 if (verbose)
222 printf("Line %d: output vector size is odd (%lu), should be even\n", lineNumber, outVector.size());
223 } else {
224 // Check in pairs since the first value of the pair could be -1 in which case the second doesn't matter.
225 size_t pairCount = outVector.size() / 2;
226 for (size_t i = 0; i < pairCount; ++i) {
227 size_t startIndex = i*2;
228 if (outVector[startIndex] != regExpTest->expectVector[startIndex]) {
229 result = false;
230 if (verbose)
231 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
232 }
233 if ((i > 0) && (regExpTest->expectVector[startIndex] != -1) && (outVector[startIndex+1] != regExpTest->expectVector[startIndex+1])) {
234 result = false;
235 if (verbose)
236 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex+1, regExpTest->expectVector[startIndex+1], outVector[startIndex+1]);
237 }
238 }
239 }
240 }
241
242 return result;
243}
244
245static int scanString(char* buffer, int bufferLength, StringBuilder& builder, char termChar)
246{
247 bool escape = false;
248
249 for (int i = 0; i < bufferLength; ++i) {
250 UChar c = buffer[i];
251
252 if (escape) {
253 switch (c) {
254 case '0':
255 c = '\0';
256 break;
257 case 'a':
258 c = '\a';
259 break;
260 case 'b':
261 c = '\b';
262 break;
263 case 'f':
264 c = '\f';
265 break;
266 case 'n':
267 c = '\n';
268 break;
269 case 'r':
270 c = '\r';
271 break;
272 case 't':
273 c = '\t';
274 break;
275 case 'v':
276 c = '\v';
277 break;
278 case '\\':
279 c = '\\';
280 break;
281 case '?':
282 c = '\?';
283 break;
284 case 'u':
285 if ((i + 4) >= bufferLength)
286 return -1;
287 unsigned int charValue;
288 if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
289 return -1;
290 c = static_cast<UChar>(charValue);
291 i += 4;
292 break;
293 }
294
295 builder.append(c);
296 escape = false;
297 } else {
298 if (c == termChar)
299 return i;
300
301 if (c == '\\')
302 escape = true;
303 else
304 builder.append(c);
305 }
306 }
307
308 return -1;
309}
310
311static RegExp* parseRegExpLine(JSGlobalData& globalData, char* line, int lineLength)
312{
313 StringBuilder pattern;
314
315 if (line[0] != '/')
316 return 0;
317
318 int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;
319
320 if ((i >= lineLength) || (line[i] != '/'))
321 return 0;
322
323 ++i;
324
325 return RegExp::create(globalData, pattern.toString(), regExpFlags(line + i));
326}
327
328static RegExpTest* parseTestLine(char* line, int lineLength)
329{
330 StringBuilder subjectString;
331
332 if ((line[0] != ' ') || (line[1] != '"'))
333 return 0;
334
335 int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;
336
337 if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
338 return 0;
339
340 i += 3;
341
342 int offset;
343
344 if (sscanf(line + i, "%d, ", &offset) != 1)
345 return 0;
346
347 while (line[i] && line[i] != ' ')
348 ++i;
349
350 ++i;
351
352 int matchResult;
353
354 if (sscanf(line + i, "%d, ", &matchResult) != 1)
355 return 0;
356
357 while (line[i] && line[i] != ' ')
358 ++i;
359
360 ++i;
361
362 if (line[i++] != '(')
363 return 0;
364
365 int start, end;
366
367 RegExpTest* result = new RegExpTest();
368
369 result->subject = subjectString.toString();
370 result->offset = offset;
371 result->result = matchResult;
372
373 while (line[i] && line[i] != ')') {
374 if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
375 delete result;
376 return 0;
377 }
378
379 result->expectVector.append(start);
380 result->expectVector.append(end);
381
382 while (line[i] && (line[i] != ',') && (line[i] != ')'))
383 i++;
384 i++;
385 while (line[i] && (line[i] != ',') && (line[i] != ')'))
386 i++;
387
388 if (line[i] == ')')
389 break;
390 if (!line[i] || (line[i] != ',')) {
391 delete result;
392 return 0;
393 }
394 i++;
395 }
396
397 return result;
398}
399
400static bool runFromFiles(GlobalObject* globalObject, const Vector<String>& files, bool verbose)
401{
402 String script;
403 String fileName;
404 Vector<char> scriptBuffer;
405 unsigned tests = 0;
406 unsigned failures = 0;
407 char* lineBuffer = new char[MaxLineLength + 1];
408
409 JSGlobalData& globalData = globalObject->globalData();
410
411 bool success = true;
412 for (size_t i = 0; i < files.size(); i++) {
413 FILE* testCasesFile = fopen(files[i].utf8().data(), "rb");
414
415 if (!testCasesFile) {
416 printf("Unable to open test data file \"%s\"\n", files[i].utf8().data());
417 continue;
418 }
419
420 RegExp* regexp = 0;
421 size_t lineLength = 0;
422 char* linePtr = 0;
423 unsigned int lineNumber = 0;
424
425 while ((linePtr = fgets(&lineBuffer[0], MaxLineLength, testCasesFile))) {
426 lineLength = strlen(linePtr);
427 if (linePtr[lineLength - 1] == '\n') {
428 linePtr[lineLength - 1] = '\0';
429 --lineLength;
430 }
431 ++lineNumber;
432
433 if (linePtr[0] == '#')
434 continue;
435
436 if (linePtr[0] == '/') {
437 regexp = parseRegExpLine(globalData, linePtr, lineLength);
438 } else if (linePtr[0] == ' ') {
439 RegExpTest* regExpTest = parseTestLine(linePtr, lineLength);
440
441 if (regexp && regExpTest) {
442 ++tests;
443 if (!testOneRegExp(globalData, regexp, regExpTest, verbose, lineNumber)) {
444 failures++;
445 printf("Failure on line %u\n", lineNumber);
446 }
447 }
448
449 if (regExpTest)
450 delete regExpTest;
451 }
452 }
453
454 fclose(testCasesFile);
455 }
456
457 if (failures)
458 printf("%u tests run, %u failures\n", tests, failures);
459 else
460 printf("%u tests passed\n", tests);
461
462 delete[] lineBuffer;
463
464 globalData.dumpSampleData(globalObject->globalExec());
465#if ENABLE(REGEXP_TRACING)
466 globalData.dumpRegExpTrace();
467#endif
468 return success;
469}
470
471#define RUNNING_FROM_XCODE 0
472
473static NO_RETURN void printUsageStatement(bool help = false)
474{
475 fprintf(stderr, "Usage: regexp_test [options] file\n");
476 fprintf(stderr, " -h|--help Prints this help message\n");
477 fprintf(stderr, " -v|--verbose Verbose output\n");
478
479 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
480}
481
482static void parseArguments(int argc, char** argv, CommandLine& options)
483{
484 int i = 1;
485 for (; i < argc; ++i) {
486 const char* arg = argv[i];
487 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
488 printUsageStatement(true);
489 if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
490 options.verbose = true;
491 else
492 options.files.append(argv[i]);
493 }
494
495 for (; i < argc; ++i)
496 options.arguments.append(argv[i]);
497}
498
499int realMain(int argc, char** argv)
500{
501 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
502 JSLockHolder lock(globalData.get());
503
504 CommandLine options;
505 parseArguments(argc, argv, options);
506
507 GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
508 bool success = runFromFiles(globalObject, options.files, options.verbose);
509
510 return success ? 0 : 3;
511}
Note: See TracBrowser for help on using the repository browser.