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

Last change on this file since 173062 was 173018, checked in by Brent Fulgham, 11 years ago

[Win] testapi and testRegExp need to find support libraries.
https://bugs.webkit.org/show_bug.cgi?id=136008.

Reviewed by Dean Jackson.

Revise the Windows build of jsc, testapi, and testRegExp so that they
find and use the proper runtime support libraries.

These locations vary between the Apple Windows build and WinCairo, and
are generally not in the system PATH environment setting. Consequently,
these applications fail on launch unless the user modifies their
PATH.

This patch revises these tools to work like WinLauncher and DumpRenderTree
so that they run reliably.

  • API/tests/testapi.c:

(dllLauncherEntryPoint): Added.

  • JavaScriptCore.vcxproj/JavaScriptCore.sln: Add new build projects and provide proper dependencies with existing projects.
  • JavaScriptCore.vcxproj/JavaScriptCore.submit.sln: Ditto.
  • JavaScriptCore.vcxproj/jsc/jsc.vcxproj: Switch to build a DLL, rather than an executable.
  • JavaScriptCore.vcxproj/jsc/jscCommon.props: Add shlwapi.lib to the list of libraries needed at link-time, and to use the DLL/Console combination entry point.
  • JavaScriptCore.vcxproj/jsc/jscLauncher.vcxproj: Added.
  • JavaScriptCore.vcxproj/jsc/jscLauncherPostBuild.cmd: Copied from JavaScriptCore.vcxproj/jsc/jscPostBuild.cmd.
  • JavaScriptCore.vcxproj/jsc/jscLauncherPreBuild.cmd: Copied from JavaScriptCore.vcxproj/jsc/jscPreBuild.cmd.
  • JavaScriptCore.vcxproj/jsc/jscLauncherPreLink.cmd: Copied from JavaScriptCore.vcxproj/jsc/jscPreLink.cmd.
  • JavaScriptCore.vcxproj/testRegExp/testRegExp.vcxproj: Switch to build a DLL, rather than an executable.
  • JavaScriptCore.vcxproj/testRegExp/testRegExpCommon.props: Add shlwapi.lib to the list of libraries needed at link-time, and to use the DLL/Console combination entry point.
  • JavaScriptCore.vcxproj/testRegExp/testRegExpLauncher.vcxproj: Added.
  • JavaScriptCore.vcxproj/testRegExp/testRegExpLauncherPostBuild.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPostBuild.cmd.
  • JavaScriptCore.vcxproj/testRegExp/testRegExpLauncherPreBuild.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPreBuild.cmd.
  • JavaScriptCore.vcxproj/testRegExp/testRegExpLauncherPreLink.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPreLink.cmd.
  • JavaScriptCore.vcxproj/testapi/testapi.vcxproj: Switch to build a DLL, rather than an executable.
  • JavaScriptCore.vcxproj/testapi/testapiLauncher.vcxproj: Added.
  • JavaScriptCore.vcxproj/testapi/testapiCommon.props: Add shlwapi.lib to the list of libraries needed at link-time, and to use the DLL/Console combination entry point.
  • JavaScriptCore.vcxproj/testapi/testapiLauncherPostBuild.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPostBuild.cmd.
  • JavaScriptCore.vcxproj/testapi/testapiLauncherPreBuild.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPreBuild.cmd.
  • JavaScriptCore.vcxproj/testapi/testapiLauncherPreLink.cmd: Copied from JavaScriptCore.vcxproj/testRegExp/testRegExpPreLink.cmd.
  • jsc.cpp:

(dllLauncherEntryPoint): Added.

  • testRegExp.cpp:

(dllLauncherEntryPoint): Added.

  • Property svn:eol-style set to native
File size: 13.9 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 "JSCInlines.h"
27#include "JSGlobalObject.h"
28#include <errno.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <wtf/text/StringBuilder.h>
33
34#if !OS(WINDOWS)
35#include <unistd.h>
36#endif
37
38#if HAVE(SYS_TIME_H)
39#include <sys/time.h>
40#endif
41
42#if COMPILER(MSVC) && !OS(WINCE)
43#include <crtdbg.h>
44#include <mmsystem.h>
45#include <windows.h>
46#endif
47
48namespace JSC {
49WTF_IMPORT extern const struct HashTable globalObjectTable;
50}
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 = monotonicallyIncreasingTime();
84}
85
86void StopWatch::stop()
87{
88 m_stopTime = monotonicallyIncreasingTime();
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(VM&, Structure*, const Vector<String>& arguments);
112
113public:
114 typedef JSGlobalObject Base;
115
116 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
117 {
118 GlobalObject* globalObject = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure, arguments);
119 vm.heap.addFinalizer(globalObject, destroy);
120 return globalObject;
121 }
122
123 DECLARE_INFO;
124
125 static const bool needsDestructor = false;
126
127 static Structure* createStructure(VM& vm, JSValue prototype)
128 {
129 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
130 }
131
132protected:
133 void finishCreation(VM& vm, const Vector<String>& arguments)
134 {
135 Base::finishCreation(vm);
136 UNUSED_PARAM(arguments);
137 }
138};
139
140const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, &globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
141
142GlobalObject::GlobalObject(VM& vm, Structure* structure, const Vector<String>& arguments)
143 : JSGlobalObject(vm, structure)
144{
145 finishCreation(vm, arguments);
146}
147
148// Use SEH for Release builds only to get rid of the crash report dialog
149// (luckily the same tests fail in Release and Debug builds so far). Need to
150// be in a separate main function because the realMain function requires object
151// unwinding.
152
153#if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
154#define TRY __try {
155#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
156#else
157#define TRY
158#define EXCEPT(x)
159#endif
160
161int realMain(int argc, char** argv);
162
163int main(int argc, char** argv)
164{
165#if OS(WINDOWS)
166#if !OS(WINCE)
167 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
168 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
169 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
170 ::SetErrorMode(0);
171#endif
172
173#if defined(_DEBUG)
174 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
175 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
176 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
177 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
178 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
179 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
180#endif
181
182 timeBeginPeriod(1);
183#endif
184
185 // Initialize JSC before getting VM.
186 JSC::initializeThreading();
187
188 // We can't use destructors in the following code because it uses Windows
189 // Structured Exception Handling
190 int res = 0;
191 TRY
192 res = realMain(argc, argv);
193 EXCEPT(res = 3)
194 return res;
195}
196
197static bool testOneRegExp(VM& vm, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
198{
199 bool result = true;
200 Vector<int, 32> outVector;
201 outVector.resize(regExpTest->expectVector.size());
202 int matchResult = regexp->match(vm, regExpTest->subject, regExpTest->offset, outVector);
203
204 if (matchResult != regExpTest->result) {
205 result = false;
206 if (verbose)
207 printf("Line %d: results mismatch - expected %d got %d\n", lineNumber, regExpTest->result, matchResult);
208 } else if (matchResult != -1) {
209 if (outVector.size() != regExpTest->expectVector.size()) {
210 result = false;
211 if (verbose)
212 printf("Line %d: output vector size mismatch - expected %lu got %lu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
213 } else if (outVector.size() % 2) {
214 result = false;
215 if (verbose)
216 printf("Line %d: output vector size is odd (%lu), should be even\n", lineNumber, outVector.size());
217 } else {
218 // Check in pairs since the first value of the pair could be -1 in which case the second doesn't matter.
219 size_t pairCount = outVector.size() / 2;
220 for (size_t i = 0; i < pairCount; ++i) {
221 size_t startIndex = i*2;
222 if (outVector[startIndex] != regExpTest->expectVector[startIndex]) {
223 result = false;
224 if (verbose)
225 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
226 }
227 if ((i > 0) && (regExpTest->expectVector[startIndex] != -1) && (outVector[startIndex+1] != regExpTest->expectVector[startIndex+1])) {
228 result = false;
229 if (verbose)
230 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex+1, regExpTest->expectVector[startIndex+1], outVector[startIndex+1]);
231 }
232 }
233 }
234 }
235
236 return result;
237}
238
239static int scanString(char* buffer, int bufferLength, StringBuilder& builder, char termChar)
240{
241 bool escape = false;
242
243 for (int i = 0; i < bufferLength; ++i) {
244 UChar c = buffer[i];
245
246 if (escape) {
247 switch (c) {
248 case '0':
249 c = '\0';
250 break;
251 case 'a':
252 c = '\a';
253 break;
254 case 'b':
255 c = '\b';
256 break;
257 case 'f':
258 c = '\f';
259 break;
260 case 'n':
261 c = '\n';
262 break;
263 case 'r':
264 c = '\r';
265 break;
266 case 't':
267 c = '\t';
268 break;
269 case 'v':
270 c = '\v';
271 break;
272 case '\\':
273 c = '\\';
274 break;
275 case '?':
276 c = '\?';
277 break;
278 case 'u':
279 if ((i + 4) >= bufferLength)
280 return -1;
281 unsigned int charValue;
282 if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
283 return -1;
284 c = static_cast<UChar>(charValue);
285 i += 4;
286 break;
287 }
288
289 builder.append(c);
290 escape = false;
291 } else {
292 if (c == termChar)
293 return i;
294
295 if (c == '\\')
296 escape = true;
297 else
298 builder.append(c);
299 }
300 }
301
302 return -1;
303}
304
305static RegExp* parseRegExpLine(VM& vm, char* line, int lineLength)
306{
307 StringBuilder pattern;
308
309 if (line[0] != '/')
310 return 0;
311
312 int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;
313
314 if ((i >= lineLength) || (line[i] != '/'))
315 return 0;
316
317 ++i;
318
319 return RegExp::create(vm, pattern.toString(), regExpFlags(line + i));
320}
321
322static RegExpTest* parseTestLine(char* line, int lineLength)
323{
324 StringBuilder subjectString;
325
326 if ((line[0] != ' ') || (line[1] != '"'))
327 return 0;
328
329 int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;
330
331 if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
332 return 0;
333
334 i += 3;
335
336 int offset;
337
338 if (sscanf(line + i, "%d, ", &offset) != 1)
339 return 0;
340
341 while (line[i] && line[i] != ' ')
342 ++i;
343
344 ++i;
345
346 int matchResult;
347
348 if (sscanf(line + i, "%d, ", &matchResult) != 1)
349 return 0;
350
351 while (line[i] && line[i] != ' ')
352 ++i;
353
354 ++i;
355
356 if (line[i++] != '(')
357 return 0;
358
359 int start, end;
360
361 RegExpTest* result = new RegExpTest();
362
363 result->subject = subjectString.toString();
364 result->offset = offset;
365 result->result = matchResult;
366
367 while (line[i] && line[i] != ')') {
368 if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
369 delete result;
370 return 0;
371 }
372
373 result->expectVector.append(start);
374 result->expectVector.append(end);
375
376 while (line[i] && (line[i] != ',') && (line[i] != ')'))
377 i++;
378 i++;
379 while (line[i] && (line[i] != ',') && (line[i] != ')'))
380 i++;
381
382 if (line[i] == ')')
383 break;
384 if (!line[i] || (line[i] != ',')) {
385 delete result;
386 return 0;
387 }
388 i++;
389 }
390
391 return result;
392}
393
394static bool runFromFiles(GlobalObject* globalObject, const Vector<String>& files, bool verbose)
395{
396 String script;
397 String fileName;
398 Vector<char> scriptBuffer;
399 unsigned tests = 0;
400 unsigned failures = 0;
401 char* lineBuffer = new char[MaxLineLength + 1];
402
403 VM& vm = globalObject->vm();
404
405 bool success = true;
406 for (size_t i = 0; i < files.size(); i++) {
407 FILE* testCasesFile = fopen(files[i].utf8().data(), "rb");
408
409 if (!testCasesFile) {
410 printf("Unable to open test data file \"%s\"\n", files[i].utf8().data());
411 continue;
412 }
413
414 RegExp* regexp = 0;
415 size_t lineLength = 0;
416 char* linePtr = 0;
417 unsigned int lineNumber = 0;
418
419 while ((linePtr = fgets(&lineBuffer[0], MaxLineLength, testCasesFile))) {
420 lineLength = strlen(linePtr);
421 if (linePtr[lineLength - 1] == '\n') {
422 linePtr[lineLength - 1] = '\0';
423 --lineLength;
424 }
425 ++lineNumber;
426
427 if (linePtr[0] == '#')
428 continue;
429
430 if (linePtr[0] == '/') {
431 regexp = parseRegExpLine(vm, linePtr, lineLength);
432 } else if (linePtr[0] == ' ') {
433 RegExpTest* regExpTest = parseTestLine(linePtr, lineLength);
434
435 if (regexp && regExpTest) {
436 ++tests;
437 if (!testOneRegExp(vm, regexp, regExpTest, verbose, lineNumber)) {
438 failures++;
439 printf("Failure on line %u\n", lineNumber);
440 }
441 }
442
443 if (regExpTest)
444 delete regExpTest;
445 }
446 }
447
448 fclose(testCasesFile);
449 }
450
451 if (failures)
452 printf("%u tests run, %u failures\n", tests, failures);
453 else
454 printf("%u tests passed\n", tests);
455
456 delete[] lineBuffer;
457
458 vm.dumpSampleData(globalObject->globalExec());
459#if ENABLE(REGEXP_TRACING)
460 vm.dumpRegExpTrace();
461#endif
462 return success;
463}
464
465#define RUNNING_FROM_XCODE 0
466
467static NO_RETURN void printUsageStatement(bool help = false)
468{
469 fprintf(stderr, "Usage: regexp_test [options] file\n");
470 fprintf(stderr, " -h|--help Prints this help message\n");
471 fprintf(stderr, " -v|--verbose Verbose output\n");
472
473 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
474}
475
476static void parseArguments(int argc, char** argv, CommandLine& options)
477{
478 int i = 1;
479 for (; i < argc; ++i) {
480 const char* arg = argv[i];
481 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
482 printUsageStatement(true);
483 if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
484 options.verbose = true;
485 else
486 options.files.append(argv[i]);
487 }
488
489 for (; i < argc; ++i)
490 options.arguments.append(argv[i]);
491}
492
493int realMain(int argc, char** argv)
494{
495 VM* vm = VM::create(LargeHeap).leakRef();
496 JSLockHolder locker(vm);
497
498 CommandLine options;
499 parseArguments(argc, argv, options);
500
501 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.arguments);
502 bool success = runFromFiles(globalObject, options.files, options.verbose);
503
504 return success ? 0 : 3;
505}
506
507#if OS(WINDOWS)
508extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
509{
510 return main(argc, const_cast<char**>(argv));
511}
512#endif
Note: See TracBrowser for help on using the repository browser.