From c54a2dca1697974e85cc42b86fa2e1a7f50bde8e Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 16 Oct 2012 10:34:44 +0200 Subject: [PATCH] tst_qlocalsocket: get rid of QtScript dependency Removing the lackey executable that needs QtScript to be built. This was a qscript bastard that was able to run a client and a server script. It's replaced by a C++ version with the same functionality. Nice side effect: the two second wait per test row could be removed. The client executable is now waiting for the server to be created. Task-number: QTBUG-24142 Change-Id: I135b75abf6620d3b0af50dc226ea8c81c2bf4149 Reviewed-by: Friedemann Kleint Reviewed-by: Rohan McGovern --- tests/auto/network/socket/qlocalsocket/.gitignore | 1 - .../network/socket/qlocalsocket/lackey/lackey.pro | 15 -- .../network/socket/qlocalsocket/lackey/main.cpp | 296 --------------------- .../socket/qlocalsocket/lackey/scripts/client.js | 35 --- .../socket/qlocalsocket/lackey/scripts/server.js | 19 -- .../network/socket/qlocalsocket/qlocalsocket.pro | 2 +- .../socket/qlocalsocket/socketprocess/main.cpp | 150 +++++++++++ .../qlocalsocket/socketprocess/socketprocess.pro | 9 + .../socket/qlocalsocket/tst_qlocalsocket.cpp | 54 ++-- 9 files changed, 197 insertions(+), 384 deletions(-) delete mode 100644 tests/auto/network/socket/qlocalsocket/lackey/lackey.pro delete mode 100644 tests/auto/network/socket/qlocalsocket/lackey/main.cpp delete mode 100755 tests/auto/network/socket/qlocalsocket/lackey/scripts/client.js delete mode 100644 tests/auto/network/socket/qlocalsocket/lackey/scripts/server.js create mode 100644 tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp create mode 100644 tests/auto/network/socket/qlocalsocket/socketprocess/socketprocess.pro diff --git a/tests/auto/network/socket/qlocalsocket/.gitignore b/tests/auto/network/socket/qlocalsocket/.gitignore index b45c266..e82f118 100644 --- a/tests/auto/network/socket/qlocalsocket/.gitignore +++ b/tests/auto/network/socket/qlocalsocket/.gitignore @@ -1,2 +1 @@ tst_qlocalsocket -lackey/lackey.exe diff --git a/tests/auto/network/socket/qlocalsocket/lackey/lackey.pro b/tests/auto/network/socket/qlocalsocket/lackey/lackey.pro deleted file mode 100644 index 6e69732..0000000 --- a/tests/auto/network/socket/qlocalsocket/lackey/lackey.pro +++ /dev/null @@ -1,15 +0,0 @@ -#include(../src/src.pri) - -QT = core script network testlib - -DESTDIR = ./ - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -DEFINES += QLOCALSERVER_DEBUG -DEFINES += QLOCALSOCKET_DEBUG - -SOURCES += main.cpp -TARGET = lackey -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qlocalsocket/lackey/main.cpp b/tests/auto/network/socket/qlocalsocket/lackey/main.cpp deleted file mode 100644 index 112bf05..0000000 --- a/tests/auto/network/socket/qlocalsocket/lackey/main.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include - #include -#include - -#include -#include - -class QScriptLocalSocket : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString serverName WRITE connectToServer READ serverName) - -public: - QScriptLocalSocket(QObject *parent = 0) : QObject(parent) - { - lc = new QLocalSocket(this); - } - -public slots: - QString serverName() - { - return lc->serverName(); - } - - void connectToServer(const QString &name) { - lc->connectToServer(name); - } - - void sleep(int x) const - { - QTest::qSleep(x); - } - - bool isConnected() { - return (lc->state() == QLocalSocket::ConnectedState); - } - - void open() { - lc->open(QIODevice::ReadWrite); - } - - bool waitForConnected() { - return lc->waitForConnected(100000); - } - void waitForReadyRead() { - lc->waitForReadyRead(); - } - - void write(const QString &string) { - QTextStream out(lc); - out << string << endl; - } - - bool waitForBytesWritten(int t = 3000) { - return lc->waitForBytesWritten(t); - } - - QString readLine() { - QTextStream in(lc); - return in.readLine(); - } - - QString errorString() { - return lc->errorString(); - } - - void close() { - lc->close(); - } - -public: - QLocalSocket *lc; -}; - -class QScriptLocalServer : public QLocalServer -{ - Q_OBJECT - Q_PROPERTY(int maxPendingConnections WRITE setMaxPendingConnections READ maxPendingConnections) - Q_PROPERTY(QString name WRITE listen READ serverName) - Q_PROPERTY(bool listening READ isListening) - -public: - QScriptLocalServer(QObject *parent = 0) : QLocalServer(parent) - { - } - -public slots: - bool listen(const QString &name) { - if (!QLocalServer::listen(name)) { - if (serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(serverName()); - return QLocalServer::listen(name); - } - return false; - } - return true; - } - - QScriptLocalSocket *nextConnection() { - QLocalSocket *other = nextPendingConnection(); - QScriptLocalSocket *s = new QScriptLocalSocket(this); - delete s->lc; - s->lc = other; - return s; - } - - bool waitForNewConnection() { - return QLocalServer::waitForNewConnection(30000); - } - - QString errorString() { - return QLocalServer::errorString(); - } - - -}; - -template -static QScriptValue _q_ScriptValueFromQObject(QScriptEngine *engine, T* const &in) -{ - return engine->newQObject(in); -} -template -static void _q_ScriptValueToQObject(const QScriptValue &v, T* &out) -{ out = qobject_cast(v.toQObject()); -} -template -static int _q_ScriptRegisterQObjectMetaType(QScriptEngine *engine, const QScriptValue &prototype) -{ - return qScriptRegisterMetaType(engine, _q_ScriptValueFromQObject, _q_ScriptValueToQObject, prototype); -} - -QT_BEGIN_NAMESPACE -Q_SCRIPT_DECLARE_QMETAOBJECT(QScriptLocalSocket, QObject*); -Q_SCRIPT_DECLARE_QMETAOBJECT(QScriptLocalServer, QObject*); -QT_END_NAMESPACE - -static void interactive(QScriptEngine &eng) -{ - QTextStream qin(stdin, QFile::ReadOnly); - - const char *qscript_prompt = "qs> "; - const char *dot_prompt = ".... "; - const char *prompt = qscript_prompt; - - QString code; - - forever { - QString line; - - printf("%s", prompt); - fflush(stdout); - - line = qin.readLine(); - if (line.isNull()) - break; - - code += line; - code += QLatin1Char('\n'); - - if (line.trimmed().isEmpty()) { - continue; - - } else if (! eng.canEvaluate(code)) { - prompt = dot_prompt; - - } else { - QScriptValue result = eng.evaluate(code); - code.clear(); - prompt = qscript_prompt; - if (!result.isUndefined()) - fprintf(stderr, "%s\n", qPrintable(result.toString())); - } - } -} -Q_DECLARE_METATYPE(QScriptLocalSocket*) -Q_DECLARE_METATYPE(QScriptLocalServer*) -int main(int argc, char *argv[]) -{ - QCoreApplication app(argc, argv); - QScriptEngine eng; - QScriptValue globalObject = eng.globalObject(); - - _q_ScriptRegisterQObjectMetaType(&eng, QScriptValue()); - - QScriptValue lss = qScriptValueFromQMetaObject(&eng); - eng.globalObject().setProperty("QScriptLocalServer", lss); - - _q_ScriptRegisterQObjectMetaType(&eng, QScriptValue()); - - QScriptValue lsc = qScriptValueFromQMetaObject(&eng); - eng.globalObject().setProperty("QScriptLocalSocket", lsc); - - if (! *++argv) { - interactive(eng); - return EXIT_SUCCESS; - } - - QStringList arguments; - for (int i = 0; i < argc - 1; ++i) - arguments << QString::fromLocal8Bit(argv[i]); - - while (!arguments.isEmpty()) { - QString fn = arguments.takeFirst(); - - if (fn == QLatin1String("-i")) { - interactive(eng); - break; - } - - QString contents; - - if (fn == QLatin1String("-")) { - QTextStream stream(stdin, QFile::ReadOnly); - contents = stream.readAll(); - } else { - QFile file(fn); - if (!file.exists()) { - fprintf(stderr, "%s doesn't exists\n", qPrintable(fn)); - return EXIT_FAILURE; - } - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - contents = stream.readAll(); - file.close(); - } - } - - if (contents.isEmpty()) - continue; - - if (contents[0] == '#') { - contents.prepend("//"); - QScriptValue args = eng.newArray(); - args.setProperty("0", QScriptValue(&eng, fn)); - int i = 1; - while (!arguments.isEmpty()) - args.setProperty(i++, QScriptValue(&eng, arguments.takeFirst())); - eng.currentContext()->activationObject().setProperty("args", args); - } - QScriptValue r = eng.evaluate(contents); - if (eng.hasUncaughtException()) { - int line = eng.uncaughtExceptionLineNumber(); - fprintf(stderr, "%d: %s\n\t%s\n\n", line, qPrintable(fn), qPrintable(r.toString())); - return EXIT_FAILURE; - } - if (r.isNumber()) - return r.toInt32(); - } - - return EXIT_SUCCESS; -} - -#include "main.moc" diff --git a/tests/auto/network/socket/qlocalsocket/lackey/scripts/client.js b/tests/auto/network/socket/qlocalsocket/lackey/scripts/client.js deleted file mode 100755 index 76cc0b9..0000000 --- a/tests/auto/network/socket/qlocalsocket/lackey/scripts/client.js +++ /dev/null @@ -1,35 +0,0 @@ -#/bin/qscript -function QVERIFY(x, socket) { - if (!(x)) { - throw(socket.errorString()); - } -} - -var socket = new QScriptLocalSocket; -var tries = 0; -do { - socket.serverName = "qlocalsocket_autotest"; - if ((socket.errorString() != "QLocalSocket::connectToServer: Invalid name") - && (socket.errorString() != "QLocalSocket::connectToServer: Connection refused")) - break; - socket.sleep(1); - ++tries; - print("isConnected:", socket.isConnected()); -} while ((socket.errorString() == "QLocalSocket::connectToServer: Invalid name" - || (socket.errorString() == "QlocalSocket::connectToServer: Connection refused")) - && tries < 5000); -if (tries == 5000) { - print("too many tries, exiting"); -} else { -socket.waitForConnected(); -//print("isConnected:", socket.isConnected()); -if (!socket.isConnected()) - print("Not Connected:", socket.errorString()); -socket.waitForReadyRead(); -var text = socket.readLine(); -var testLine = "test"; -QVERIFY((text == testLine), socket); -QVERIFY((socket.errorString() == "Unknown error"), socket); -socket.close(); -//print("client: exiting", text); -} diff --git a/tests/auto/network/socket/qlocalsocket/lackey/scripts/server.js b/tests/auto/network/socket/qlocalsocket/lackey/scripts/server.js deleted file mode 100644 index 98a83bc..0000000 --- a/tests/auto/network/socket/qlocalsocket/lackey/scripts/server.js +++ /dev/null @@ -1,19 +0,0 @@ -#/bin/qscript -function QVERIFY(x, server) { - if (!(x)) { - throw(server.errorString()); - } -} -var server = new QScriptLocalServer; -QVERIFY(server.listen("qlocalsocket_autotest"), server); -var done = args[1]; -var testLine = "test"; -while (done > 0) { - QVERIFY(server.waitForNewConnection(), server); - var serverSocket = server.nextConnection(); - serverSocket.write(testLine); - QVERIFY(serverSocket.waitForBytesWritten(), serverSocket); - QVERIFY(serverSocket.errorString() == "" - ||serverSocket.errorString() == "Unknown error", serverSocket); - --done; -} diff --git a/tests/auto/network/socket/qlocalsocket/qlocalsocket.pro b/tests/auto/network/socket/qlocalsocket/qlocalsocket.pro index fb09dd6..cbf5d16 100644 --- a/tests/auto/network/socket/qlocalsocket/qlocalsocket.pro +++ b/tests/auto/network/socket/qlocalsocket/qlocalsocket.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = test # lackey should be moved to the QtScript module +SUBDIRS = test socketprocess diff --git a/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp new file mode 100644 index 0000000..de78f9a --- /dev/null +++ b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include + +const QString serverName = QStringLiteral("qlocalsocket_autotest"); +const QByteArray testData("test"); +QSystemSemaphore *semaphore = 0; + +bool runServer(int numberOfConnections) +{ + QLocalServer *server = new QLocalServer(qApp); + if (!server->removeServer(serverName)) { + fprintf(stderr, "server: cannot remove server: %s\n", qPrintable(server->errorString())); + return false; + } + printf("server: listen on \"%s\"\n", qPrintable(serverName)); + if (!server->listen(serverName)) { + fprintf(stderr, "server: listen failed: %s\n", qPrintable(server->errorString())); + return false; + } + semaphore->release(); + for (int i = 1; i <= numberOfConnections; ++i) { + printf("server: wait for connection %d\n", i); + if (!server->waitForNewConnection(30000)) { + semaphore->acquire(); + fprintf(stderr, "server: waitForNewConnection failed: %s\n", + qPrintable(server->errorString())); + return false; + } + QLocalSocket *socket = server->nextPendingConnection(); + printf("server: writing \"%s\"\n", testData.data()); + socket->write(testData); + if (!socket->waitForBytesWritten()) { + semaphore->acquire(); + fprintf(stderr, "server: waitForBytesWritten failed: %s\n", + qPrintable(socket->errorString())); + return false; + } + printf("server: data written\n"); + if (socket->error() != QLocalSocket::UnknownSocketError) { + semaphore->acquire(); + fprintf(stderr, "server: socket error %d\n", socket->error()); + return false; + } + } + semaphore->acquire(); + return true; +} + +bool runClient() +{ + semaphore->acquire(); // wait until the server is up and running + semaphore->release(); + + QLocalSocket socket; + printf("client: connecting to \"%s\"\n", qPrintable(serverName)); + socket.connectToServer(serverName, QLocalSocket::ReadWrite); + if (!socket.waitForConnected()) { + fprintf(stderr, "client: waitForConnected failed: %s\n", + qPrintable(socket.errorString())); + return false; + } + printf("client: connected\n"); + if (!socket.waitForReadyRead()) { + fprintf(stderr, "client: waitForReadyRead failed: %s\n", + qPrintable(socket.errorString())); + return false; + } + printf("client: data is available for reading\n"); + const QByteArray data = socket.readLine(); + printf("client: received \"%s\"\n", data.data()); + if (data != testData) { + fprintf(stderr, "client: received unexpected data\n"); + return false; + } + return true; +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QSystemSemaphore s("tst_qlocalsocket_socketprocess"); + semaphore = &s; + if (argc < 2) + return EXIT_FAILURE; + if (strcmp(argv[1], "--server") == 0) { + if (argc < 3) { + fprintf(stderr, "--server needs the number of incoming connections\n"); + return EXIT_FAILURE; + } + bool ok; + int n = QByteArray(argv[2]).toInt(&ok); + if (!ok) { + fprintf(stderr, "Cannot convert %s to a number.\n", argv[2]); + return EXIT_FAILURE; + } + if (!runServer(n)) + return EXIT_FAILURE; + } else if (strcmp(argv[1], "--client") == 0) { + if (!runClient()) + return EXIT_FAILURE; + } else { + fprintf(stderr, "unknown command line option: %s\n", argv[1]); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/tests/auto/network/socket/qlocalsocket/socketprocess/socketprocess.pro b/tests/auto/network/socket/qlocalsocket/socketprocess/socketprocess.pro new file mode 100644 index 0000000..643c4c5 --- /dev/null +++ b/tests/auto/network/socket/qlocalsocket/socketprocess/socketprocess.pro @@ -0,0 +1,9 @@ +QT = core network testlib + +DESTDIR = ./ +TARGET = socketprocess + +win32:CONFIG += console +mac:CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 8bcb8cc..4f6fc46 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -735,53 +735,73 @@ void tst_QLocalSocket::processConnection_data() { QTest::addColumn("processes"); QTest::newRow("1 client") << 1; -#ifndef Q_OS_WIN QTest::newRow("2 clients") << 2; QTest::newRow("5 clients") << 5; -#endif QTest::newRow("30 clients") << 30; } +class ProcessOutputDumper +{ +public: + ProcessOutputDumper(QProcess *p = 0) + : process(p) + {} + + ~ProcessOutputDumper() + { + if (process) + fputs(process->readAll().data(), stdout); + } + + void clear() + { + process = 0; + } + +private: + QProcess *process; +}; + /*! Create external processes that produce and consume. */ void tst_QLocalSocket::processConnection() { #ifdef Q_OS_WIN -# define EXE_SUFFIX ".exe" + const QString exeSuffix = QStringLiteral(".exe"); #else -# define EXE_SUFFIX + const QString exeSuffix; #endif -// ### lackey is currently not build - QEXPECT_FAIL("", "lackey is currently not built due to qscript dependency, QTBUG-24142", Abort); - QVERIFY(QFile::exists("lackey/lackey" EXE_SUFFIX)); + QString socketProcess = QStringLiteral("socketprocess/socketprocess") + exeSuffix; + QVERIFY(QFile::exists(socketProcess)); QFETCH(int, processes); - QStringList serverArguments = QStringList() << SRCDIR "lackey/scripts/server.js" << QString::number(processes); + QStringList serverArguments = QStringList() << "--server" << QString::number(processes); QProcess producer; - producer.setProcessChannelMode(QProcess::ForwardedChannels); + ProcessOutputDumper producerOutputDumper(&producer); QList consumers; - producer.start("lackey/lackey", serverArguments); + producer.start(socketProcess, serverArguments); QVERIFY2(producer.waitForStarted(-1), qPrintable(producer.errorString())); - QTest::qWait(2000); for (int i = 0; i < processes; ++i) { - QStringList arguments = QStringList() << SRCDIR "lackey/scripts/client.js"; + QStringList arguments = QStringList() << "--client"; QProcess *p = new QProcess; - p->setProcessChannelMode(QProcess::ForwardedChannels); consumers.append(p); - p->start("lackey/lackey", arguments); + p->start(socketProcess, arguments); } while (!consumers.isEmpty()) { - consumers.first()->waitForFinished(20000); - QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit); - QCOMPARE(consumers.first()->exitCode(), 0); QProcess *consumer = consumers.takeFirst(); + ProcessOutputDumper consumerOutputDumper(consumer); + consumer->waitForFinished(20000); + QCOMPARE(consumer->exitStatus(), QProcess::NormalExit); + QCOMPARE(consumer->exitCode(), 0); + consumerOutputDumper.clear(); consumer->terminate(); delete consumer; } producer.waitForFinished(15000); + producerOutputDumper.clear(); } #endif -- 2.7.4