summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMarcus Tillmanns <marcus.tillmanns@qt.io>2022-06-28 09:26:06 +0200
committerMarcus Tillmanns <marcus.tillmanns@qt.io>2022-06-29 07:28:46 +0000
commit39580871241c77303c43204da8bd1c666a2140e0 (patch)
tree68f3e2d4c96144750a928cc9b704a0738718d486 /tests
parent8130d895c820bff633884536c4955751a2b107f4 (diff)
downloadqt-creator-39580871241c77303c43204da8bd1c666a2140e0.tar.gz
deviceshell: fix hang on multithreaded access
When outputting a commands stdout / stderr / exitcode, the shell was free to interlace different outputs. This could trip the parsing of the output, leading to the shell missing the exit code of a command. When that happened, the caller might wait indefinitely for a result that would never come. To workaround, the shell script now writes each command output to a temporary file first, which is then written to stdout by a single subshell, that way guaranteeing that the output of multiple commands will not interleave Change-Id: I9d8e7e788f5922c612ff533e5ba063f61a22aa8c Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/utils/deviceshell/tst_deviceshell.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/auto/utils/deviceshell/tst_deviceshell.cpp b/tests/auto/utils/deviceshell/tst_deviceshell.cpp
index 983c2d35ce..2c209b94a1 100644
--- a/tests/auto/utils/deviceshell/tst_deviceshell.cpp
+++ b/tests/auto/utils/deviceshell/tst_deviceshell.cpp
@@ -29,6 +29,7 @@
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/launcherinterface.h>
+#include <utils/mapreduce.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/temporarydirectory.h>
@@ -287,6 +288,63 @@ private slots:
const DeviceShell::RunResult result2 = shell.outputForRunInShell(
{"cat", {"/tmp/i-do-not-exist.none"}});
QVERIFY(!result2.stdErr.isEmpty());
+ QVERIFY(result2.exitCode != 0);
+ }
+
+ void testNoCommand_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : m_availableShells) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testNoCommand()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({}, {});
+
+ QVERIFY(result.exitCode == 255);
+ }
+
+ void testMultiThreadedFind_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : m_availableShells) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testMultiThreadedFind()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QList<int> runs{1,2,3,4,5,6,7,8,9};
+
+ QList<QByteArray> results = Utils::mapped<QList>(runs, [&shell](const int i) -> QByteArray{
+ QElapsedTimer t;
+ t.start();
+ DeviceShell::RunResult result = shell.outputForRunInShell({"find", {"/usr", "-maxdepth", "4"}});
+ qDebug() << i << "took" << t.elapsed() << "ms";
+ return result.stdOut;
+ });
+
+ QVERIFY (!Utils::anyOf(results, [&results](const QByteArray r){ return r != results[0]; }));
}
};