forked from qt-creator/qt-creator
AutoTest: Filter out interfering environment variables
If there are environment variables that might interfere with the test process filter them out before setting the environment for the test process as they can - in the worst case - even lead to being not able to execute the test application at all. Task-number: QTCREATORBUG-21012 Change-Id: I4a2059cf527395498824a0914fd6c3203eca9bcf Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -107,5 +107,17 @@ QStringList GTestConfiguration::argumentsForTestRunner(QStringList *omitted) con
|
||||
return arguments;
|
||||
}
|
||||
|
||||
Utils::Environment GTestConfiguration::filteredEnvironment(const Utils::Environment &original) const
|
||||
{
|
||||
const QStringList interfering{"GTEST_FILTER", "GTEST_COLOR", "GTEST_ALSO_RUN_DISABLED_TESTS",
|
||||
"GTEST_REPEAT", "GTEST_SHUFFLE", "GTEST_RANDOM_SEED",
|
||||
"GTEST_OUTPUT", "GTEST_BREAK_ON_FAILURE", "GTEST_PRINT_TIME",
|
||||
"GTEST_CATCH_EXCEPTIONS"};
|
||||
Utils::Environment result = original;
|
||||
for (const QString &key : interfering)
|
||||
result.unset(key);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Autotest
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||
QProcess *app) const override;
|
||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
#include "qttest_utils.h"
|
||||
#include "qttesttreeitem.h"
|
||||
#include "../autotestplugin.h"
|
||||
#include "../testframeworkmanager.h"
|
||||
#include "../testsettings.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -140,6 +142,17 @@ QStringList filterInterfering(const QStringList &provided, QStringList *omitted,
|
||||
return allowed;
|
||||
}
|
||||
|
||||
Utils::Environment prepareBasicEnvironment(const Utils::Environment &env)
|
||||
{
|
||||
Utils::Environment result(env);
|
||||
if (Utils::HostOsInfo::isWindowsHost())
|
||||
result.set("QT_LOGGING_TO_CONSOLE", "1");
|
||||
const int timeout = AutotestPlugin::settings()->timeout;
|
||||
if (timeout > 5 * 60 * 1000) // Qt5.5 introduced hard limit, Qt5.6.1 added env var to raise this
|
||||
result.set("QTEST_FUNCTION_TIMEOUT", QString::number(timeout));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace QTestUtils
|
||||
} // namespace Internal
|
||||
} // namespace Autotest
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <QHash>
|
||||
|
||||
namespace Core { class Id; }
|
||||
namespace Utils { class Environment; }
|
||||
|
||||
namespace Autotest {
|
||||
namespace Internal {
|
||||
@@ -37,6 +38,7 @@ bool isQTestMacro(const QByteArray ¯o);
|
||||
QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files);
|
||||
QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files);
|
||||
QStringList filterInterfering(const QStringList &provided, QStringList *omitted, bool isQuickTest);
|
||||
Utils::Environment prepareBasicEnvironment(const Utils::Environment &env);
|
||||
|
||||
} // namespace QTestUtils
|
||||
} // namespace Internal
|
||||
|
||||
@@ -84,5 +84,10 @@ QStringList QtTestConfiguration::argumentsForTestRunner(QStringList *omitted) co
|
||||
return arguments;
|
||||
}
|
||||
|
||||
Utils::Environment QtTestConfiguration::filteredEnvironment(const Utils::Environment &original) const
|
||||
{
|
||||
return QTestUtils::prepareBasicEnvironment(original);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Autotest
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||
QProcess *app) const override;
|
||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -86,6 +86,11 @@ QStringList QuickTestConfiguration::argumentsForTestRunner(QStringList *omitted)
|
||||
return arguments;
|
||||
}
|
||||
|
||||
Utils::Environment QuickTestConfiguration::filteredEnvironment(const Utils::Environment &original) const
|
||||
{
|
||||
return QTestUtils::prepareBasicEnvironment(original);
|
||||
}
|
||||
|
||||
void QuickTestConfiguration::setUnnamedOnly(bool unnamedOnly)
|
||||
{
|
||||
m_unnamedOnly = unnamedOnly;
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||
QProcess *app) const override;
|
||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||
|
||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||
void setUnnamedOnly(bool unnamedOnly);
|
||||
bool unnamedOnly() const { return m_unnamedOnly; }
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||
QProcess *app) const = 0;
|
||||
virtual QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const = 0;
|
||||
|
||||
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const = 0;
|
||||
private:
|
||||
QStringList m_testCases;
|
||||
int m_testCaseCount = 0;
|
||||
|
||||
@@ -148,6 +148,15 @@ static QString constructOmittedDetailsString(const QStringList &omitted)
|
||||
"configuration page for \"%1\":") + '\n' + omitted.join('\n');
|
||||
}
|
||||
|
||||
static QString constructOmittedVariablesDetailsString(const QList<Utils::EnvironmentItem> &diff)
|
||||
{
|
||||
auto removedVars = Utils::transform<QStringList>(diff, [](const Utils::EnvironmentItem &it) {
|
||||
return it.name;
|
||||
});
|
||||
return TestRunner::tr("Omitted the following environment variables for \"%1\":")
|
||||
+ '\n' + removedVars.join('\n');
|
||||
}
|
||||
|
||||
void TestRunner::scheduleNext()
|
||||
{
|
||||
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
|
||||
@@ -192,17 +201,23 @@ void TestRunner::scheduleNext()
|
||||
details.arg(m_currentConfig->displayName()))));
|
||||
}
|
||||
m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory());
|
||||
QProcessEnvironment environment = m_currentConfig->environment().toProcessEnvironment();
|
||||
if (Utils::HostOsInfo::isWindowsHost())
|
||||
environment.insert("QT_LOGGING_TO_CONSOLE", "1");
|
||||
const int timeout = AutotestPlugin::settings()->timeout;
|
||||
if (timeout > 5 * 60 * 1000) // Qt5.5 introduced hard limit, Qt5.6.1 added env var to raise this
|
||||
environment.insert("QTEST_FUNCTION_TIMEOUT", QString::number(timeout));
|
||||
m_currentProcess->setProcessEnvironment(environment);
|
||||
const Utils::Environment &original = m_currentConfig->environment();
|
||||
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
|
||||
const QList<Utils::EnvironmentItem> removedVariables
|
||||
= Utils::filtered(original.diff(environment), [](const Utils::EnvironmentItem &it) {
|
||||
return it.operation == Utils::EnvironmentItem::Unset;
|
||||
});
|
||||
if (!removedVariables.isEmpty()) {
|
||||
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
|
||||
.arg(m_currentConfig->displayName());
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, details)));
|
||||
}
|
||||
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
|
||||
|
||||
connect(m_currentProcess,
|
||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
this, &TestRunner::onProcessFinished);
|
||||
const int timeout = AutotestPlugin::settings()->timeout;
|
||||
QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
|
||||
|
||||
m_currentProcess->start();
|
||||
@@ -521,6 +536,17 @@ void TestRunner::debugTests()
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||
details.arg(config->displayName()))));
|
||||
}
|
||||
Utils::Environment original(inferior.environment);
|
||||
inferior.environment = config->filteredEnvironment(original);
|
||||
const QList<Utils::EnvironmentItem> removedVariables
|
||||
= Utils::filtered(original.diff(inferior.environment), [](const Utils::EnvironmentItem &it) {
|
||||
return it.operation == Utils::EnvironmentItem::Unset;
|
||||
});
|
||||
if (!removedVariables.isEmpty()) {
|
||||
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
|
||||
.arg(config->displayName());
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, details)));
|
||||
}
|
||||
auto debugger = new Debugger::DebuggerRunTool(runControl);
|
||||
debugger->setInferior(inferior);
|
||||
debugger->setRunControlName(config->displayName());
|
||||
|
||||
Reference in New Issue
Block a user