summaryrefslogtreecommitdiff
path: root/plugins/autotest/testsquishtools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/autotest/testsquishtools.cpp')
-rw-r--r--plugins/autotest/testsquishtools.cpp678
1 files changed, 678 insertions, 0 deletions
diff --git a/plugins/autotest/testsquishtools.cpp b/plugins/autotest/testsquishtools.cpp
new file mode 100644
index 0000000000..49739271ee
--- /dev/null
+++ b/plugins/autotest/testsquishtools.cpp
@@ -0,0 +1,678 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at
+** http://www.qt.io/contact-us
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://www.qt.io/contact-us
+**
+****************************************************************************/
+
+#include "autotestplugin.h"
+#include "squishsettings.h"
+#include "testsquishtools.h"
+#include "testresultspane.h"
+
+#include <QDebug> // TODO remove
+
+#include <coreplugin/icore.h>
+
+#include <utils/environment.h>
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+
+#include <QApplication>
+#include <QDateTime>
+#include <QDir>
+#include <QFile>
+#include <QFileSystemWatcher>
+#include <QMessageBox>
+#include <QTimer>
+#include <QWindow>
+
+namespace Autotest {
+namespace Internal {
+
+// make this configurable?
+static const QString resultsDirectory = QFileInfo(QDir::home(),
+ QLatin1String(".squishQC/Test Results")
+ ).absoluteFilePath();
+
+TestSquishTools::TestSquishTools(QObject *parent)
+ : QObject(parent),
+ m_serverProcess(0),
+ m_runnerProcess(0),
+ m_serverPort(-1),
+ m_request(None),
+ m_state(Idle),
+ m_currentResultsXML(0),
+ m_resultsFileWatcher(0),
+ m_testRunning(false)
+{
+ connect(this, &TestSquishTools::logOutputReceived,
+ TestResultsPane::instance(), &TestResultsPane::addLogoutput, Qt::QueuedConnection);
+}
+
+TestSquishTools::~TestSquishTools()
+{
+ // TODO add confirmation dialog somewhere
+ if (m_runnerProcess) {
+ m_runnerProcess->terminate();
+ if (!m_runnerProcess->waitForFinished(5000))
+ m_runnerProcess->kill();
+ delete m_runnerProcess;
+ m_runnerProcess = 0;
+ }
+
+ if (m_serverProcess) {
+ m_serverProcess->terminate();
+ if (!m_serverProcess->waitForFinished(5000))
+ m_serverProcess->kill();
+ delete m_serverProcess;
+ m_serverProcess = 0;
+ }
+}
+
+struct SquishToolsSettings
+{
+ SquishToolsSettings()
+ : serverPath(QLatin1String("squishserver"))
+ , runnerPath(QLatin1String("squishrunner"))
+ , isLocalServer(true)
+ , verboseLog(false)
+ , serverHost(QLatin1String("localhost"))
+ , serverPort(9999)
+ {}
+
+ QString squishPath;
+ QString serverPath;
+ QString runnerPath;
+ bool isLocalServer;
+ bool verboseLog;
+ QString serverHost;
+ int serverPort;
+ QString licenseKeyPath;
+};
+
+void TestSquishTools::runTestCases(const QString &suitePath, const QStringList &testCases,
+ const QStringList &additionalServerArgs,
+ const QStringList &additionalRunnerArgs)
+{
+ if (m_state != Idle) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Error"),
+ tr("Squish Tools in unexpected state (%1).\n"
+ "Refusing to run a test case.").arg(m_state));
+ return;
+ }
+ // create test results directory (if necessary) and return on fail
+ if (!QDir().mkpath(resultsDirectory)) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Error"),
+ tr("Could not create test results folder. Canceling test run."));
+ return;
+ }
+
+ m_suitePath = suitePath;
+ m_testCases = testCases;
+ m_reportFiles.clear();
+ m_additionalServerArguments = additionalServerArgs;
+
+ const QString dateTimeString
+ = QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-ddTHH-mm-ss"));
+ m_currentResultsDirectory = QFileInfo(QDir(resultsDirectory),
+ dateTimeString).absoluteFilePath();
+
+ m_additionalRunnerArguments = additionalRunnerArgs;
+ m_additionalRunnerArguments << QLatin1String("--interactive")
+ << QLatin1String("--resultdir")
+ << QDir::toNativeSeparators(m_currentResultsDirectory);
+
+ m_testRunning = true;
+ emit squishTestRunStarted();
+ startSquishServer(RunTestRequested);
+}
+
+void TestSquishTools::setState(TestSquishTools::State state)
+{
+ // TODO check whether state transition is legal
+ m_state = state;
+
+ switch (m_state) {
+ case Idle:
+ m_request = None;
+ m_suitePath = QString();
+ m_testCases.clear();
+ m_reportFiles.clear();
+ m_additionalRunnerArguments.clear();
+ m_additionalServerArguments.clear();
+ m_testRunning = false;
+ m_currentResultsDirectory.clear();
+ m_lastTopLevelWindows.clear();
+ break;
+ case ServerStarted:
+ if (m_request == RunTestRequested) {
+ startSquishRunner();
+ } else if (m_request == RecordTestRequested) {
+
+ } else if (m_request == RunnerQueryRequested) {
+
+ } else {
+ QTC_ASSERT(false, qDebug() << m_state << m_request);
+ }
+ break;
+ case ServerStartFailed:
+ m_state = Idle;
+ m_request = None;
+ if (m_testRunning) {
+ emit squishTestRunFinished();
+ m_testRunning = false;
+ }
+ restoreQtCreatorWindows();
+ break;
+ case ServerStopped:
+ m_state = Idle;
+ if (m_request == ServerStopRequested) {
+ m_request = None;
+ if (m_testRunning) {
+ emit squishTestRunFinished();
+ m_testRunning = false;
+ }
+ restoreQtCreatorWindows();
+ } else if (m_request == KillOldBeforeRunRunner) {
+ startSquishServer(RunTestRequested);
+ } else if (m_request == KillOldBeforeRecordRunner) {
+ startSquishServer(RecordTestRequested);
+ } else if (m_request == KillOldBeforeQueryRunner) {
+ startSquishServer(RunnerQueryRequested);
+ } else {
+ QTC_ASSERT(false, qDebug() << m_state << m_request);
+ }
+ break;
+ case ServerStopFailed:
+ if (m_serverProcess && m_serverProcess->state() != QProcess::NotRunning) {
+ m_serverProcess->terminate();
+ if (!m_serverProcess->waitForFinished(5000)) {
+ m_serverProcess->kill();
+ delete m_serverProcess;
+ m_serverProcess = 0;
+ }
+ }
+ m_state = Idle;
+ break;
+ case RunnerStartFailed:
+ case RunnerStopped:
+ if (m_testCases.isEmpty()) {
+ m_request = ServerStopRequested;
+ stopSquishServer();
+ // TODO merge result files
+ logrotateTestResults();
+ } else {
+ startSquishRunner();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// will be populated by calling setupSquishTools() with current settings
+static SquishToolsSettings toolsSettings;
+
+void setupSquishTools()
+{
+ QSharedPointer<SquishSettings> squishSettings = AutotestPlugin::instance()->squishSettings();
+ toolsSettings.squishPath = squishSettings->squishPath.toString();
+
+ toolsSettings.serverPath
+ = Utils::HostOsInfo::withExecutableSuffix(QLatin1String("squishserver"));
+ toolsSettings.runnerPath
+ = Utils::HostOsInfo::withExecutableSuffix(QLatin1String("squishrunner"));
+
+ if (!toolsSettings.squishPath.isEmpty()) {
+ const QDir squishBin(toolsSettings.squishPath + QDir::separator() + QLatin1String("bin"));
+ toolsSettings.serverPath = QFileInfo(squishBin,
+ toolsSettings.serverPath).absoluteFilePath();
+ toolsSettings.runnerPath = QFileInfo(squishBin,
+ toolsSettings.runnerPath).absoluteFilePath();
+ }
+
+ toolsSettings.isLocalServer = squishSettings->local;
+ toolsSettings.serverHost = squishSettings->serverHost;
+ toolsSettings.serverPort = squishSettings->serverPort;
+ toolsSettings.verboseLog = squishSettings->verbose;
+ toolsSettings.licenseKeyPath = squishSettings->licensePath.toString();
+}
+
+void TestSquishTools::startSquishServer(Request request)
+{
+ m_request = request;
+ if (m_serverProcess) {
+ if (QMessageBox::question(Core::ICore::dialogParent(), tr("Squish Server Already Running"),
+ tr("There is still an old Squish server instance running.\n"
+ "This will cause problems later on.\n\n"
+ "If you continue the old instance will be terminated.\n"
+ "Do you want to continue?")) == QMessageBox::Yes) {
+ switch (m_request) {
+ case RunTestRequested:
+ m_request = KillOldBeforeRunRunner;
+ break;
+ case RecordTestRequested:
+ m_request = KillOldBeforeRecordRunner;
+ break;
+ case RunnerQueryRequested:
+ m_request = KillOldBeforeQueryRunner;
+ break;
+ default:
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Error"),
+ tr("Unexpected state or request while starting Squish "
+ "server. (state: %1, request: %2)")
+ .arg(m_state).arg(m_request));
+ }
+ stopSquishServer();
+ }
+ return;
+ }
+
+ setupSquishTools();
+ m_serverPort = -1;
+
+ const Utils::FileName squishServer
+ = Utils::Environment::systemEnvironment().searchInPath(toolsSettings.serverPath);
+ if (squishServer.isEmpty()) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Squish Server Error"),
+ tr("\"%1\" could not be found or is not executable.\n"
+ "Check the settings.")
+ .arg(QDir::toNativeSeparators(toolsSettings.serverPath)));
+ setState(Idle);
+ return;
+ }
+ toolsSettings.serverPath = squishServer.toString();
+
+ if (true) // TODO squish setting of minimize QC on squish run/record
+ minimizeQtCreatorWindows();
+ else
+ m_lastTopLevelWindows.clear();
+
+ m_serverProcess = new QProcess;
+ m_serverProcess->setProgram(toolsSettings.serverPath);
+ QStringList arguments;
+ // TODO if isLocalServer is false we should start a squishserver on remote device
+ if (toolsSettings.isLocalServer)
+ arguments << QLatin1String("--local"); // for now - although Squish Docs say "don't use it"
+ else
+ arguments << QLatin1String("--port") << QString::number(toolsSettings.serverPort);
+
+ if (toolsSettings.verboseLog)
+ arguments << QLatin1String("--verbose");
+
+ m_serverProcess->setArguments(arguments);
+ m_serverProcess->setProcessEnvironment(squishEnvironment());
+
+ connect(m_serverProcess, &QProcess::readyReadStandardOutput,
+ this, &TestSquishTools::onServerOutput);
+ connect(m_serverProcess, &QProcess::readyReadStandardError,
+ this, &TestSquishTools::onServerErrorOutput);
+ connect(m_serverProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ this, SLOT(onServerFinished(int,QProcess::ExitStatus)));
+
+ setState(ServerStarting);
+ m_serverProcess->start();
+ if (!m_serverProcess->waitForStarted()) {
+ setState(ServerStartFailed);
+ qWarning() << "squishserver did not start within 30s";
+ }
+}
+
+void TestSquishTools::stopSquishServer()
+{
+ if (m_serverProcess && m_serverPort > 0) {
+ QProcess serverKiller;
+ serverKiller.setProgram(m_serverProcess->program());
+ QStringList args;
+ args << QLatin1String("--stop") << QLatin1String("--port") << QString::number(m_serverPort);
+ serverKiller.setArguments(args);
+ serverKiller.setProcessEnvironment(m_serverProcess->processEnvironment());
+ serverKiller.start();
+ if (serverKiller.waitForStarted()) {
+ if (!serverKiller.waitForFinished()) {
+ qWarning() << "Could not shutdown server within 30s";
+ setState(ServerStopFailed);
+ }
+ } else {
+ qWarning() << "Could not shutdown server within 30s";
+ setState(ServerStopFailed);
+ }
+ } else {
+ qWarning() << "either no process running or port < 1?" << m_serverProcess << m_serverPort;
+ setState(ServerStopFailed);
+ }
+}
+
+void TestSquishTools::startSquishRunner()
+{
+ if (!m_serverProcess) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("No Squish Server"),
+ tr("Squish server does not seem to be running.\n"
+ "(state: %1, request: %2)\n"
+ "Try again.").arg(m_state).arg(m_request));
+ setState(Idle);
+ return;
+ }
+ if (m_serverPort == -1) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("No Squish Server Port"),
+ tr("Failed to get the server port.\n"
+ "(state: %1, request: %2)\n"
+ "Try again.").arg(m_state).arg(m_request));
+ // setting state to ServerStartFailed will terminate/kill the current unusable server
+ setState(ServerStartFailed);
+ return;
+ }
+
+ if (m_runnerProcess) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Squish Runner Running"),
+ tr("Squish runner seems to be running already.\n"
+ "(state: %1, request: %2)\n"
+ "Wait until it has finished and try again.")
+ .arg(m_state).arg(m_request));
+ return;
+ }
+
+ const Utils::FileName squishRunner
+ = Utils::Environment::systemEnvironment().searchInPath(toolsSettings.runnerPath);
+ if (squishRunner.isEmpty()) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Squish Runner Error"),
+ tr("\"%1\" could not be found or is not executable.\n"
+ "Check the settings.")
+ .arg(QDir::toNativeSeparators(toolsSettings.runnerPath)));
+ setState(RunnerStopped);
+ return;
+ }
+ toolsSettings.runnerPath = squishRunner.toString();
+
+ m_runnerProcess = new QProcess;
+
+ QStringList args;
+ args << m_additionalServerArguments;
+ if (!toolsSettings.isLocalServer)
+ args << QLatin1String("--host") << toolsSettings.serverHost;
+ args << QLatin1String("--port") << QString::number(m_serverPort);
+ args << QLatin1String("--debugLog") << QLatin1String("alpw"); // TODO make this configurable?
+
+ const QFileInfo testCasePath(QDir(m_suitePath), m_testCases.takeFirst());
+ args << QLatin1String("--testcase") << testCasePath.absoluteFilePath();
+ args << QLatin1String("--suitedir") << m_suitePath;
+
+ args << m_additionalRunnerArguments;
+
+ const QString caseReportFilePath = QFileInfo(QString::fromLatin1("%1/%2/%3/results.xml")
+ .arg(m_currentResultsDirectory,
+ QDir(m_suitePath).dirName(),
+ testCasePath.baseName())).absoluteFilePath();
+ m_reportFiles.append(caseReportFilePath);
+
+ args << QLatin1String("--reportgen")
+ << QString::fromLatin1("xml2.2,%1").arg(caseReportFilePath);
+
+ m_runnerProcess->setProgram(toolsSettings.runnerPath);
+ m_runnerProcess->setArguments(args);
+ m_runnerProcess->setProcessEnvironment(squishEnvironment());
+
+ connect(m_runnerProcess, &QProcess::readyReadStandardError,
+ this, &TestSquishTools::onRunnerErrorOutput);
+ connect(m_runnerProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ this, SLOT(onRunnerFinished(int,QProcess::ExitStatus)));
+
+ setState(RunnerStarting);
+
+ // set up the file system watcher for being able to read the results.xml file
+ m_resultsFileWatcher = new QFileSystemWatcher;
+ // on second run this directory exists and won't emit changes, so use the current subdirectory
+ if (QDir(m_currentResultsDirectory).exists())
+ m_resultsFileWatcher->addPath(m_currentResultsDirectory + QDir::separator() + QDir(m_suitePath).dirName());
+ else
+ m_resultsFileWatcher->addPath(QFileInfo(m_currentResultsDirectory).absolutePath());
+
+ connect(m_resultsFileWatcher, &QFileSystemWatcher::directoryChanged,
+ this, &TestSquishTools::onResultsDirChanged);
+
+ m_runnerProcess->start();
+ if (!m_runnerProcess->waitForStarted()) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Squish Runner Error"),
+ tr("Squish runner failed to start within given timeframe."));
+ delete m_resultsFileWatcher;
+ m_resultsFileWatcher = 0;
+ setState(RunnerStartFailed);
+ return;
+ }
+ setState(RunnerStarted);
+ m_currentResultsXML = new QFile(caseReportFilePath);
+}
+
+QProcessEnvironment TestSquishTools::squishEnvironment() const
+{
+ Utils::Environment environment = Utils::Environment::systemEnvironment();
+ if (!toolsSettings.licenseKeyPath.isEmpty())
+ environment.prependOrSet(QLatin1String("SQUISH_LICENSEKEY_DIR"),
+ toolsSettings.licenseKeyPath);
+ environment.prependOrSet(QLatin1String("SQUISH_PREFIX"), toolsSettings.squishPath);
+ return environment.toProcessEnvironment();
+}
+
+void TestSquishTools::onServerFinished(int, QProcess::ExitStatus)
+{
+ delete m_serverProcess;
+ m_serverProcess = 0;
+ m_serverPort = -1;
+ setState(ServerStopped);
+}
+
+void TestSquishTools::onRunnerFinished(int, QProcess::ExitStatus)
+{
+ delete m_runnerProcess;
+ m_runnerProcess = 0;
+
+ if (m_resultsFileWatcher) {
+ delete m_resultsFileWatcher;
+ m_resultsFileWatcher = 0;
+ }
+ if (m_currentResultsXML) {
+ if (m_currentResultsXML->isOpen())
+ m_currentResultsXML->close();
+ delete m_currentResultsXML;
+ m_currentResultsXML = 0;
+ }
+ setState(RunnerStopped);
+}
+
+void TestSquishTools::onServerOutput()
+{
+ // output used for getting the port information of the current squishserver
+ const QByteArray output = m_serverProcess->readAllStandardOutput();
+ foreach (const QByteArray &line, output.split('\n')) {
+ const QByteArray trimmed = line.trimmed();
+ if (trimmed.isEmpty())
+ continue;
+ if (trimmed.startsWith("Port:")) {
+ if (m_serverPort == -1) {
+ bool ok;
+ int port = trimmed.mid(6).toInt(&ok);
+ if (ok) {
+ m_serverPort = port;
+ setState(ServerStarted);
+ } else {
+ qWarning() << "could not get port number" << trimmed.mid(6);
+ setState(ServerStartFailed);
+ }
+ } else {
+ qWarning() << "got a Port output - don't know why...";
+ }
+ }
+ emit logOutputReceived(QLatin1String("Server: ") + QLatin1String(trimmed));
+ }
+}
+
+void TestSquishTools::onServerErrorOutput()
+{
+ // output that must be send to the Runner/Server Log
+ const QByteArray output = m_serverProcess->readAllStandardError();
+ foreach (const QByteArray &line, output.split('\n')) {
+ const QByteArray trimmed = line.trimmed();
+ if (!trimmed.isEmpty())
+ emit logOutputReceived(QLatin1String("Server: ") + QLatin1String(trimmed));
+ }
+}
+
+static char firstNonWhitespace(const QByteArray &text)
+{
+ for (int i = 0, limit = text.size(); i < limit; ++i)
+ if (isspace(text.at(i)))
+ continue;
+ else
+ return text.at(i);
+ return 0;
+}
+
+static int positionAfterLastClosingTag(const QByteArray &text)
+{
+ QList<QByteArray> possibleEndTags;
+ possibleEndTags << "</description>" << "</message>" << "</verification>" << "</result>"
+ << "</test>" << "</prolog>" << "</epilog>" << "</SquishReport>";
+
+ int positionStart = text.lastIndexOf("</");
+ if (positionStart == -1)
+ return -1;
+
+ int positionEnd = text.indexOf('>', positionStart);
+ if (positionEnd == -1)
+ return -1;
+
+ QByteArray endTag = text.mid(positionStart, positionEnd + 1 - positionStart);
+ if (possibleEndTags.contains(endTag))
+ return positionEnd + 1;
+ else
+ return positionAfterLastClosingTag(text.mid(0, positionStart));
+}
+
+void TestSquishTools::onRunnerOutput(const QString)
+{
+ // buffer for already read, but not processed content
+ static QByteArray buffer;
+ const qint64 currentSize = m_currentResultsXML->size();
+
+ if (currentSize <= m_readResultsCount)
+ return;
+
+ QByteArray output = m_currentResultsXML->read(currentSize - m_readResultsCount);
+ if (output.isEmpty())
+ return;
+
+ if (!buffer.isEmpty())
+ output.prepend(buffer);
+ // we might read only partial written stuff - so we have to figure out how much we can
+ // pass on for further processing and buffer the rest for the next reading
+ const int endTag = positionAfterLastClosingTag(output);
+ if (endTag < output.size()) {
+ buffer = output.mid(endTag);
+ output.truncate(endTag);
+ } else {
+ buffer.clear();
+ }
+
+ m_readResultsCount += output.size();
+
+ if (firstNonWhitespace(output) == '<') {
+ // output that must be used for the TestResultsPane
+ qDebug() << "RunnerOutput:" << output;
+ } else {
+ foreach (const QByteArray &line, output.split('\n')) {
+ const QByteArray trimmed = line.trimmed();
+ if (!trimmed.isEmpty())
+ emit logOutputReceived(QLatin1String("Runner: ") + QLatin1String(trimmed));
+ }
+ }
+}
+
+void TestSquishTools::onRunnerErrorOutput()
+{
+ // output that must be send to the Runner/Server Log
+ const QByteArray output = m_runnerProcess->readAllStandardError();
+ foreach (const QByteArray &line, output.split('\n')) {
+ const QByteArray trimmed = line.trimmed();
+ if (!trimmed.isEmpty())
+ emit logOutputReceived(QLatin1String("Runner: ") + QLatin1String(trimmed));
+ }
+}
+
+void TestSquishTools::onResultsDirChanged(const QString &filePath)
+{
+ if (m_currentResultsXML->exists()) {
+ delete m_resultsFileWatcher;
+ m_resultsFileWatcher = 0;
+ m_readResultsCount = 0;
+ if (m_currentResultsXML->open(QFile::ReadOnly)) {
+ m_resultsFileWatcher = new QFileSystemWatcher;
+ m_resultsFileWatcher->addPath(m_currentResultsXML->fileName());
+ connect(m_resultsFileWatcher, &QFileSystemWatcher::fileChanged,
+ this, &TestSquishTools::onRunnerOutput);
+ } else {
+ // TODO set a flag to process results.xml as soon the complete test run has finished
+ qWarning() << "could not open results.xml although it exists"
+ << filePath << m_currentResultsXML->error()
+ << m_currentResultsXML->errorString();
+ }
+ } else {
+ disconnect(m_resultsFileWatcher);
+ // results.xml is created as soon some output has been opened - so try again in a second
+ QTimer::singleShot(1000, this, [this, filePath] () {
+ onResultsDirChanged(filePath);
+ });
+ }
+}
+
+void TestSquishTools::logrotateTestResults()
+{
+ // make this configurable?
+ const int maxNumberOfTestResults = 10;
+ const QStringList existing = QDir(resultsDirectory).entryList(QDir::Dirs | QDir::NoDotAndDotDot,
+ QDir::Name);
+
+ for (int i = 0, limit = existing.size() - maxNumberOfTestResults; i < limit; ++i) {
+ QDir current(resultsDirectory + QDir::separator() + existing.at(i));
+ if (!current.removeRecursively())
+ qWarning() << "could not remove" << current.absolutePath();
+ }
+}
+
+void TestSquishTools::minimizeQtCreatorWindows()
+{
+ m_lastTopLevelWindows = QApplication::topLevelWindows();
+ QWindowList toBeRemoved;
+ foreach (QWindow *window, m_lastTopLevelWindows) {
+ if (window->isVisible())
+ window->showMinimized();
+ else
+ toBeRemoved.append(window);
+ }
+
+ foreach (QWindow *window, toBeRemoved)
+ m_lastTopLevelWindows.removeOne(window);
+}
+
+void TestSquishTools::restoreQtCreatorWindows()
+{
+ foreach (QWindow *window, m_lastTopLevelWindows) {
+ window->requestActivate();
+ window->showNormal();
+ }
+}
+
+} // namespace Internal
+} // namespace Autotest