void DroneshareUploadDialog::vehicleQueryComplete(const QString &jsonResponse)
{
    QLOG_DEBUG() << "droneshare: Vehicle Query Complete"/* << jsonResponse*/;

    QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(jsonResponse);
    QScriptEngine engine;
    QScriptValue result = engine.evaluate("("+jsonResponse+")");

    if (engine.hasUncaughtException()){
        QLOG_ERROR() << "Error evaluating version object";
        QLOG_ERROR() << "Error @line#" << engine.uncaughtExceptionLineNumber();
        QLOG_ERROR() << "Backtrace:" << engine.uncaughtExceptionBacktrace();
        QLOG_ERROR() << "Syntax Check:" << syntaxCheck.errorMessage();
        QLOG_ERROR() << "Syntax Check line:" << syntaxCheck.errorLineNumber()
                     << " col:" << syntaxCheck.errorColumnNumber();
        return;
    }
    ui->statusLabel->setText("Vehicle Query Complete.");
    QMap<QString,QString> vehicleList;

    QScriptValue entries = result.property("vehicles");
    QScriptValueIterator it(entries);
    while (it.hasNext()){
        it.next();
        QScriptValue entry = it.value();
        QString uuid = entry.property("uuid").toString();
        QString name = entry.property("name").toString();
        vehicleList.insert(name,uuid);
    }

    bool ok = false;
    QString item = QInputDialog::getItem(this, tr("Vehicle Selection"),tr("vehicle"),vehicleList.keys(),1,
                                                          false, &ok, Qt::Dialog, Qt::ImhNone);
    if (ok){
        startLogUpload(vehicleList.value(item));
    }

    m_droneshareQuery->deleteLater();
    m_droneshareQuery = NULL;
}
Example #2
0
Graph * JSONGraphReader::ReadGraph(const QString & filename, Graph * graph){
    QFile file( filename );
    if ( file.open(  QIODevice::ReadOnly ) ) {

        QTextStream stream( &file );
        stream.setCodec("utf-8");
        QString str = stream.readAll();
        QScriptValue sc;
        QScriptEngine engine;
        sc = engine.evaluate("("+ str +")");
        if(engine.hasUncaughtException()){
            QMessageBox::warning(0,"Warning", "Warning\nException on line:"+QString(engine.uncaughtExceptionLineNumber())
                                 +"\n"+engine.uncaughtExceptionBacktrace().join("\n"));
            return 0;
        }
        if( !graph )
            graph = new Graph;

        LoadVers(graph, sc);
        LoadEdges(graph, sc);
        GraphInfo * gi;
        graph->setInfo( m_infoReader->ReadGraphInfo( sc ));
//        }catch(ReaderError & e){
//            qDebug()<<e.message();
//            return 0;
//        }
        //graph->setInfo( gi );
//        qDebug()<<gi->name();
//        graph->setInfo( gi );
        file.close();

        return graph;
    }


    return 0;
}
void DroneshareUploadDialog::uploadComplete(const QString& jsonResponse)
{
    QLOG_DEBUG() << "droneshare: upload success: " << jsonResponse;
    m_droneshareUpload->deleteLater();
    m_droneshareUpload = NULL;

    QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(jsonResponse);
    QScriptEngine engine;
    QScriptValue result = engine.evaluate("("+jsonResponse+")");

    if (engine.hasUncaughtException()){
        QLOG_ERROR() << "Error evaluating version object";
        QLOG_ERROR() << "Error @line#" << engine.uncaughtExceptionLineNumber();
        QLOG_ERROR() << "Backtrace:" << engine.uncaughtExceptionBacktrace();
        QLOG_ERROR() << "Syntax Check:" << syntaxCheck.errorMessage();
        QLOG_ERROR() << "Syntax Check line:" << syntaxCheck.errorLineNumber()
                     << " col:" << syntaxCheck.errorColumnNumber();
        return;
    }

    QString viewURL = result.property(0).property("viewURL").toString();
    ui->statusLabel->setOpenExternalLinks(true);
    ui->statusLabel->setText(tr("<html><head/><body><p>Upload Suceeded!<br><a href=\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">Click to view on Droneshare</span></a></p></body></html>").arg(viewURL));
}
void DroneshareUploadDialog::uploadFailed(const QString& jsonResponse, const QString& errorString)
{
    QLOG_DEBUG() << "droneshare: upload failed: " << errorString
                    << "JSON response:" << jsonResponse;
    m_droneshareUpload->deleteLater();
    m_droneshareUpload = NULL;

    QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(jsonResponse);
    QScriptEngine engine;
    QScriptValue result = engine.evaluate("("+jsonResponse+")");

    if (engine.hasUncaughtException()){
        QLOG_ERROR() << "Error evaluating version object";
        QLOG_ERROR() << "Error @line#" << engine.uncaughtExceptionLineNumber();
        QLOG_ERROR() << "Backtrace:" << engine.uncaughtExceptionBacktrace();
        QLOG_ERROR() << "Syntax Check:" << syntaxCheck.errorMessage();
        QLOG_ERROR() << "Syntax Check line:" << syntaxCheck.errorLineNumber()
                     << " col:" << syntaxCheck.errorColumnNumber();
        return;
    }

    QString message = result.property("message").toString();
    ui->statusLabel->setText(tr("Upload Failed!\n%1").arg(message));
}
Example #5
0
void ScriptableWorker::run()
{
    if ( hasLogLevel(LogDebug) ) {
        bool isEval = m_args.length() == Arguments::Rest + 2
                && m_args.at(Arguments::Rest) == "eval";

        for (int i = Arguments::Rest + (isEval ? 1 : 0); i < m_args.length(); ++i) {
            QString indent = isEval ? QString("EVAL:")
                                    : (QString::number(i - Arguments::Rest + 1) + " ");
            foreach (const QByteArray &line, m_args.at(i).split('\n')) {
                SCRIPT_LOG( indent + getTextData(line) );
                indent = "  ";
            }
        }
    }

    bool hasData;
    const quintptr id = m_args.at(Arguments::ActionId).toULongLong(&hasData);
    QVariantMap data;
    if (hasData)
        data = Action::data(id);

    const QString currentPath = getTextData(m_args.at(Arguments::CurrentPath));

    QScriptEngine engine;
    ScriptableProxy proxy(m_wnd, data);
    Scriptable scriptable(&proxy);
    scriptable.initEngine(&engine, currentPath, data);

    if (m_socket) {
        QObject::connect( proxy.signaler(), SIGNAL(sendMessage(QByteArray,int)),
                          m_socket, SLOT(sendMessage(QByteArray,int)) );

        QObject::connect( &scriptable, SIGNAL(sendMessage(QByteArray,int)),
                          m_socket, SLOT(sendMessage(QByteArray,int)) );
        QObject::connect( m_socket, SIGNAL(messageReceived(QByteArray,int)),
                          &scriptable, SLOT(setInput(QByteArray)) );

        QObject::connect( m_socket, SIGNAL(disconnected()),
                          &scriptable, SLOT(abort()) );
        QObject::connect( &scriptable, SIGNAL(destroyed()),
                          m_socket, SLOT(deleteAfterDisconnected()) );

        if ( m_socket->isClosed() ) {
            SCRIPT_LOG("TERMINATED");
            return;
        }

        m_socket->start();
    }

    QObject::connect( &scriptable, SIGNAL(requestApplicationQuit()),
                      qApp, SLOT(quit()) );

    QByteArray response;
    int exitCode;

    if ( m_args.length() <= Arguments::Rest ) {
        SCRIPT_LOG("Error: bad command syntax");
        exitCode = CommandBadSyntax;
    } else {
        const QString cmd = getTextData( m_args.at(Arguments::Rest) );

#ifdef HAS_TESTS
        if ( cmd == "flush" && m_args.length() == Arguments::Rest + 2 ) {
            log( "flush ID: " + getTextData(m_args.at(Arguments::Rest + 1)), LogAlways );
            scriptable.sendMessageToClient(QByteArray(), CommandFinished);
            return;
        }
#endif

        QScriptValue fn = engine.globalObject().property(cmd);
        if ( !fn.isFunction() ) {
            SCRIPT_LOG("Error: unknown command");
            const QString msg =
                    Scriptable::tr("Name \"%1\" doesn't refer to a function.").arg(cmd);
            response = createLogMessage(msg, LogError).toUtf8();
            exitCode = CommandError;
        } else {
            /* Special arguments:
             * "-"  read this argument from stdin
             * "--" read all following arguments without control sequences
             */
            QScriptValueList fnArgs;
            bool readRaw = false;
            for ( int i = Arguments::Rest + 1; i < m_args.length(); ++i ) {
                const QByteArray &arg = m_args.at(i);
                if (!readRaw && arg == "--") {
                    readRaw = true;
                } else {
                    const QScriptValue value = readRaw || arg != "-"
                            ? scriptable.newByteArray(arg)
                            : scriptable.input();
                    fnArgs.append(value);
                }
            }

            engine.evaluate(m_pluginScript);
            QScriptValue result = fn.call(QScriptValue(), fnArgs);

            if ( engine.hasUncaughtException() ) {
                const QString exceptionText =
                        QString("%1\n--- backtrace ---\n%2\n--- end backtrace ---")
                        .arg( engine.uncaughtException().toString(),
                              engine.uncaughtExceptionBacktrace().join("\n") );

                SCRIPT_LOG( QString("Error: Exception in command \"%1\": %2")
                             .arg(cmd, exceptionText) );

                response = createLogMessage(exceptionText, LogError).toUtf8();
                exitCode = CommandError;
            } else {
                response = serializeScriptValue(result);
                exitCode = CommandFinished;
            }
        }
    }

    if (exitCode == CommandFinished && hasData)
        Action::setData(id, scriptable.data());

    scriptable.sendMessageToClient(response, exitCode);

    SCRIPT_LOG("DONE");
}
NResponse & NTcpServerSocketUserServices::postUser(const NClientSession & session, NResponse & response)
{
    QScriptEngine se;
    QScriptValue svRoot = se.newObject();

    se.evaluate("var data = " + QString::fromUtf8(session.content()));
    if (se.hasUncaughtException()){
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_JSON));
        logDebug("NTcpServerSocketUserServices::svcPostUser", se.uncaughtExceptionBacktrace());
        logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    QScriptValue svReadUser = se.globalObject().property("data").property("data");
    QString email = svReadUser.property("email").toString();
    QString name = svReadUser.property("name").toString();
    QString password = getConfig().toPasswordHash(svReadUser.property("password").toString());
    QString preferences = svReadUser.property("preferences").toString();
    QString enabled = svReadUser.property("enabled").toString();
    QString level = NTcpServerAuthSession::normalizeLevels(svReadUser.property("level").toString());

    logDebug("email", email);
    logDebug("name", name);
    logDebug("password", password);
    logDebug("preferences", preferences);
    logDebug("enabled", enabled);
    logDebug("level", level);

    // User already exists?
    NStringMap user = NDB.getUserByEmail(email);

    if (user.count() > 0) // User already exists
    {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, "User already exists");
        logMessage("Registration failed", QString("already registered; %1(%2); user agent: %3").
              arg(email).
              arg(session.peerAddress()).
              arg(session.userAgent()));

        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    // User do not exists
    int userId = NDB.addUser(name, email, password, level, preferences, QVariant(enabled).toBool());
    if (userId < 0) // Error
    {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        QString errorMsg;
        switch(userId){
        case DB_USER_ERROR_INVALID_PARAMS:
            errorMsg = "Invalid params";
            break;
        case  DB_USER_ERROR_QUERY:
            errorMsg = "Query error";
            break;
        }
        svRoot.setProperty(RSP_MSG, errorMsg);
        logMessage("User add failed", QString("%1; %2(%3); user agent: %4").
              arg(errorMsg).
              arg(email).
              arg(session.peerAddress()).
              arg(session.userAgent()));

        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    svRoot.setProperty(RSP_SUCCESS , QScriptValue(true));
    svRoot.setProperty(RSP_MSG, QString("User %1 added").arg(email));
    logMessage("User add succeed", QString("%1, %2(%3); user agent: %4").
               arg(userId).
               arg(email).
               arg(session.peerAddress()).
               arg(session.userAgent()));

    // We add new user to response
    QScriptValue svData = se.newArray(1);
    svRoot.setProperty(RSP_DATA, svData);
    QScriptValue svUser = se.newObject();
    svData.setProperty(0, svUser);
    svUser.setProperty("id", userId);
    svUser.setProperty("name", name);
    svUser.setProperty("email", email);
    svUser.setProperty("preferences", preferences);
    svUser.setProperty("enabled", QVariant(enabled).toBool());
    svUser.setProperty("level", level);

    response.setData(NJson::serializeToQByteArray(svRoot));
    return response;
}
NResponse & NTcpServerSocketUserServices::putUser(const NClientSession & session, NResponse & response)
{
    QScriptEngine se;
    QScriptValue svRoot = se.newObject();

    QString strId = session.resource();
    logDebug("svcPutUser strId", strId);
    bool ok;
    int id = strId.toInt(&ok);
    if (!ok)
    {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_USER));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    se.evaluate("var data = " + QString::fromUtf8(session.content()));
    if (se.hasUncaughtException()){
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_JSON));
        logDebug("NTcpServerSocketUserServices::svcPutUser", se.uncaughtExceptionBacktrace());
        logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    NStringMap user = NDB.getUserById(id);
    if (user.count()  == 0)
    {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_USER));
        //logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    QScriptValue svReadUser = se.globalObject().property("data").property("data");
    QString email = svReadUser.property("email").toString();
    QString password = getConfig().toPasswordHash(svReadUser.property("password").toString());
    QString name = svReadUser.property("name").toString();
    QString preferences = svReadUser.property("preferences").toString();
    QString enabled = svReadUser.property("enabled").toString();
    QString level = NTcpServerAuthSession::normalizeLevels(svReadUser.property("level").toString());

    email = email.isEmpty() ? user["email"] : email;
    password = password.isEmpty() ? user["password"] : password;
    name = name.isEmpty() ? user["name"] : name;
    preferences = preferences.isEmpty() ? user["preferences"] : preferences;
    enabled = enabled.isEmpty() ? user["enabled"] : enabled;
    level = level.isEmpty() ? user["level"] : level;

    logDebug("email", email);
    logDebug("password", password);
    logDebug("name", name);
    logDebug("preferences", preferences);
    logDebug("enabled", enabled);
    logDebug("level", level);

    if (!NDB.updateUser(id, email, password, name, preferences,
                        QVariant(enabled).toBool(),level)) {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_ERROR_OCCURRED));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    logMessage("User update succeed", QString("%1, %2 (%3); user agent: %4").
               arg(id).
               arg(email).
               arg(session.peerAddress()).
               arg(session.userAgent()));

    svRoot.setProperty(RSP_SUCCESS , QScriptValue(true));
    svRoot.setProperty(RSP_MSG, QScriptValue(QString(RSP_MSG_N_UPDATED).arg(id)));
    QScriptValue svData = se.newArray();
    svRoot.setProperty(RSP_DATA, svData);
    QScriptValue svUser = se.newObject();
    svData.setProperty(0, svUser);
    svUser.setProperty("id", id);
    svUser.setProperty("email", email);
    svUser.setProperty("name", name);
    svUser.setProperty("preferences", preferences);
    svUser.setProperty("enabled", QVariant(enabled).toBool());
    svUser.setProperty("level", level);

    response.setData(NJson::serializeToQByteArray(svRoot));
    return response;
}
Example #8
0
int main(int argc, char *argv[])
{
    QApplication *app;
    if (argc >= 2 && !qstrcmp(argv[1], "-tty")) {
        ++argv;
       --argc;
        app = new QApplication(argc, argv, QApplication::Tty);
    } else {
        app = new QApplication(argc, argv);
    }

    QScriptEngine *eng = new QScriptEngine();

    QScriptValue globalObject = eng->globalObject();

    globalObject.setProperty("load", eng->newFunction(loadScripts, /*length=*/1));

    {
        if (!globalObject.property("qt").isObject())
            globalObject.setProperty("qt", eng->newObject());            
        QScriptValue qscript = eng->newObject();
        qscript.setProperty("importExtension", eng->newFunction(importExtension));
        globalObject.property("qt").setProperty("script", qscript);
    }

    ByteArrayClass *byteArrayClass = new ByteArrayClass(eng);
    globalObject.setProperty("ByteArray", byteArrayClass->constructor());

    if (! *++argv) {
        interactive(eng);
        return EXIT_SUCCESS;
    }

    while (const char *arg = *argv++) {
        QString fn = QString::fromLocal8Bit(arg);

        if (fn == QLatin1String("-i")) {
            interactive(eng);
            break;
        }

        QString contents;
        int lineNumber = 1;

        if (fn == QLatin1String("-")) {
            QTextStream stream(stdin, QFile::ReadOnly);
            contents = stream.readAll();
        }

        else {
            QFile file(fn);

            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                contents = stream.readAll();
                file.close();

                // strip off #!/usr/bin/env qscript line
                if (contents.startsWith("#!")) {
                    contents.remove(0, contents.indexOf("\n"));
                    ++lineNumber;
                }
            }
        }

        if (contents.isEmpty())
            continue;

        QScriptValue r = eng->evaluate(contents, fn, lineNumber);
        if (eng->hasUncaughtException()) {
            QStringList backtrace = eng->uncaughtExceptionBacktrace();
            fprintf (stderr, "    %s\n%s\n\n", qPrintable(r.toString()),
                     qPrintable(backtrace.join("\n")));
            return EXIT_FAILURE;
        }
    }

    delete eng;
    delete app;

    return EXIT_SUCCESS;
}
NResponse & NTcpServerSocketCfgServices::putSharedDir(const NClientSession & session, NResponse & response)
{
    //logDebug("NTcpServerSocketCfgServices::svcPutSharedDir", session.postData());
    QScriptEngine se;
    QScriptValue svRoot = se.newObject();

    QString strId = session.resource();
    logDebug("svcPutSharedDir strId", strId);
    bool ok;
    int id = strId.toInt(&ok);
    if (!ok)
    {
        svRoot.setProperty(RSP_SUCCESS, QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_INDEX_PROPERTY));
        //logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    se.evaluate("var data = " + QString::fromUtf8(session.content()));
    if (se.hasUncaughtException()){
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_JSON));
        logDebug("NTcpServerSocketCfgServices::svcPutSharedDir", se.uncaughtExceptionBacktrace());
        logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    NDirList sharedDirs = getConfig().sharedDirectories();
    if (id >= sharedDirs.count())
    {
        svRoot.setProperty(RSP_SUCCESS , QScriptValue(false));
        svRoot.setProperty(RSP_MSG, QScriptValue(RSP_MSG_INVALID_INDEX));
        //logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
        response.setData(NJson::serializeToQByteArray(svRoot));
        return response;
    }

    QScriptValue svReadDir = se.globalObject().property("data").property("data");
    QString path = svReadDir.property("path").toString();
    QString recursive = svReadDir.property("recursive").toString();
    QString shared = svReadDir.property("shared").toString();

    logDebug("path", path);
    logDebug("recursive", recursive);
    logDebug("shared", shared);

    NDir dir = sharedDirs.at(id);
    NDir modifiedDir = NDir(path.isEmpty() ? dir.path() : path,
                            recursive.isEmpty() ? dir.recursive() : QVariant(recursive).toBool(),
                            shared.isEmpty() ? dir.shared() : QVariant(shared).toBool());

    modifiedDir = getConfig().modifySharedDirectory(id, modifiedDir);
    svRoot.setProperty(RSP_SUCCESS , QScriptValue(true));
    svRoot.setProperty(RSP_MSG, QScriptValue(QString(RSP_MSG_N_UPDATED).arg(id)));
    QScriptValue svData = se.newArray();
    svRoot.setProperty(RSP_DATA, svData);
    QScriptValue svDir = se.newObject();
    svData.setProperty(0, svDir);
    svDir.setProperty("id", id);
    svDir.setProperty("path", modifiedDir.path());
    svDir.setProperty("recursive", modifiedDir.recursive());
    svDir.setProperty("shared", modifiedDir.shared());
    svDir.setProperty("exists", modifiedDir.exists());
    //logDebug("NJson::serialize(svRoot)", NJson::serialize(svRoot));
    response.setData(NJson::serializeToQByteArray(svRoot));
    return response;
}
void tst_QScriptJSTestSuite::runTestFunction(int testIndex)
{
    if (!(testIndex & 1)) {
        // data
        QTest::addColumn<TestRecord>("record");
        bool hasData = false;

        QString testsShellPath = testsDir.absoluteFilePath("shell.js");
        QString testsShellContents = readFile(testsShellPath);

        QDir subSuiteDir(subSuitePaths.at(testIndex / 2));
        QString subSuiteShellPath = subSuiteDir.absoluteFilePath("shell.js");
        QString subSuiteShellContents = readFile(subSuiteShellPath);

        QDir testSuiteDir(subSuiteDir);
        testSuiteDir.cdUp();
        QString suiteJsrefPath = testSuiteDir.absoluteFilePath("jsref.js");
        QString suiteJsrefContents = readFile(suiteJsrefPath);
        QString suiteShellPath = testSuiteDir.absoluteFilePath("shell.js");
        QString suiteShellContents = readFile(suiteShellPath);

        QFileInfoList testFileInfos = subSuiteDir.entryInfoList(QStringList() << "*.js", QDir::Files);
        foreach (QFileInfo tfi, testFileInfos) {
            if ((tfi.fileName() == "shell.js") || (tfi.fileName() == "browser.js"))
                continue;

            QString abspath = tfi.absoluteFilePath();
            QString relpath = testsDir.relativeFilePath(abspath);
            QString excludeMessage;
            if (isExcludedFile(relpath, &excludeMessage)) {
                QTest::newRow(relpath.toLatin1()) << TestRecord(excludeMessage, relpath);
                continue;
            }

            QScriptEngine eng;
            QScriptValue global = eng.globalObject();
            global.setProperty("print", eng.newFunction(qscript_void));
            global.setProperty("quit", eng.newFunction(qscript_quit));
            global.setProperty("options", eng.newFunction(qscript_options));

            eng.evaluate(testsShellContents, testsShellPath);
            if (eng.hasUncaughtException()) {
                QStringList bt = eng.uncaughtExceptionBacktrace();
                QString err = eng.uncaughtException().toString();
                qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n")));
                break;
            }

            eng.evaluate(suiteJsrefContents, suiteJsrefPath);
            if (eng.hasUncaughtException()) {
                QStringList bt = eng.uncaughtExceptionBacktrace();
                QString err = eng.uncaughtException().toString();
                qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n")));
                break;
            }

            eng.evaluate(suiteShellContents, suiteShellPath);
            if (eng.hasUncaughtException()) {
                QStringList bt = eng.uncaughtExceptionBacktrace();
                QString err = eng.uncaughtException().toString();
                qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n")));
                break;
            }

            eng.evaluate(subSuiteShellContents, subSuiteShellPath);
            if (eng.hasUncaughtException()) {
                QStringList bt = eng.uncaughtExceptionBacktrace();
                QString err = eng.uncaughtException().toString();
                qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n")));
                break;
            }

            QScriptValue origTestCaseCtor = global.property("TestCase");
            QScriptValue myTestCaseCtor = eng.newFunction(qscript_TestCase);
            myTestCaseCtor.setData(origTestCaseCtor);
            global.setProperty("TestCase", myTestCaseCtor);

            global.setProperty("gTestfile", tfi.fileName());
            global.setProperty("gTestsuite", testSuiteDir.dirName());
            global.setProperty("gTestsubsuite", subSuiteDir.dirName());
            QString testFileContents = readFile(abspath);
//                qDebug() << relpath;
            eng.evaluate(testFileContents, abspath);
            if (eng.hasUncaughtException() && !relpath.endsWith("-n.js")) {
                QStringList bt = eng.uncaughtExceptionBacktrace();
                QString err = eng.uncaughtException().toString();
                qWarning("%s\n%s\n", qPrintable(err), qPrintable(bt.join("\n")));
                continue;
            }

            QScriptValue testcases = global.property("testcases");
            if (!testcases.isArray())
                testcases = global.property("gTestcases");
            int count = testcases.property("length").toInt32();
            if (count == 0)
                continue;

            hasData = true;
            QString title = global.property("TITLE").toString();
            for (int i = 0; i < count; ++i) {
                QScriptValue kase = testcases.property(i);
                QString description = kase.property("description").toString();
                QScriptValue expect = kase.property("expect");
                QScriptValue actual = kase.property("actual");
                bool passed = kase.property("passed").toBoolean();
                int lineNumber = kase.property("__lineNumber__").toInt32();

                TestRecord rec(description, passed,
                               actual.toString(), expect.toString(),
                               relpath, lineNumber);

                QTest::newRow(description.toLatin1()) << rec;
            }
        }
        if (!hasData)
            QTest::newRow("") << TestRecord(); // dummy
    } else {