From 8d4022187b660de6c81c09ea7a4864048aa94978 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Sun, 20 Oct 2024 17:20:19 +0300 Subject: [PATCH] AndroidTestRunner: get test exit code instead of parsing results Write the exit code for qt tests at the end of the test run where it would be available to androidtestrunner to find out the exact number of failed tests, this would make the custom parses in the androidtestrunner redandant. Fixes: QTBUG-129976 Pick-to: 6.8 Change-Id: I3c2ea9780505f1d4a2a46ae94534cd1e4f07334c Reviewed-by: Ville Voutilainen --- src/testlib/qtestcase.cpp | 30 +++++++++++++++++++++++- src/tools/androidtestrunner/main.cpp | 35 +++++++++++++++++++--------- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 78e8038c05b..0b6c01e4140 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -111,6 +111,10 @@ #include #endif +#ifdef Q_OS_ANDROID +#include +#endif + #include QT_BEGIN_NAMESPACE @@ -1790,6 +1794,14 @@ static void initEnvironment() qputenv("QT_QTESTLIB_RUNNING", "1"); } +#ifdef Q_OS_ANDROID +static QFile androidExitCodeFile() +{ + const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + return QFile(testHome + "/qtest_last_exit_code"_L1); +} +#endif + /*! Executes tests declared in \a testObject. In addition, the private slots \c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()} @@ -1890,6 +1902,10 @@ void QTest::qInit(QObject *testObject, int argc, char **argv) if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess) #endif QTestLog::startLogging(); + +#ifdef Q_OS_ANDROID + androidExitCodeFile().remove(); +#endif } /*! \internal @@ -1984,7 +2000,19 @@ int QTest::qRun() #endif // make sure our exit code is never going above 127 // since that could wrap and indicate 0 test fails - return qMin(QTestLog::failCount(), 127); + const int exitCode = qMin(QTestLog::failCount(), 127); + +#ifdef Q_OS_ANDROID + QFile exitCodeFile = androidExitCodeFile(); + if (exitCodeFile.open(QIODevice::WriteOnly)) { + exitCodeFile.write(qPrintable(QString::number(exitCode))); + } else { + qWarning("Failed to open %s for writing test exit code: %s", + qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString())); + } +#endif + + return exitCode; } /*! \internal diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp index b800bee8c54..b81d7a73600 100644 --- a/src/tools/androidtestrunner/main.cpp +++ b/src/tools/androidtestrunner/main.cpp @@ -547,7 +547,7 @@ static QString runCommandAsUserArgs(const QString &cmd) return "run-as %1 --user %2 %3"_L1.arg(g_options.package, g_testInfo.userId, cmd); } -static bool pullFiles() +static bool pullResults() { bool ret = true; for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.end(); ++it) { @@ -702,6 +702,19 @@ static QString getCurrentTimeString() return QString::fromUtf8(output.simplified()); } +static int testExitCode() +{ + QByteArray exitCodeOutput; + const QString exitCodeCmd = "cat files/qtest_last_exit_code 2> /dev/null"_L1; + if (!execAdbCommand({ "shell"_L1, runCommandAsUserArgs(exitCodeCmd) }, &exitCodeOutput)) + return 1; + + bool ok; + int exitCode = exitCodeOutput.toInt(&ok); + + return ok ? exitCode : 1; +} + static bool uninstallTestPackage() { return execAdbCommand({ "uninstall"_L1, g_options.package }, nullptr); @@ -814,24 +827,24 @@ int main(int argc, char *argv[]) const QString formattedTime = getCurrentTimeString(); // start the tests - bool success = execAdbCommand(g_options.amStarttestArgs, nullptr); + if (!execAdbCommand(g_options.amStarttestArgs, nullptr)) + return 1; waitForStartedAndFinished(); - if (success) { - success &= pullFiles(); - if (g_options.showLogcatOutput) - printLogcat(formattedTime); - } + int exitCode = testExitCode(); // If we have a failure, attempt to print both logcat and the crash buffer which // includes the crash stacktrace that is not included in the default logcat. - if (!success) { + if (exitCode != 0 || g_options.showLogcatOutput) printLogcat(formattedTime); + if (exitCode != 0) printLogcatCrashBuffer(formattedTime); - } - success &= uninstallTestPackage(); + exitCode = pullResults() ? exitCode : 1; + + if (!uninstallTestPackage()) + return 1; testRunnerLock.release(); @@ -840,5 +853,5 @@ int main(int argc, char *argv[]) return 1; } - return success ? 0 : 1; + return exitCode; }