Warning, file /frameworks/kjs/tests/testkjs.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2004-2006 Apple Computer, Inc. 0005 * Copyright (C) 2006 Björn Graf (bjoern.graf@gmail.com) 0006 * 0007 * This library is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU Library General Public 0009 * License as published by the Free Software Foundation; either 0010 * version 2 of the License, or (at your option) any later version. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Library General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Library General Public License 0018 * along with this library; see the file COPYING.LIB. If not, write to 0019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 * Boston, MA 02110-1301, USA. 0021 * 0022 */ 0023 0024 #include "collector.h" 0025 0026 #include <wtf/HashTraits.h> 0027 #include "JSLock.h" 0028 #include "object.h" 0029 #include "JSVariableObject.h" 0030 #include "Parser.h" 0031 0032 #include <math.h> 0033 #include <stdio.h> 0034 #include <string.h> 0035 0036 #include "global.h" 0037 #if HAVE_SYS_TIME_H 0038 #include <sys/time.h> 0039 #endif 0040 0041 #include "protect.h" 0042 0043 #if defined(WTF_COMPILER_MSVC) 0044 #include <windows.h> 0045 #include <timeapi.h> 0046 #if HAVE_CRTDBG_H 0047 #include <crtdbg.h> 0048 #endif 0049 #endif 0050 0051 #if PLATFORM(WIN_OS) && ! defined(WTF_COMPILER_MSVC) 0052 #ifndef timersub 0053 # define timersub(a, b, result) \ 0054 do { \ 0055 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 0056 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 0057 if ((result)->tv_usec < 0) { \ 0058 --(result)->tv_sec; \ 0059 (result)->tv_usec += 1000000; \ 0060 } \ 0061 } while (0) 0062 #endif 0063 #endif 0064 0065 using namespace KJS; 0066 using namespace WTF; 0067 0068 static void testIsInteger(); 0069 static void testUString(); 0070 static char *createStringWithContentsOfFile(const char *fileName); 0071 0072 class StopWatch 0073 { 0074 public: 0075 void start(); 0076 void stop(); 0077 long getElapsedMS(); // call stop() first 0078 0079 private: 0080 #if ! HAVE_GETTIMEOFDAY 0081 DWORD m_startTime; 0082 DWORD m_stopTime; 0083 #else 0084 // Windows does not have timeval, disabling this class for now (bug 7399) 0085 timeval m_startTime; 0086 timeval m_stopTime; 0087 #endif 0088 }; 0089 0090 void StopWatch::start() 0091 { 0092 #if ! HAVE_GETTIMEOFDAY 0093 m_startTime = timeGetTime(); 0094 #else 0095 gettimeofday(&m_startTime, nullptr); 0096 #endif 0097 } 0098 0099 void StopWatch::stop() 0100 { 0101 #if ! HAVE_GETTIMEOFDAY 0102 m_stopTime = timeGetTime(); 0103 #else 0104 gettimeofday(&m_stopTime, nullptr); 0105 #endif 0106 } 0107 0108 long StopWatch::getElapsedMS() 0109 { 0110 #if ! HAVE_GETTIMEOFDAY 0111 return m_stopTime - m_startTime; 0112 #else 0113 timeval elapsedTime; 0114 timersub(&m_stopTime, &m_startTime, &elapsedTime); 0115 0116 return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f); 0117 #endif 0118 } 0119 0120 class GlobalImp : public JSGlobalObject 0121 { 0122 public: 0123 UString className() const override 0124 { 0125 return "global"; 0126 } 0127 }; 0128 0129 class TestFunctionImp : public JSObject 0130 { 0131 public: 0132 TestFunctionImp(int i, int length); 0133 bool implementsCall() const override 0134 { 0135 return true; 0136 } 0137 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) override; 0138 0139 enum { Print, Debug, Quit, GC, Version, Run }; 0140 0141 private: 0142 int id; 0143 }; 0144 0145 TestFunctionImp::TestFunctionImp(int i, int length) : JSObject(), id(i) 0146 { 0147 putDirect(Identifier("length"), length, DontDelete | ReadOnly | DontEnum); 0148 } 0149 0150 JSValue *TestFunctionImp::callAsFunction(ExecState *exec, JSObject *, const List &args) 0151 { 0152 switch (id) { 0153 case Print: 0154 printf("--> %s\n", JSValue::toString(args[0], exec).UTF8String().c_str()); 0155 return jsUndefined(); 0156 case Debug: 0157 fprintf(stderr, "--> %s\n", JSValue::toString(args[0], exec).UTF8String().c_str()); 0158 return jsUndefined(); 0159 case GC: { 0160 JSLock lock; 0161 Interpreter::collect(); 0162 return jsUndefined(); 0163 } 0164 case Version: 0165 // We need this function for compatibility with the Mozilla JS tests but for now 0166 // we don't actually do any version-specific handling 0167 return jsUndefined(); 0168 case Run: { 0169 StopWatch stopWatch; 0170 char *fileName = strdup(JSValue::toString(args[0], exec).UTF8String().c_str()); 0171 char *script = createStringWithContentsOfFile(fileName); 0172 if (!script) { 0173 return throwError(exec, GeneralError, "Could not open file."); 0174 } 0175 0176 stopWatch.start(); 0177 exec->dynamicInterpreter()->evaluate(fileName, 0, script); 0178 stopWatch.stop(); 0179 0180 free(script); 0181 free(fileName); 0182 0183 return jsNumber(stopWatch.getElapsedMS()); 0184 } 0185 case Quit: 0186 exit(0); 0187 default: 0188 abort(); 0189 } 0190 return nullptr; 0191 } 0192 0193 #if PLATFORM(WIN_OS) && defined(HAVE_CRTDBG_H) && !defined(__MINGW32__) 0194 // Use SEH for Release builds only to get rid of the crash report dialog 0195 // (luckily the same tests fail in Release and Debug builds so far). Need to 0196 // be in a separate main function because the kjsmain function requires object 0197 // unwinding. 0198 0199 #if defined(_DEBUG) 0200 #define TRY 0201 #define EXCEPT(x) 0202 #else 0203 #define TRY __try { 0204 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; } 0205 #endif 0206 0207 #else 0208 0209 #define TRY 0210 #define EXCEPT(x) 0211 0212 #endif 0213 0214 int kjsmain(int argc, char **argv); 0215 0216 int main(int argc, char **argv) 0217 { 0218 #if defined(_DEBUG) && PLATFORM(WIN_OS) 0219 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 0220 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 0221 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); 0222 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 0223 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); 0224 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 0225 #endif 0226 0227 int res = 0; 0228 TRY 0229 res = kjsmain(argc, argv); 0230 EXCEPT(res = 3) 0231 return res; 0232 } 0233 0234 bool doIt(int argc, char **argv) 0235 { 0236 bool success = true; 0237 #if 0 0238 bool prettyPrint = false; 0239 #endif 0240 GlobalImp *global = new GlobalImp(); 0241 0242 // create interpreter 0243 RefPtr<Interpreter> interp = new Interpreter(global); 0244 // add debug() function 0245 global->put(interp->globalExec(), "debug", new TestFunctionImp(TestFunctionImp::Debug, 1)); 0246 // add "print" for compatibility with the mozilla js shell 0247 global->put(interp->globalExec(), "print", new TestFunctionImp(TestFunctionImp::Print, 1)); 0248 // add "quit" for compatibility with the mozilla js shell 0249 global->put(interp->globalExec(), "quit", new TestFunctionImp(TestFunctionImp::Quit, 0)); 0250 // add "gc" for compatibility with the mozilla js shell 0251 global->put(interp->globalExec(), "gc", new TestFunctionImp(TestFunctionImp::GC, 0)); 0252 // add "version" for compatibility with the mozilla js shell 0253 global->put(interp->globalExec(), "version", new TestFunctionImp(TestFunctionImp::Version, 1)); 0254 global->put(interp->globalExec(), "run", new TestFunctionImp(TestFunctionImp::Run, 1)); 0255 0256 // abort evaluation of single script file after 5 seconds 0257 interp->setTimeoutTime(5000); 0258 0259 Interpreter::setShouldPrintExceptions(true); 0260 0261 for (int i = 1; i < argc; i++) { 0262 const char *fileName = argv[i]; 0263 if (strcmp(fileName, "-f") == 0) { // mozilla test driver script uses "-f" prefix for files 0264 continue; 0265 } 0266 #if 0 0267 if (strcmp(fileName, "-p") == 0) { 0268 prettyPrint = true; 0269 continue; 0270 } 0271 #endif 0272 0273 char *script = createStringWithContentsOfFile(fileName); 0274 if (!script) { 0275 success = false; 0276 break; // fail early so we can catch missing files 0277 } 0278 0279 #if 0 0280 if (prettyPrint) { 0281 int errLine = 0; 0282 UString errMsg; 0283 UString s = Parser::prettyPrint(script, &errLine, &errMsg); 0284 if (s.isNull()) { 0285 fprintf(stderr, "%s:%d: %s.\n", fileName, errLine, errMsg.UTF8String().c_str()); 0286 success = false; 0287 break; 0288 } 0289 0290 printf("%s\n", s.UTF8String().c_str()); 0291 } else 0292 #endif 0293 { 0294 interp->startTimeoutCheck(); 0295 Completion completion = interp->evaluate(fileName, 0, script); 0296 interp->stopTimeoutCheck(); 0297 success = success && completion.complType() != Throw; 0298 } 0299 free(script); 0300 } 0301 0302 return success; 0303 } 0304 0305 int kjsmain(int argc, char **argv) 0306 { 0307 if (argc < 2) { 0308 fprintf(stderr, "Usage: testkjs file1 [file2...]\n"); 0309 return -1; 0310 } 0311 0312 testIsInteger(); 0313 testUString(); 0314 0315 JSLock lock; 0316 0317 bool success = doIt(argc, argv); 0318 0319 #ifndef NDEBUG 0320 Collector::collect(); 0321 #endif 0322 0323 if (success) { 0324 fprintf(stderr, "OK.\n"); 0325 } 0326 0327 return success ? 0 : 3; 0328 } 0329 0330 static void testIsInteger() 0331 { 0332 // Unit tests for WTF::IsInteger. Don't have a better place for them now. 0333 // FIXME: move these once we create a unit test directory for WTF. 0334 0335 assert(IsInteger<bool>::value); 0336 assert(IsInteger<char>::value); 0337 assert(IsInteger<signed char>::value); 0338 assert(IsInteger<unsigned char>::value); 0339 assert(IsInteger<short>::value); 0340 assert(IsInteger<unsigned short>::value); 0341 assert(IsInteger<int>::value); 0342 assert(IsInteger<unsigned int>::value); 0343 assert(IsInteger<long>::value); 0344 assert(IsInteger<unsigned long>::value); 0345 assert(IsInteger<long long>::value); 0346 assert(IsInteger<unsigned long long>::value); 0347 0348 assert(!IsInteger<char *>::value); 0349 assert(!IsInteger<const char * >::value); 0350 assert(!IsInteger<volatile char * >::value); 0351 assert(!IsInteger<double>::value); 0352 assert(!IsInteger<float>::value); 0353 assert(!IsInteger<GlobalImp>::value); 0354 } 0355 0356 // not a good place either 0357 void testUString() 0358 { 0359 // bug #141720 0360 UString s1 = "abc"; 0361 UString s2 = s1; 0362 s1.append("xxx"); 0363 s2.append((unsigned short)0x64); 0364 assert(s2.size() == 4); 0365 } 0366 0367 static char *createStringWithContentsOfFile(const char *fileName) 0368 { 0369 char *buffer; 0370 0371 size_t buffer_size = 0; 0372 size_t buffer_capacity = 1024; 0373 buffer = (char *)malloc(buffer_capacity); 0374 0375 FILE *f = fopen(fileName, "r"); 0376 if (!f) { 0377 fprintf(stderr, "Could not open file: %s\n", fileName); 0378 return nullptr; 0379 } 0380 0381 while (!feof(f) && !ferror(f)) { 0382 buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f); 0383 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0' 0384 buffer_capacity *= 2; 0385 buffer = (char *)realloc(buffer, buffer_capacity); 0386 assert(buffer); 0387 } 0388 0389 assert(buffer_size < buffer_capacity); 0390 } 0391 fclose(f); 0392 buffer[buffer_size] = '\0'; 0393 0394 return buffer; 0395 }