Files
qt-creator/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
Jarek Kobus 866a658b42 Get rid of unneeded includes of RunControl
Removed also some other includes that were marked
with yellow triangles. In some cases includes of
runcontrol.h were substituted with other includes,
like qtcassert.h.

Change-Id: Ica40f68198c7f8f70e6047acb2eddc8ef017e43d
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
2022-10-25 09:49:13 +00:00

424 lines
14 KiB
C++

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "qmlprofilerclientmanager_test.h"
#include "fakedebugserver.h"
#include <utils/url.h>
#include <QTcpServer>
#include <QTcpSocket>
#include <QLocalSocket>
#include <QQmlDebuggingEnabler>
#include <QtTest>
using namespace ProjectExplorer;
namespace QmlProfiler {
namespace Internal {
struct MessageHandler {
MessageHandler(QtMessageHandler handler)
{
defaultHandler = qInstallMessageHandler(handler);
}
~MessageHandler()
{
qInstallMessageHandler(defaultHandler);
}
static QtMessageHandler defaultHandler;
};
QtMessageHandler MessageHandler::defaultHandler;
QmlProfilerClientManagerTest::QmlProfilerClientManagerTest(QObject *parent) :
QObject(parent), modelManager(nullptr)
{
clientManager.setRetryInterval(10);
clientManager.setMaximumRetries(10);
}
void QmlProfilerClientManagerTest::testConnectionFailure_data()
{
QTest::addColumn<QmlProfilerModelManager *>("modelManager");
QVarLengthArray<QmlProfilerModelManager *> modelManagers({nullptr, &modelManager});
QTest::addColumn<QmlProfilerStateManager *>("stateManager");
QVarLengthArray<QmlProfilerStateManager *> stateManagers({nullptr, &stateManager});
QUrl localUrl = Utils::urlFromLocalHostAndFreePort();
QTest::addColumn<QUrl>("serverUrl");
const QVarLengthArray<QString> hosts({"", "/-/|\\-\\|/-", localUrl.host()});
const QVarLengthArray<int> ports({-1, 5, localUrl.port()});
const QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-",
Utils::urlFromLocalSocket().path()});
const QVarLengthArray<QString> schemes({"", Utils::urlSocketScheme(),
Utils::urlTcpScheme()});
for (QmlProfilerModelManager *modelManager : modelManagers) {
for (QmlProfilerStateManager *stateManager : stateManagers) {
for (const QString &host : hosts) {
for (int port : ports) {
for (const QString &socket : sockets) {
for (const QString &scheme : schemes ) {
QUrl url;
url.setScheme(scheme);
url.setHost(host);
url.setPort(port);
url.setPath(socket);
QString tag = QString::fromLatin1("%1, %2, %3")
.arg(QLatin1String(modelManager ? "modelManager" : "<null>"))
.arg(QLatin1String(stateManager ? "stateManager" : "<null>"))
.arg(url.toString());
QTest::newRow(tag.toLatin1().constData()) << modelManager
<< stateManager << url;
}
}
}
}
}
}
}
void softAssertMessageHandler(QtMsgType type, const QMessageLogContext &context,
const QString &message)
{
if (type != QtDebugMsg || !message.startsWith("SOFT ASSERT: "))
MessageHandler::defaultHandler(type, context, message);
}
void QmlProfilerClientManagerTest::testConnectionFailure()
{
clientManager.setRetryInterval(1);
clientManager.setMaximumRetries(2);
// This triggers a lot of soft asserts. We test that it still doesn't crash and stays in a
// consistent state.
QByteArray fatalAsserts = qgetenv("QTC_FATAL_ASSERTS");
qunsetenv("QTC_FATAL_ASSERTS");
MessageHandler handler(&softAssertMessageHandler);
Q_UNUSED(handler)
QFETCH(QmlProfilerModelManager *, modelManager);
QFETCH(QmlProfilerStateManager *, stateManager);
QFETCH(QUrl, serverUrl);
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QSignalSpy failedSpy(&clientManager, SIGNAL(connectionFailed()));
QVERIFY(!clientManager.isConnected());
clientManager.setModelManager(modelManager);
clientManager.setProfilerStateManager(stateManager);
QVERIFY(!clientManager.isConnected());
clientManager.connectToServer(serverUrl);
QTRY_COMPARE(failedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
QCOMPARE(openedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
clientManager.retryConnect();
QTRY_COMPARE(failedSpy.count(), 2);
QCOMPARE(closedSpy.count(), 0);
QCOMPARE(openedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
clientManager.disconnectFromServer();
qputenv("QTC_FATAL_ASSERTS", fatalAsserts);
clientManager.setRetryInterval(10);
clientManager.setMaximumRetries(10);
}
void QmlProfilerClientManagerTest::testUnresponsiveTcp()
{
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QSignalSpy failedSpy(&clientManager, SIGNAL(connectionFailed()));
QVERIFY(!clientManager.isConnected());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl serverUrl = Utils::urlFromLocalHostAndFreePort();
QTcpServer server;
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
QSignalSpy connectionSpy(&server, SIGNAL(newConnection()));
clientManager.connectToServer(serverUrl);
QTRY_VERIFY(connectionSpy.count() > 0);
QTRY_COMPARE(failedSpy.count(), 1);
QCOMPARE(openedSpy.count(), 0);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
clientManager.disconnectFromServer();
}
void QmlProfilerClientManagerTest::testUnresponsiveLocal()
{
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QSignalSpy failedSpy(&clientManager, SIGNAL(connectionFailed()));
QVERIFY(!clientManager.isConnected());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl socketUrl = Utils::urlFromLocalSocket();
QLocalSocket socket;
QSignalSpy connectionSpy(&socket, SIGNAL(connected()));
clientManager.connectToServer(socketUrl);
socket.connectToServer(socketUrl.path());
QTRY_COMPARE(connectionSpy.count(), 1);
QTRY_COMPARE(failedSpy.count(), 1);
QCOMPARE(openedSpy.count(), 0);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
clientManager.disconnectFromServer();
}
void responsiveTestData()
{
QTest::addColumn<quint32>("flushInterval");
QTest::newRow("no flush") << 0u;
QTest::newRow("flush") << 1u;
}
void QmlProfilerClientManagerTest::testResponsiveTcp_data()
{
responsiveTestData();
}
void QmlProfilerClientManagerTest::testResponsiveTcp()
{
QFETCH(quint32, flushInterval);
QUrl serverUrl = Utils::urlFromLocalHostAndFreePort();
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QVERIFY(!clientManager.isConnected());
{
QTcpServer server;
QScopedPointer<QTcpSocket> socket;
connect(&server, &QTcpServer::newConnection, [&server, &socket]() {
socket.reset(server.nextPendingConnection());
fakeDebugServer(socket.data());
});
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
clientManager.setFlushInterval(flushInterval);
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
clientManager.connectToServer(serverUrl);
QTRY_COMPARE(openedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(clientManager.isConnected());
// Do some nasty things and make sure it doesn't crash
stateManager.setCurrentState(QmlProfilerStateManager::AppRunning);
stateManager.setClientRecording(false);
stateManager.setClientRecording(true);
clientManager.clearBufferedData();
stateManager.setCurrentState(QmlProfilerStateManager::AppStopRequested);
QVERIFY(socket);
}
QTRY_COMPARE(closedSpy.count(), 1);
QVERIFY(!clientManager.isConnected());
disconnect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
stateManager.setCurrentState(QmlProfilerStateManager::Idle);
}
void QmlProfilerClientManagerTest::testResponsiveLocal_data()
{
responsiveTestData();
}
void QmlProfilerClientManagerTest::testResponsiveLocal()
{
QFETCH(quint32, flushInterval);
QUrl socketUrl = Utils::urlFromLocalSocket();
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QVERIFY(!clientManager.isConnected());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
clientManager.setFlushInterval(flushInterval);
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
clientManager.connectToServer(socketUrl);
{
QScopedPointer<QLocalSocket> socket(new QLocalSocket(this));
socket->connectToServer(socketUrl.path());
QVERIFY(socket->isOpen());
fakeDebugServer(socket.data());
QTRY_COMPARE(openedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(clientManager.isConnected());
// Do some nasty things and make sure it doesn't crash
stateManager.setCurrentState(QmlProfilerStateManager::AppRunning);
stateManager.setClientRecording(false);
stateManager.setClientRecording(true);
clientManager.clearBufferedData();
stateManager.setCurrentState(QmlProfilerStateManager::AppStopRequested);
}
QTRY_COMPARE(closedSpy.count(), 1);
QVERIFY(!clientManager.isConnected());
disconnect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
stateManager.setCurrentState(QmlProfilerStateManager::Idle);
}
void invalidHelloMessageHandler(QtMsgType type, const QMessageLogContext &context,
const QString &message)
{
if (type != QtWarningMsg || message != "QML Debug Client: Invalid hello message")
MessageHandler::defaultHandler(type, context, message);
}
void QmlProfilerClientManagerTest::testInvalidData()
{
MessageHandler handler(&invalidHelloMessageHandler);
Q_UNUSED(handler)
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QSignalSpy failedSpy(&clientManager, SIGNAL(connectionFailed()));
QVERIFY(!clientManager.isConnected());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl serverUrl = Utils::urlFromLocalHostAndFreePort();
bool dataSent = false;
QTcpServer server;
connect(&server, &QTcpServer::newConnection, [&server, &dataSent](){
QTcpSocket *socket = server.nextPendingConnection();
// emulate packet protocol
qint32 sendSize32 = 10;
socket->write((char *)&sendSize32, sizeof(qint32));
socket->write("----------------------- x -----------------------");
dataSent = true;
});
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
clientManager.connectToServer(serverUrl);
QTRY_VERIFY(dataSent);
QTRY_COMPARE(failedSpy.count(), 1);
QCOMPARE(openedSpy.count(), 0);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
clientManager.disconnectFromServer();
}
void QmlProfilerClientManagerTest::testStopRecording()
{
QUrl socketUrl = Utils::urlFromLocalSocket();
{
QmlProfilerClientManager clientManager;
clientManager.setRetryInterval(10);
clientManager.setMaximumRetries(10);
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
QVERIFY(!clientManager.isConnected());
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
clientManager.connectToServer(socketUrl);
QScopedPointer<QLocalSocket> socket(new QLocalSocket(this));
socket->connectToServer(socketUrl.path());
QVERIFY(socket->isOpen());
fakeDebugServer(socket.data());
QTRY_COMPARE(openedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
QVERIFY(clientManager.isConnected());
// We can't verify that it does anything useful, but at least it doesn't crash
clientManager.stopRecording();
}
// Delete while still connected, for added fun
}
void QmlProfilerClientManagerTest::testConnectionDrop()
{
QUrl socketUrl = Utils::urlFromLocalSocket();
QmlProfilerClientManager clientManager;
{
clientManager.setRetryInterval(10);
clientManager.setMaximumRetries(10);
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
clientManager.connectToServer(socketUrl);
QScopedPointer<QLocalSocket> socket(new QLocalSocket(this));
socket->connectToServer(socketUrl.path());
QVERIFY(socket->isOpen());
fakeDebugServer(socket.data());
// Fake a trace. We want to test that this is reset when the connection drops.
stateManager.setServerRecording(true);
QTRY_VERIFY(clientManager.isConnected());
}
QTRY_VERIFY(!stateManager.serverRecording());
}
} // namespace Internal
} // namespace QmlProfiler