Utils: Fix addCommandLineWithAnd for Windows

Also enable more unittests on windows

Change-Id: I241b77c640949cf622dc8138991036bb066ce3cf
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-11-29 10:41:30 +01:00
parent 7bc86a8b8d
commit fd829240ed
3 changed files with 110 additions and 32 deletions

View File

@@ -1490,7 +1490,7 @@ void CommandLine::addCommandLineWithAnd(const CommandLine &cmd)
}
addArgs("&&", Raw);
addCommandLineAsArgs(cmd);
addCommandLineAsArgs(cmd, Raw);
}
void CommandLine::addArgs(const QString &inArgs, RawType)

View File

@@ -1,4 +1,8 @@
file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
add_qtc_test(tst_utils_commandline
DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
DEPENDS Utils app_version
SOURCES tst_commandline.cpp
)

View File

@@ -1,75 +1,149 @@
// Copyright (C) 2022 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 <app/app_version.h>
#include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/launcherinterface.h>
#include <utils/processinterface.h>
#include <utils/qtcprocess.h>
#include <utils/temporarydirectory.h>
#include <QObject>
#include <QtTest>
#include <iostream>
using namespace Utils;
FilePath self;
class tst_CommandLine : public QObject
{
Q_OBJECT
private:
Environment testEnv = Environment::systemEnvironment();
QString newLine;
QString run(const CommandLine &cmd)
{
QtcProcess p;
p.setCommand(cmd);
p.setEnvironment(testEnv);
p.runBlocking();
return QString::fromUtf8(p.readAllStandardOutput());
}
private slots:
void initTestCase() {}
void cleanupTestCase() {}
void initTestCase()
{
TemporaryDirectory::setMasterTemporaryDirectory(
QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
const QString libExecPath(qApp->applicationDirPath() + '/'
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
LauncherInterface::setPathToLauncher(libExecPath);
testEnv.appendOrSet("TEST_ECHO", "1");
if (HostOsInfo::isWindowsHost())
newLine = "\r\n";
else
newLine = "\n";
}
void cleanupTestCase() { Singleton::deleteAll(); }
void testSpace()
{
CommandLine cmd(self, {"With Space"});
QString expected = "With Space" + newLine;
QCOMPARE(run(cmd), expected);
}
void testQuote()
{
QStringList args = {"\"With <\"Quote\"> % ^^ \"", "Hallo ??"};
CommandLine cmd(self, args);
QString expected = args.join(newLine) + newLine;
QCOMPARE(run(cmd), expected);
}
void testAnd()
{
CommandLine cmd("echo", {"foo"});
CommandLine cmd2("echo", {"bar", "blizz"});
QStringList args = {"foo", "bar", "baz"};
CommandLine cmd(self, {args[0]});
CommandLine cmd2(self, args.sliced(1));
cmd.addCommandLineWithAnd(cmd2);
const QString actual = cmd.toUserOutput();
const QString wanted = "echo foo && echo bar blizz";
QString expected = args.join(newLine) + newLine;
QCOMPARE(actual, wanted);
QCOMPARE(run(cmd), expected);
}
void testAndComplex()
{
if (HostOsInfo::isWindowsHost())
QSKIP("CommandLine does not produce useful escaping on windows.");
CommandLine cmd("/tmp/space path/\"echo", {"foo", "long with space"});
CommandLine cmd2("/tmp/space \"path/echo", {"bar\"", "blizz is 'great"});
QStringList args = {"foo", "long with space", "bar\"", "blizz is 'great"};
CommandLine cmd(self, args.sliced(0, 2));
CommandLine cmd2(self, args.sliced(2, 2));
cmd.addCommandLineWithAnd(cmd2);
const QString actual = cmd.toUserOutput();
const QString wanted =
"/tmp/space path/\"echo foo 'long with space' && '/tmp/space \"path/echo' "
"'bar\"' 'blizz is '\\''great'";
QCOMPARE(actual, wanted);
QString expected = args.join(newLine) + newLine;
QString actual = run(cmd);
QCOMPARE(actual, expected);
}
void testAndAdd()
{
if (HostOsInfo::isWindowsHost())
QSKIP("CommandLine does not produce useful escaping on windows.");
QSKIP("The test does not yet work on Windows.");
QStringList args = {"foo", "long with space", "bar", "blizz is great"};
CommandLine cmd(self, args.sliced(0, 2));
CommandLine cmd2(self, args.sliced(2, 2));
CommandLine cmd("/tmp/space path/\"echo", {"foo", "long with space"});
CommandLine cmd2("/tmp/space \"path/echo", {"bar\"", "blizz is 'great"});
cmd.addCommandLineWithAnd(cmd2);
CommandLine shell("bash", {"-c"});
CommandLine shell;
if (HostOsInfo::isWindowsHost()) {
shell.setExecutable(FilePath::fromUserInput(qEnvironmentVariable("COMSPEC")));
shell.addArgs({"/v:off", "/s", "/c"});
} else {
shell.setExecutable(FilePath::fromUserInput("/bin/sh"));
shell.addArgs({"-c"});
}
shell.addCommandLineAsSingleArg(cmd);
const QString actual = shell.toUserOutput();
const QString wanted =
"bash -c ''\\''/tmp/space path/\"echo'\\'' foo '\\''long with space'\\'' && "
"'\\''/tmp/space \"path/echo'\\'' '\\''bar\"'\\'' '\\''blizz is "
"'\\''\\'\\'''\\''great'\\'''";
QCOMPARE(actual, wanted);
QString expected = args.join(newLine) + newLine;
QString actual = run(shell);
QCOMPARE(actual, expected);
}
};
QTEST_GUILESS_MAIN(tst_CommandLine)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
self = FilePath::fromString(argv[0]);
if (qEnvironmentVariableIsSet("TEST_ECHO")) {
for (int i = 1; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
return 0;
}
TESTLIB_SELFCOVERAGE_START(tst_CommandLine)
QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<tst_CommandLine>();
tst_CommandLine tc;
QTEST_SET_MAIN_SOURCE_PATH
return QTest::qExec(&tc, argc, argv);
}
#include "tst_commandline.moc"