diff options
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/androidtestrunner/main.cpp | 59 | ||||
| -rw-r--r-- | src/tools/configure.cmake | 2 |
2 files changed, 42 insertions, 19 deletions
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp index b517d85c5fb..161d95db49c 100644 --- a/src/tools/androidtestrunner/main.cpp +++ b/src/tools/androidtestrunner/main.cpp @@ -28,7 +28,16 @@ using namespace Qt::StringLiterals; -#define EXIT_ERROR -1 + +// QTest-based test processes may exit with up to 127 for normal test failures +static constexpr int HIGHEST_QTEST_EXITCODE = 127; +// Something went wrong in androidtestrunner, in general +static constexpr int EXIT_ERROR = 254; +// More specific exit codes for failures in androidtestrunner: +static constexpr int EXIT_NOEXITCODE = 253; // Failed to transfer exit code from device +static constexpr int EXIT_ANR = 252; // Android ANR error (Application Not Responding) +static constexpr int EXIT_NORESULTS = 251; // Failed to transfer result files from device + struct Options { @@ -71,6 +80,13 @@ struct TestInfo static TestInfo g_testInfo; +// QTest-based processes return 0 if all tests PASSed, or the number of FAILs up to 127. +// Other exitcodes signify abnormal termination and are system-dependent. +static bool isTestExitCodeNormal(const int ec) +{ + return (ec >= 0 && ec <= HIGHEST_QTEST_EXITCODE); +} + static bool execCommand(const QString &program, const QStringList &args, QByteArray *output = nullptr, bool verbose = false) { @@ -744,9 +760,9 @@ void printLogcatCrash(const QByteArray &logcat) } if (!crashLogcat.startsWith("********** Crash dump")) - qDebug() << "********** Crash dump: **********"; + qDebug() << "[androidtestrunner] ********** BEGIN crash dump **********"; qDebug().noquote() << crashLogcat.trimmed(); - qDebug() << "********** End crash dump **********"; + qDebug() << "[androidtestrunner] ********** END crash dump **********"; } void analyseLogcat(const QString &timeStamp, int *exitCode) @@ -781,10 +797,13 @@ void analyseLogcat(const QString &timeStamp, int *exitCode) // Check for ANRs const bool anrOccurred = logcat.contains("ANR in %1"_L1.arg(g_options.package).toUtf8()); if (anrOccurred) { - // Treat a found ANR as a test failure. - *exitCode = *exitCode < 1 ? 1 : *exitCode; - qCritical("An ANR has occurred while running the test %s. The logcat will include " - "additional logs from the system_server process.", + // Rather improbable, but if the test managed to return a non-crash exitcode then overwrite + // it to signify that something blew up. Same if we didn't manage to collect an exit code. + // Preserve all other exitcodes, they might be useful crash information from the device. + if (isTestExitCodeNormal(*exitCode) || *exitCode == EXIT_NOEXITCODE) + *exitCode = EXIT_ANR; + qCritical("[androidtestrunner] An ANR has occurred while running the test '%s';" + " consult logcat for additional logs from the system_server process", qPrintable(g_options.package)); } @@ -818,13 +837,14 @@ void analyseLogcat(const QString &timeStamp, int *exitCode) } } - // If we have a crash, attempt to print both logcat and the crash buffer which - // includes the crash stacktrace that is not included in the default logcat. - const bool testCrashed = *exitCode == EXIT_ERROR && !g_testInfo.isTestRunnerInterrupted.load(); + // If we have an unpredictable exitcode, possibly a crash, attempt to print both logcat and the + // crash buffer which includes the crash stacktrace that is not included in the default logcat. + const bool testCrashed = ( !isTestExitCodeNormal(*exitCode) + && !g_testInfo.isTestRunnerInterrupted.load()); if (testCrashed) { - qDebug() << "********** logcat dump **********"; + qDebug() << "[androidtestrunner] ********** BEGIN logcat dump **********"; qDebug().noquote() << testLogcat.join(u'\n').trimmed(); - qDebug() << "********** End logcat dump **********"; + qDebug() << "[androidtestrunner] ********** END logcat dump **********"; if (!crashLogcat.isEmpty()) printLogcatCrash(crashLogcat); @@ -839,7 +859,7 @@ static QString getCurrentTimeString() QStringList dateArgs = { "shell"_L1, "date"_L1, "+'%1'"_L1.arg(timeFormat) }; QByteArray output; if (!execAdbCommand(dateArgs, &output, false)) { - qWarning() << "Date/time adb command failed"; + qWarning() << "[androidtestrunner] ERROR in command: adb shell date"; return {}; } @@ -851,14 +871,15 @@ 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, false)) { - qCritical() << "Failed to retrieve the test exit code."; - return EXIT_ERROR; + qCritical() << "[androidtestrunner] ERROR in command: adb shell cat files/qtest_last_exit_code"; + return EXIT_NOEXITCODE; } + qDebug() << "[androidtestrunner] Test exitcode: " << exitCodeOutput; bool ok; int exitCode = exitCodeOutput.toInt(&ok); - return ok ? exitCode : EXIT_ERROR; + return ok ? exitCode : EXIT_NOEXITCODE; } static bool uninstallTestPackage() @@ -899,7 +920,7 @@ void sigHandler(int signal) // a main event loop. Since, there's no other alternative to do this, // let's do the cleanup anyway. if (!g_testInfo.isPackageInstalled.load()) - _exit(-1); + _exit(EXIT_ERROR); g_testInfo.isTestRunnerInterrupted.store(true); } @@ -1031,7 +1052,9 @@ int main(int argc, char *argv[]) if (g_options.showLogcatOutput) analyseLogcat(formattedStartTime, &exitCode); - exitCode = pullResults() ? exitCode : EXIT_ERROR; + const bool pullRes = pullResults(); + if (!pullRes && isTestExitCodeNormal(exitCode)) + exitCode = EXIT_NORESULTS; if (!uninstallTestPackage()) return EXIT_ERROR; diff --git a/src/tools/configure.cmake b/src/tools/configure.cmake index 27ea90b89ac..07e11dd935b 100644 --- a/src/tools/configure.cmake +++ b/src/tools/configure.cmake @@ -37,7 +37,7 @@ qt_feature("qmake" PRIVATE QT_FEATURE_datestring AND QT_FEATURE_regularexpression AND QT_FEATURE_temporaryfile) qt_feature("qtwaylandscanner" PRIVATE - CONDITION TARGET Wayland::Scanner + CONDITION TARGET Wayland::Scanner AND NOT INTEGRITY AND NOT ANDROID AND NOT WASM AND NOT IOS AND NOT QNX AND NOT VXWORKS ) qt_configure_add_summary_section(NAME "Core tools") |
