void tst_QScriptV8TestSuite::runTestFunction(int testIndex) { QString name = testNames.at(testIndex); QString path = testsDir.absoluteFilePath(name + ".js"); QString excludeMessage; if (isExcludedTest(name, &excludeMessage)) { QTest::qSkip(excludeMessage.toLatin1(), path.toLatin1(), -1); return; } QScriptEngine engine; engine.evaluate(mjsunitContents); if (engine.hasUncaughtException()) { QStringList bt = engine.uncaughtExceptionBacktrace(); QString err = engine.uncaughtException().toString(); qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); } else { // Prepare to intercept calls to mjsunit's fail() function. QScriptValue fakeFail = engine.newFunction(qscript_fail); fakeFail.setData(engine.globalObject().property("fail")); engine.globalObject().setProperty("fail", fakeFail); QString contents = readFile(path); QScriptValue ret = engine.evaluate(contents); if (engine.hasUncaughtException()) { if (!ret.isError()) { int lineNumber = ret.property("lineNumber").toInt32(); QTest::qVerify(ret.instanceOf(engine.globalObject().property("MjsUnitAssertionError")), ret.toString().toLatin1(), "", path.toLatin1(), lineNumber); QString actual = ret.property("actual").toString(); QString expected = ret.property("expected").toString(); QString failMessage; if (shouldGenerateExpectedFailures) { if (ret.property("message").isString()) failMessage = ret.property("message").toString(); addExpectedFailure(name, actual, expected, failMessage); } else if (isExpectedFailure(name, actual, expected, &failMessage)) { QTest::qExpectFail("", failMessage.toLatin1(), QTest::Continue, path.toLatin1(), lineNumber); } QTest::qCompare(actual, expected, "actual", "expect", path.toLatin1(), lineNumber); } else { int lineNumber = ret.property("lineNumber").toInt32(); QTest::qExpectFail("", ret.toString().toLatin1(), QTest::Continue, path.toLatin1(), lineNumber); QTest::qVerify(false, ret.toString().toLatin1(), "", path.toLatin1(), lineNumber); } } } }
tst_Suite::tst_Suite() { testsDir = QDir(SRCDIR); bool testsFound = testsDir.cd("tests"); if (!testsFound) { qWarning("*** no tests/ dir!"); } else { if (!testsDir.exists("mjsunit.js")) qWarning("*** no tests/mjsunit.js file!"); else { mjsunitContents = readFile(testsDir.absoluteFilePath("mjsunit.js")); if (mjsunitContents.isEmpty()) qWarning("*** tests/mjsunit.js is empty!"); } } QString willFixInNextReleaseMessage = QString::fromLatin1("Will fix in next release"); addExpectedFailure("arguments-enum", "2", "0", willFixInNextReleaseMessage); addExpectedFailure("const-redecl", "undefined", "TypeError", willFixInNextReleaseMessage); addExpectedFailure("global-const-var-conflicts", "false", "true", willFixInNextReleaseMessage); addExpectedFailure("string-lastindexof", "0", "-1", "test is wrong?"); addTestExclusion("debug-*", "not applicable"); addTestExclusion("mirror-*", "not applicable"); addTestExclusion("array-concat", "Hangs on JSC backend"); addTestExclusion("array-splice", "Hangs on JSC backend"); addTestExclusion("sparse-array-reverse", "Hangs on JSC backend"); addTestExclusion("string-case", "V8-specific behavior? (Doesn't pass on SpiderMonkey either)"); #ifdef Q_OS_WINCE addTestExclusion("deep-recursion", "Demands too much memory on WinCE"); addTestExclusion("nested-repetition-count-overflow", "Demands too much memory on WinCE"); addTestExclusion("unicode-test", "Demands too much memory on WinCE"); addTestExclusion("mul-exhaustive", "Demands too much memory on WinCE"); #endif #ifdef Q_OS_SYMBIAN addTestExclusion("nested-repetition-count-overflow", "Demands too much memory on Symbian"); addTestExclusion("unicode-test", "Demands too much memory on Symbian"); #endif // Failures due to switch to JSC as back-end addExpectedFailure("date-parse", "NaN", "946713600000", willFixInNextReleaseMessage); addExpectedFailure("delete-global-properties", "true", "false", willFixInNextReleaseMessage); addExpectedFailure("delete", "false", "true", willFixInNextReleaseMessage); addExpectedFailure("function-arguments-null", "false", "true", willFixInNextReleaseMessage); addExpectedFailure("function-caller", "null", "function eval() {\n [native code]\n}", willFixInNextReleaseMessage); addExpectedFailure("function-prototype", "prototype", "disconnectconnect", willFixInNextReleaseMessage); addExpectedFailure("number-tostring", "0", "0.0000a7c5ac471b4788", willFixInNextReleaseMessage); addExpectedFailure("parse-int-float", "1e+21", "1", willFixInNextReleaseMessage); addExpectedFailure("regexp", "false", "true", willFixInNextReleaseMessage); addExpectedFailure("smi-negative-zero", "-Infinity", "Infinity", willFixInNextReleaseMessage); addExpectedFailure("string-split", "4", "3", willFixInNextReleaseMessage); addExpectedFailure("substr", "abcdefghijklmn", "", willFixInNextReleaseMessage); static const char klass[] = "tst_QScriptV8TestSuite"; QVector<uint> *data = qt_meta_data_tst_Suite(); // content: *data << 1 // revision << 0 // classname << 0 << 0 // classinfo << 0 << 10 // methods (backpatched later) << 0 << 0 // properties << 0 << 0 // enums/sets ; QVector<char> *stringdata = qt_meta_stringdata_tst_Suite(); appendCString(stringdata, klass); appendCString(stringdata, ""); QFileInfoList testFileInfos; if (testsFound) testFileInfos = testsDir.entryInfoList(QStringList() << "*.js", QDir::Files); foreach (QFileInfo tfi, testFileInfos) { QString name = tfi.baseName(); // slot: signature, parameters, type, tag, flags QString slot = QString::fromLatin1("%0()").arg(name); static const int nullbyte = sizeof(klass); *data << stringdata->size() << nullbyte << nullbyte << nullbyte << 0x08; appendCString(stringdata, slot.toLatin1()); testNames.append(name); }