AndroidTestRunner: don't fail waiting for the app to start/finish
Currently, under waitToFinish(), we wait for the app to start and if it doesn't start or starts and exits too quickly for the test runner to catch it, it fails. The test runner tries to get the pid of the test after it detects the app has started. However, we don't really need to fail, the test runner could simply continue the execution and assume the test was run and finished, and proceed to fetching the test results. Since, the results fetching don't anyway rely on the pid, the test runner can let that operation decide whether to fail or not (if not output is found). Also, along the way, instead of issuing a different command to get the pid (i.e. adb shell pidof), we can use the same "adb shell ps" command that is used to check if the app is running, to obtain the pid. Fixes: QTQAINFRA-5928 Fixes: QTBUG-88508 Pick-to: 6.6 6.5 Change-Id: Ice945fcb686c4ef21b5f1c143aa22922ae928333 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
parent
518ac20dcb
commit
4bc3f700ff
@ -10,9 +10,9 @@
|
|||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
#include <QtCore/QDeadlineTimer>
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <shellquote_shared.h>
|
#include <shellquote_shared.h>
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ struct Options
|
|||||||
bool helpRequested = false;
|
bool helpRequested = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool skipAddInstallRoot = false;
|
bool skipAddInstallRoot = false;
|
||||||
std::chrono::seconds timeout{480}; // 8 minutes
|
int timeoutSecs = 480; // 8 minutes
|
||||||
QString buildPath;
|
QString buildPath;
|
||||||
QString adbCommand{QStringLiteral("adb")};
|
QString adbCommand{QStringLiteral("adb")};
|
||||||
QString makeCommand;
|
QString makeCommand;
|
||||||
@ -205,7 +205,7 @@ static bool parseOptions()
|
|||||||
if (i + 1 == arguments.size())
|
if (i + 1 == arguments.size())
|
||||||
g_options.helpRequested = true;
|
g_options.helpRequested = true;
|
||||||
else
|
else
|
||||||
g_options.timeout = std::chrono::seconds{arguments.at(++i).toInt()};
|
g_options.timeoutSecs = arguments.at(++i).toInt();
|
||||||
} else if (argument.compare(QStringLiteral("--help"), Qt::CaseInsensitive) == 0) {
|
} else if (argument.compare(QStringLiteral("--help"), Qt::CaseInsensitive) == 0) {
|
||||||
g_options.helpRequested = true;
|
g_options.helpRequested = true;
|
||||||
} else if (argument.compare(QStringLiteral("--verbose"), Qt::CaseInsensitive) == 0) {
|
} else if (argument.compare(QStringLiteral("--verbose"), Qt::CaseInsensitive) == 0) {
|
||||||
@ -355,53 +355,58 @@ static bool parseTestArgs()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool obtainPid() {
|
||||||
|
QByteArray output;
|
||||||
|
const auto psCmd = "%1 shell \"ps | grep ' %2'\""_L1.arg(g_options.adbCommand,
|
||||||
|
shellQuote(g_options.package));
|
||||||
|
if (!execCommand(psCmd, &output))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const QList<QByteArray> lines = output.split(u'\n');
|
||||||
|
if (lines.size() < 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QList<QByteArray> columns = lines.first().simplified().replace(u'\t', u' ').split(u' ');
|
||||||
|
if (columns.size() < 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (g_options.pid == -1) {
|
||||||
|
bool ok = false;
|
||||||
|
int pid = columns.at(1).toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
g_options.pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool isRunning() {
|
static bool isRunning() {
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
if (!execCommand(QStringLiteral("%1 shell \"ps | grep ' %2'\"").arg(g_options.adbCommand,
|
const auto psCmd = "%1 shell \"ps | grep ' %2'\""_L1.arg(g_options.adbCommand,
|
||||||
shellQuote(g_options.package)), &output)) {
|
shellQuote(g_options.package));
|
||||||
|
if (!execCommand(psCmd, &output))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return output.indexOf(QLatin1StringView(" " + g_options.package.toUtf8())) > -1;
|
return output.indexOf(QLatin1StringView(" " + g_options.package.toUtf8())) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool waitToFinish()
|
static void waitForFinished()
|
||||||
{
|
{
|
||||||
using clock = std::chrono::system_clock;
|
// wait to start and set PID
|
||||||
auto start = clock::now();
|
QDeadlineTimer startDeadline(10000);
|
||||||
// wait to start
|
do {
|
||||||
while (!isRunning()) {
|
if (obtainPid())
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
break;
|
||||||
if ((clock::now() - start) > std::chrono::seconds{10})
|
QThread::msleep(100);
|
||||||
return false;
|
} while (!startDeadline.hasExpired());
|
||||||
}
|
|
||||||
|
|
||||||
if (g_options.sdkVersion > 23) { // pidof is broken in SDK 23, non-existent before
|
|
||||||
QByteArray output;
|
|
||||||
const QString command(QStringLiteral("%1 shell pidof -s %2")
|
|
||||||
.arg(g_options.adbCommand, shellQuote(g_options.package)));
|
|
||||||
execCommand(command, &output, g_options.verbose);
|
|
||||||
bool ok = false;
|
|
||||||
int pid = output.toInt(&ok); // If we got more than one pid, fail.
|
|
||||||
if (ok) {
|
|
||||||
g_options.pid = pid;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Unable to obtain the PID of the running unit test. Command \"%s\" "
|
|
||||||
"returned \"%s\"\n",
|
|
||||||
command.toUtf8().constData(), output.constData());
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait to finish
|
// Wait to finish
|
||||||
while (isRunning()) {
|
QDeadlineTimer finishedDeadline(g_options.timeoutSecs * 1000);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
do {
|
||||||
if (g_options.timeout >= std::chrono::seconds::zero()
|
if (!isRunning())
|
||||||
&& (clock::now() - start) > g_options.timeout)
|
break;
|
||||||
return false;
|
QThread::msleep(250);
|
||||||
}
|
} while (!finishedDeadline.hasExpired());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void obtainSDKVersion()
|
static void obtainSDKVersion()
|
||||||
@ -604,9 +609,10 @@ int main(int argc, char *argv[])
|
|||||||
const QString formattedTime = getCurrentTimeString();
|
const QString formattedTime = getCurrentTimeString();
|
||||||
|
|
||||||
// start the tests
|
// start the tests
|
||||||
bool res = execCommand("%1 %2"_L1.arg(g_options.adbCommand, g_options.testArgs),
|
const auto startCmd = "%1 %2"_L1.arg(g_options.adbCommand, g_options.testArgs);
|
||||||
nullptr, g_options.verbose)
|
bool res = execCommand(startCmd, nullptr, g_options.verbose);
|
||||||
&& waitToFinish();
|
|
||||||
|
waitForFinished();
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
res &= pullFiles();
|
res &= pullFiles();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user