source: webkit/trunk/JavaScriptCore/kjs/testkjs.cpp@ 26185

Last change on this file since 26185 was 26185, checked in by staikos, 18 years ago

Fix the build on Win32 for VS2005. A solution for mingw and others may be
needed for FTPDirectory*.cpp still

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * Copyright (C) 1999-2000 Harri Porten ([email protected])
4 * Copyright (C) 2004-2007 Apple Inc.
5 * Copyright (C) 2006 Bjoern Graf ([email protected])
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "collector.h"
26
27#include <wtf/HashTraits.h>
28#include "JSLock.h"
29#include "object.h"
30#include "Parser.h"
31
32#include <math.h>
33#include <stdio.h>
34
35#include <string.h>
36#if HAVE(SYS_TIME_H)
37#include <sys/time.h>
38#endif
39
40#include "protect.h"
41
42#if PLATFORM(WIN)
43#include <WebKitInitializer/WebKitInitializer.h>
44#include <crtdbg.h>
45#include <windows.h>
46#endif
47
48#if PLATFORM(QT)
49#include <QDateTime>
50#endif
51
52using namespace KJS;
53using namespace WTF;
54
55static void testIsInteger();
56static char* createStringWithContentsOfFile(const char* fileName);
57
58class StopWatch
59{
60public:
61 void start();
62 void stop();
63 long getElapsedMS(); // call stop() first
64
65private:
66#if PLATFORM(QT)
67 uint m_startTime;
68 uint m_stopTime;
69#elif PLATFORM(WIN_OS)
70 DWORD m_startTime;
71 DWORD m_stopTime;
72#else
73 // Windows does not have timeval, disabling this class for now (bug 7399)
74 timeval m_startTime;
75 timeval m_stopTime;
76#endif
77};
78
79void StopWatch::start()
80{
81#if PLATFORM(QT)
82 QDateTime t = QDateTime::currentDateTime();
83 m_startTime = t.toTime_t() * 1000 + t.time().msec();
84#elif PLATFORM(WIN_OS)
85 m_startTime = timeGetTime();
86#else
87 gettimeofday(&m_startTime, 0);
88#endif
89}
90
91void StopWatch::stop()
92{
93#if PLATFORM(QT)
94 QDateTime t = QDateTime::currentDateTime();
95 m_stopTime = t.toTime_t() * 1000 + t.time().msec();
96#elif PLATFORM(WIN_OS)
97 m_stopTime = timeGetTime();
98#else
99 gettimeofday(&m_stopTime, 0);
100#endif
101}
102
103long StopWatch::getElapsedMS()
104{
105#if PLATFORM(WIN_OS) || PLATFORM(QT)
106 return m_stopTime - m_startTime;
107#else
108 timeval elapsedTime;
109 timersub(&m_stopTime, &m_startTime, &elapsedTime);
110
111 return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
112#endif
113}
114
115class GlobalImp : public JSObject {
116public:
117 virtual UString className() const { return "global"; }
118};
119
120class TestFunctionImp : public JSObject {
121public:
122 TestFunctionImp(int i, int length);
123 virtual bool implementsCall() const { return true; }
124 virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List &args);
125
126 enum { Print, Debug, Quit, GC, Version, Run };
127
128private:
129 int id;
130};
131
132TestFunctionImp::TestFunctionImp(int i, int length) : JSObject(), id(i)
133{
134 putDirect(Identifier("length"), length, DontDelete | ReadOnly | DontEnum);
135}
136
137JSValue* TestFunctionImp::callAsFunction(ExecState* exec, JSObject*, const List &args)
138{
139 switch (id) {
140 case Print:
141 printf("--> %s\n", args[0]->toString(exec).UTF8String().c_str());
142 return jsUndefined();
143 case Debug:
144 fprintf(stderr, "--> %s\n", args[0]->toString(exec).UTF8String().c_str());
145 return jsUndefined();
146 case GC:
147 {
148 JSLock lock;
149 Collector::collect();
150 return jsUndefined();
151 }
152 case Version:
153 // We need this function for compatibility with the Mozilla JS tests but for now
154 // we don't actually do any version-specific handling
155 return jsUndefined();
156 case Run:
157 {
158 StopWatch stopWatch;
159 char* fileName = strdup(args[0]->toString(exec).UTF8String().c_str());
160 char* script = createStringWithContentsOfFile(fileName);
161 if (!script)
162 return throwError(exec, GeneralError, "Could not open file.");
163
164 stopWatch.start();
165 exec->dynamicInterpreter()->evaluate(fileName, 0, script);
166 stopWatch.stop();
167
168 free(script);
169 free(fileName);
170
171 return jsNumber(stopWatch.getElapsedMS());
172 }
173 case Quit:
174 exit(0);
175 default:
176 abort();
177 }
178 return 0;
179}
180
181#if PLATFORM(WIN_OS)
182
183// Use SEH for Release builds only to get rid of the crash report dialog
184// (luckyly the same tests fail in Release and Debug builds so far). Need to
185// be in a separate main function because the kjsmain function requires object
186// unwinding.
187
188#if defined(_DEBUG)
189#define TRY
190#define EXCEPT(x)
191#else
192#define TRY __try {
193#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
194#endif
195
196#else
197
198#define TRY
199#define EXCEPT(x)
200
201#endif
202
203int kjsmain(int argc, char** argv);
204
205int main(int argc, char** argv)
206{
207#if PLATFORM(WIN)
208 if (!initializeWebKit()) {
209 fprintf(stderr, "Failed to initialize WebKit\n");
210 abort();
211 }
212#endif
213#if defined(_DEBUG) && PLATFORM(WIN_OS)
214 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
215 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
216 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
217 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
218 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
219 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
220#endif
221
222 int res = 0;
223 TRY
224 res = kjsmain(argc, argv);
225 EXCEPT(res = 3)
226 return res;
227}
228
229
230bool doIt(int argc, char** argv)
231{
232 bool success = true;
233 bool prettyPrint = false;
234 GlobalImp* global = new GlobalImp();
235
236 // create interpreter
237 RefPtr<Interpreter> interp = new Interpreter(global);
238 // add debug() function
239 global->put(interp->globalExec(), "debug", new TestFunctionImp(TestFunctionImp::Debug, 1));
240 // add "print" for compatibility with the mozilla js shell
241 global->put(interp->globalExec(), "print", new TestFunctionImp(TestFunctionImp::Print, 1));
242 // add "quit" for compatibility with the mozilla js shell
243 global->put(interp->globalExec(), "quit", new TestFunctionImp(TestFunctionImp::Quit, 0));
244 // add "gc" for compatibility with the mozilla js shell
245 global->put(interp->globalExec(), "gc", new TestFunctionImp(TestFunctionImp::GC, 0));
246 // add "version" for compatibility with the mozilla js shell
247 global->put(interp->globalExec(), "version", new TestFunctionImp(TestFunctionImp::Version, 1));
248 global->put(interp->globalExec(), "run", new TestFunctionImp(TestFunctionImp::Run, 1));
249
250 Interpreter::setShouldPrintExceptions(true);
251
252 for (int i = 1; i < argc; i++) {
253 const char* fileName = argv[i];
254 if (strcmp(fileName, "-f") == 0) // mozilla test driver script uses "-f" prefix for files
255 continue;
256 if (strcmp(fileName, "-p") == 0) {
257 prettyPrint = true;
258 continue;
259 }
260
261 char* script = createStringWithContentsOfFile(fileName);
262 if (!script) {
263 success = false;
264 break; // fail early so we can catch missing files
265 }
266
267 if (prettyPrint) {
268 int errLine = 0;
269 UString errMsg;
270 UString s = Parser::prettyPrint(script, &errLine, &errMsg);
271 if (s.isNull()) {
272 fprintf(stderr, "%s:%d: %s.\n", fileName, errLine, errMsg.UTF8String().c_str());
273 success = false;
274 free(script);
275 break;
276 }
277
278 printf("%s\n", s.UTF8String().c_str());
279
280 } else {
281 Completion completion = interp->evaluate(fileName, 0, script);
282 success = success && completion.complType() != Throw;
283 }
284
285 free(script);
286 }
287
288 return success;
289}
290
291
292int kjsmain(int argc, char** argv)
293{
294 if (argc < 2) {
295 fprintf(stderr, "Usage: testkjs file1 [file2...]\n");
296 return -1;
297 }
298
299 testIsInteger();
300
301 JSLock lock;
302
303 bool success = doIt(argc, argv);
304
305#ifndef NDEBUG
306 Collector::collect();
307#endif
308
309 if (success)
310 fprintf(stderr, "OK.\n");
311
312#ifdef KJS_DEBUG_MEM
313 Interpreter::finalCheck();
314#endif
315 return success ? 0 : 3;
316}
317
318static void testIsInteger()
319{
320 // Unit tests for WTF::IsInteger. Don't have a better place for them now.
321 // FIXME: move these once we create a unit test directory for WTF.
322
323 assert(IsInteger<bool>::value);
324 assert(IsInteger<char>::value);
325 assert(IsInteger<signed char>::value);
326 assert(IsInteger<unsigned char>::value);
327 assert(IsInteger<short>::value);
328 assert(IsInteger<unsigned short>::value);
329 assert(IsInteger<int>::value);
330 assert(IsInteger<unsigned int>::value);
331 assert(IsInteger<long>::value);
332 assert(IsInteger<unsigned long>::value);
333 assert(IsInteger<long long>::value);
334 assert(IsInteger<unsigned long long>::value);
335
336 assert(!IsInteger<char*>::value);
337 assert(!IsInteger<const char* >::value);
338 assert(!IsInteger<volatile char* >::value);
339 assert(!IsInteger<double>::value);
340 assert(!IsInteger<float>::value);
341 assert(!IsInteger<GlobalImp>::value);
342}
343
344static char* createStringWithContentsOfFile(const char* fileName)
345{
346 char* buffer;
347
348 size_t buffer_size = 0;
349 size_t buffer_capacity = 1024;
350 buffer = (char*)malloc(buffer_capacity);
351
352 FILE* f = fopen(fileName, "r");
353 if (!f) {
354 fprintf(stderr, "Could not open file: %s\n", fileName);
355 free(buffer);
356 return 0;
357 }
358
359 while (!feof(f) && !ferror(f)) {
360 buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
361 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
362 buffer_capacity *= 2;
363 buffer = (char*)realloc(buffer, buffer_capacity);
364 assert(buffer);
365 }
366
367 assert(buffer_size < buffer_capacity);
368 }
369 fclose(f);
370 buffer[buffer_size] = '\0';
371
372 return buffer;
373}
Note: See TracBrowser for help on using the repository browser.