summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <[email protected]>2023-11-29 13:45:04 +0200
committerQt Cherry-pick Bot <[email protected]>2023-12-15 05:26:01 +0000
commit893c3c9e00a5536efcba6663c9c728cd6da5ad6e (patch)
tree87330dd6d3405a2242106e32af08e0d2a84240d8
parentd3c7055b450cb62ddca6859a650f67d4938afb17 (diff)
AndroidTestRunner: uninstall the test when interrupted
If the test runner was interrupted, stop waiting for the test to start or to finish, go fetch the available test results and logcat and uninstall the test app. Also, set CMake TIMEOUT_SIGNAL_NAME to SIGINT and TIMEOUT_SIGNAL_GRACE_PERIOD to 10 seconds to allow enough time to fetch the logs and uninstall the test app. Task-number: QTBUG-106479 Change-Id: I4820cfe58f05d15179b4af819caa92e475881634 Reviewed-by: Alexandru Croitor <[email protected]> (cherry picked from commit 4a3936c33cb2ab9fee2e93cbe99d31daf1cd0cc8) Reviewed-by: Qt Cherry-pick Bot <[email protected]> (cherry picked from commit aecf64eb7b896285d66b22fd725cb11e83f5e807) (cherry picked from commit 3d2265b333b97e9e564833948021306cbc3b1940)
-rw-r--r--cmake/QtTestHelpers.cmake18
-rw-r--r--src/tools/androidtestrunner/main.cpp74
2 files changed, 64 insertions, 28 deletions
diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake
index 98d04e3c967..21ec4f39a7e 100644
--- a/cmake/QtTestHelpers.cmake
+++ b/cmake/QtTestHelpers.cmake
@@ -526,12 +526,12 @@ function(qt_internal_add_test name)
endif()
endif()
- # Pass 95% of the timeout to allow the test runner time to do any cleanup
- # before being killed.
- set(percentage "95")
- qt_internal_get_android_test_timeout("${arg_TIMEOUT}" "${percentage}" android_timeout)
-
if (ANDROID)
+ # Pass 95% of the timeout to allow the test runner time to do any cleanup
+ # before being killed.
+ set(percentage "95")
+ qt_internal_get_android_test_timeout("${arg_TIMEOUT}" "${percentage}" android_timeout)
+
if(arg_BUNDLE_ANDROID_OPENSSL_LIBS)
if(NOT OPENSSL_ROOT_DIR)
message(WARNING "The argument BUNDLE_ANDROID_OPENSSL_LIBS is set "
@@ -635,6 +635,14 @@ function(qt_internal_add_test name)
set_tests_properties(${testname} PROPERTIES TIMEOUT ${arg_TIMEOUT})
endif()
+ if(ANDROID)
+ # Set timeout signal and some time for androidtestrunner to do cleanup
+ set_tests_properties(${testname} PROPERTIES
+ TIMEOUT_SIGNAL_NAME "SIGINT"
+ TIMEOUT_SIGNAL_GRACE_PERIOD 10.0
+ )
+ endif()
+
# Add a ${target}/check makefile target, to more easily test one test.
set(test_config_options "")
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp
index 0dac9b0048a..943ed55ef9b 100644
--- a/src/tools/androidtestrunner/main.cpp
+++ b/src/tools/androidtestrunner/main.cpp
@@ -13,6 +13,13 @@
#include <functional>
#include <atomic>
#include <csignal>
+
+#if defined(Q_OS_WIN32)
+#include <process.h>
+#else
+#include <unistd.h>
+#endif
+
#include <QtCore/QDeadlineTimer>
#include <QtCore/QThread>
#include <QtCore/QProcessEnvironment>
@@ -425,7 +432,10 @@ static bool isRunning() {
return output.indexOf(QLatin1StringView(" " + g_options.package.toUtf8())) > -1;
}
-static void waitForFinished()
+std::atomic<bool> isPackageInstalled { false };
+std::atomic<bool> isTestRunnerInterrupted { false };
+
+static void waitForStartedAndFinished()
{
// wait to start and set PID
QDeadlineTimer startDeadline(10000);
@@ -433,7 +443,7 @@ static void waitForFinished()
if (obtainPid())
break;
QThread::msleep(100);
- } while (!startDeadline.hasExpired());
+ } while (!startDeadline.hasExpired() && !isTestRunnerInterrupted.load());
// Wait to finish
// In 6.5, only value of -1 cause the deadline to never expire.
@@ -443,10 +453,10 @@ static void waitForFinished()
if (!isRunning())
break;
QThread::msleep(250);
- } while (!finishedDeadline.hasExpired());
+ } while (!finishedDeadline.hasExpired() && !isTestRunnerInterrupted.load());
}
-static void obtainSDKVersion()
+static void obtainSdkVersion()
{
// SDK version is necessary, as in SDK 23 pidof is broken, so we cannot obtain the pid.
// Also, Logcat cannot filter by pid in SDK 23, so we don't offer the --show-logcat option.
@@ -607,6 +617,12 @@ static QString getCurrentTimeString()
return QString::fromUtf8(output.simplified());
}
+static bool uninstallTestPackage()
+{
+ return execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand,
+ g_options.package), nullptr, g_options.verbose);
+}
+
struct TestRunnerSystemSemaphore
{
TestRunnerSystemSemaphore() { }
@@ -634,6 +650,13 @@ void sigHandler(int signal)
{
std::signal(signal, SIG_DFL);
testRunnerLock.release();
+ // Ideally we shouldn't be doing such calls from a signal handler,
+ // and we can't use QSocketNotifier because this tool doesn't spin
+ // a main event loop. Since, there's no other alternative to do this,
+ // let's do the cleanup anyway.
+ if (!isPackageInstalled.load())
+ _exit(-1);
+ isTestRunnerInterrupted.store(true);
}
int main(int argc, char *argv[])
@@ -676,15 +699,7 @@ int main(int argc, char *argv[])
return 1;
}
- obtainSDKVersion();
-
- // do not install or run packages while another test is running
- testRunnerLock.acquire();
-
- if (!execCommand(QStringLiteral("%1 install -r -g %2")
- .arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose)) {
- return 1;
- }
+ obtainSdkVersion();
QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml");
g_options.package = packageNameFromAndroidManifest(manifest);
@@ -695,31 +710,44 @@ int main(int argc, char *argv[])
if (!parseTestArgs())
return 1;
+ // do not install or run packages while another test is running
+ testRunnerLock.acquire();
+
+ isPackageInstalled.store(execCommand(QStringLiteral("%1 install -r -g %2")
+ .arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose));
+ if (!isPackageInstalled)
+ return 1;
+
const QString formattedTime = getCurrentTimeString();
// start the tests
const auto startCmd = "%1 %2"_L1.arg(g_options.adbCommand, g_options.testArgs);
- bool res = execCommand(startCmd, nullptr, g_options.verbose);
+ bool success = execCommand(startCmd, nullptr, g_options.verbose);
- waitForFinished();
+ waitForStartedAndFinished();
- if (res)
- res &= pullFiles();
+ if (success) {
+ success &= pullFiles();
+ if (g_options.showLogcatOutput)
+ printLogcat(formattedTime);
+ }
// 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 (!res) {
+ if (!success) {
printLogcat(formattedTime);
printLogcatCrashBuffer(formattedTime);
- } else if (g_options.showLogcatOutput) {
- printLogcat(formattedTime);
}
- res &= execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand, g_options.package),
- nullptr, g_options.verbose);
+ success &= uninstallTestPackage();
fflush(stdout);
testRunnerLock.release();
- return res ? 0 : 1;
+ if (isTestRunnerInterrupted.load()) {
+ qCritical() << "The androidtestrunner was interrupted and the was test cleaned up.";
+ return 1;
+ }
+
+ return success ? 0 : 1;
}