AndroidTestRunner: use QProcess instead of popen()
Using QProcess would make the test runner more robust when dealing with quoted arguments since it won't be using the system shell and handles quoting under the hood. Fixes: QTBUG-105524 Fixes: QTQAINFRA-5703 Change-Id: Ib666ffea33302f1dfc7e8972bd7750f14065c4fc Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
parent
ee874e7ca8
commit
10a706df27
@ -17,8 +17,6 @@ qt_internal_add_tool(${target_name}
|
|||||||
QT_NO_FOREACH
|
QT_NO_FOREACH
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Core
|
Qt::Core
|
||||||
INCLUDE_DIRECTORIES
|
|
||||||
../shared
|
|
||||||
)
|
)
|
||||||
qt_internal_return_unless_building_tools()
|
qt_internal_return_unless_building_tools()
|
||||||
set_target_properties(${target_name} PROPERTIES
|
set_target_properties(${target_name} PROPERTIES
|
||||||
|
@ -17,15 +17,7 @@
|
|||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QProcessEnvironment>
|
#include <QtCore/QProcessEnvironment>
|
||||||
|
|
||||||
#include <shellquote_shared.h>
|
#include <QtCore/QProcess>
|
||||||
|
|
||||||
#ifdef Q_CC_MSVC
|
|
||||||
#define popen _popen
|
|
||||||
#define QT_POPEN_READ "rb"
|
|
||||||
#define pclose _pclose
|
|
||||||
#else
|
|
||||||
#define QT_POPEN_READ "r"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
@ -126,7 +118,7 @@ struct Options
|
|||||||
QString activity;
|
QString activity;
|
||||||
QStringList testArgsList;
|
QStringList testArgsList;
|
||||||
QHash<QString, QString> outFiles;
|
QHash<QString, QString> outFiles;
|
||||||
QString testArgs;
|
QStringList amStarttestArgs;
|
||||||
QString apkPath;
|
QString apkPath;
|
||||||
QString ndkStackPath;
|
QString ndkStackPath;
|
||||||
int sdkVersion = -1;
|
int sdkVersion = -1;
|
||||||
@ -146,28 +138,51 @@ struct Options
|
|||||||
|
|
||||||
static Options g_options;
|
static Options g_options;
|
||||||
|
|
||||||
static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = false)
|
static bool execCommand(const QString &program, const QStringList &args,
|
||||||
|
QByteArray *output = nullptr, bool verbose = false)
|
||||||
{
|
{
|
||||||
if (verbose)
|
const auto command = program + " "_L1 + args.join(u' ');
|
||||||
fprintf(stdout, "Execute %s.\n", command.toUtf8().constData());
|
|
||||||
FILE *process = popen(command.toUtf8().constData(), QT_POPEN_READ);
|
|
||||||
|
|
||||||
if (!process) {
|
if (verbose && g_options.verbose)
|
||||||
|
fprintf(stdout, "Execute %s.\n", command.toUtf8().constData());
|
||||||
|
|
||||||
|
QProcess process;
|
||||||
|
process.start(program, args);
|
||||||
|
if (!process.waitForStarted()) {
|
||||||
fprintf(stderr, "Cannot execute command %s.\n", qPrintable(command));
|
fprintf(stderr, "Cannot execute command %s.\n", qPrintable(command));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char buffer[512];
|
|
||||||
while (fgets(buffer, sizeof(buffer), process)) {
|
// If the command is not adb, for example, make or ninja, it can take more that
|
||||||
if (output)
|
// QProcess::waitForFinished() 30 secs, so for that use a higher timeout.
|
||||||
output->append(buffer);
|
const int FinishTimeout = program.endsWith("adb"_L1) ? 30000 : g_options.timeoutSecs * 1000;
|
||||||
if (verbose)
|
if (!process.waitForFinished(FinishTimeout)) {
|
||||||
fprintf(stdout, "%s", buffer);
|
fprintf(stderr, "Execution of command %s timed out.\n", qPrintable(command));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
const auto stdOut = process.readAllStandardOutput();
|
||||||
fflush(stderr);
|
if (output)
|
||||||
|
output->append(stdOut);
|
||||||
|
|
||||||
return pclose(process) == 0;
|
if (verbose && g_options.verbose)
|
||||||
|
fprintf(stdout, "%s", stdOut.constData());
|
||||||
|
|
||||||
|
return process.exitCode() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool execAdbCommand(const QStringList &args, QByteArray *output = nullptr,
|
||||||
|
bool verbose = true)
|
||||||
|
{
|
||||||
|
return execCommand(g_options.adbCommand, args, output, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = true)
|
||||||
|
{
|
||||||
|
auto args = command.split(u' ');
|
||||||
|
const auto program = args.first();
|
||||||
|
args.removeOne(program);
|
||||||
|
return execCommand(program, args, output, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseOptions()
|
static bool parseOptions()
|
||||||
@ -355,17 +370,20 @@ static bool parseTestArgs()
|
|||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
logType = match.capturedTexts().at(1);
|
logType = match.capturedTexts().at(1);
|
||||||
} else {
|
} else {
|
||||||
unhandledArgs << " %1"_L1.arg(arg).replace("\""_L1, "\\\""_L1);
|
unhandledArgs << " %1"_L1.arg(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g_options.outFiles.isEmpty() || !file.isEmpty() || !logType.isEmpty())
|
if (g_options.outFiles.isEmpty() || !file.isEmpty() || !logType.isEmpty())
|
||||||
setOutputFile(file, logType);
|
setOutputFile(file, logType);
|
||||||
|
|
||||||
|
QString testAppArgs;
|
||||||
for (const auto &format : g_options.outFiles.keys())
|
for (const auto &format : g_options.outFiles.keys())
|
||||||
g_options.testArgs += QStringLiteral(" -o output.%1,%1").arg(format);
|
testAppArgs += "-o output.%1,%1 "_L1.arg(format);
|
||||||
|
|
||||||
g_options.testArgs += unhandledArgs.join(u' ');
|
testAppArgs += unhandledArgs.join(u' ').trimmed();
|
||||||
|
testAppArgs = "'%1'"_L1.arg(testAppArgs);
|
||||||
|
const QString activityName = "%1/%2"_L1.arg(g_options.package).arg(g_options.activity);
|
||||||
|
|
||||||
// Pass over any testlib env vars if set
|
// Pass over any testlib env vars if set
|
||||||
QString testEnvVars;
|
QString testEnvVars;
|
||||||
@ -380,21 +398,19 @@ static bool parseTestArgs()
|
|||||||
testEnvVars = "-e extraenvvars \"%4\""_L1.arg(testEnvVars);
|
testEnvVars = "-e extraenvvars \"%4\""_L1.arg(testEnvVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_options.testArgs = "shell am start -n %1/%2 -e applicationArguments \"%3\" %4"_L1
|
g_options.amStarttestArgs = { "shell"_L1, "am"_L1, "start"_L1,
|
||||||
.arg(g_options.package)
|
"-n"_L1, activityName,
|
||||||
.arg(g_options.activity)
|
"-e"_L1, "applicationArguments"_L1, testAppArgs,
|
||||||
.arg(shellQuote(g_options.testArgs.trimmed()))
|
testEnvVars
|
||||||
.arg(testEnvVars)
|
};
|
||||||
.trimmed();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool obtainPid() {
|
static bool obtainPid() {
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
const auto psCmd = "%1 shell \"ps | grep ' %2'\""_L1.arg(g_options.adbCommand,
|
const QStringList psArgs = { "shell"_L1, "ps | grep ' %1'"_L1.arg(g_options.package) };
|
||||||
shellQuote(g_options.package));
|
if (!execAdbCommand(psArgs, &output, false))
|
||||||
if (!execCommand(psCmd, &output))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QList<QByteArray> lines = output.split(u'\n');
|
const QList<QByteArray> lines = output.split(u'\n');
|
||||||
@ -417,9 +433,8 @@ static bool obtainPid() {
|
|||||||
|
|
||||||
static bool isRunning() {
|
static bool isRunning() {
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
const auto psCmd = "%1 shell \"ps | grep ' %2'\""_L1.arg(g_options.adbCommand,
|
const QStringList psArgs = { "shell"_L1, "ps | grep ' %1'"_L1.arg(g_options.package) };
|
||||||
shellQuote(g_options.package));
|
if (!execAdbCommand(psArgs, &output, false))
|
||||||
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;
|
||||||
@ -449,18 +464,14 @@ static void obtainSDKVersion()
|
|||||||
// SDK version is necessary, as in SDK 23 pidof is broken, so we cannot obtain the pid.
|
// 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.
|
// Also, Logcat cannot filter by pid in SDK 23, so we don't offer the --show-logcat option.
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
const QString command(
|
const QStringList versionArgs = { "shell"_L1, "getprop"_L1, "ro.build.version.sdk"_L1 };
|
||||||
QStringLiteral("%1 shell getprop ro.build.version.sdk").arg(g_options.adbCommand));
|
execAdbCommand(versionArgs, &output, false);
|
||||||
execCommand(command, &output, g_options.verbose);
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
int sdkVersion = output.toInt(&ok);
|
int sdkVersion = output.toInt(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
g_options.sdkVersion = sdkVersion;
|
g_options.sdkVersion = sdkVersion;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Unable to obtain the SDK version of the target.\n");
|
||||||
"Unable to obtain the SDK version of the target. Command \"%s\" "
|
|
||||||
"returned \"%s\"\n",
|
|
||||||
command.toUtf8().constData(), output.constData());
|
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,8 +482,8 @@ static bool pullFiles()
|
|||||||
QByteArray userId;
|
QByteArray userId;
|
||||||
// adb get-current-user command is available starting from API level 26.
|
// adb get-current-user command is available starting from API level 26.
|
||||||
if (g_options.sdkVersion >= 26) {
|
if (g_options.sdkVersion >= 26) {
|
||||||
const QString userIdCmd = "%1 shell cmd activity get-current-user"_L1.arg(g_options.adbCommand);
|
const QStringList userIdArgs = {"shell"_L1, "cmd"_L1, "activity"_L1, "get-current-user"_L1};
|
||||||
if (!execCommand(userIdCmd, &userId)) {
|
if (!execAdbCommand(userIdArgs, &userId)) {
|
||||||
qCritical() << "Error: failed to retrieve the user ID";
|
qCritical() << "Error: failed to retrieve the user ID";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -484,12 +495,11 @@ static bool pullFiles()
|
|||||||
// Get only stdout from cat and get rid of stderr and fail later if the output is empty
|
// Get only stdout from cat and get rid of stderr and fail later if the output is empty
|
||||||
const QString outSuffix = it.key();
|
const QString outSuffix = it.key();
|
||||||
const QString catCmd = "cat files/output.%1 2> /dev/null"_L1.arg(outSuffix);
|
const QString catCmd = "cat files/output.%1 2> /dev/null"_L1.arg(outSuffix);
|
||||||
const QString fullCatCmd = "%1 shell 'run-as %2 --user %3 %4'"_L1.arg(
|
const QStringList fullCatArgs = { "shell"_L1, "run-as %1 --user %2 %3"_L1.arg(
|
||||||
g_options.adbCommand, g_options.package, QString::fromUtf8(userId.simplified()),
|
g_options.package, QString::fromUtf8(userId.simplified()), catCmd) };
|
||||||
catCmd);
|
|
||||||
|
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
if (!execCommand(fullCatCmd, &output)) {
|
if (!execAdbCommand(fullCatArgs, &output, false)) {
|
||||||
qCritical() << "Error: failed to retrieve the test's output.%1 file."_L1.arg(outSuffix);
|
qCritical() << "Error: failed to retrieve the test's output.%1 file."_L1.arg(outSuffix);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -516,14 +526,14 @@ static bool pullFiles()
|
|||||||
|
|
||||||
void printLogcat(const QString &formattedTime)
|
void printLogcat(const QString &formattedTime)
|
||||||
{
|
{
|
||||||
QString logcatCmd = "%1 logcat "_L1.arg(g_options.adbCommand);
|
QStringList logcatArgs = { "logcat"_L1 };
|
||||||
if (g_options.sdkVersion <= 23 || g_options.pid == -1)
|
if (g_options.sdkVersion <= 23 || g_options.pid == -1)
|
||||||
logcatCmd += "-t '%1'"_L1.arg(formattedTime);
|
logcatArgs << "-t"_L1 << formattedTime;
|
||||||
else
|
else
|
||||||
logcatCmd += "-d --pid=%1"_L1.arg(QString::number(g_options.pid));
|
logcatArgs << "-d"_L1 << "--pid=%1"_L1.arg(QString::number(g_options.pid));
|
||||||
|
|
||||||
QByteArray logcat;
|
QByteArray logcat;
|
||||||
if (!execCommand(logcatCmd, &logcat)) {
|
if (!execAdbCommand(logcatArgs, &logcat, false)) {
|
||||||
qCritical() << "Error: failed to fetch logcat of the test";
|
qCritical() << "Error: failed to fetch logcat of the test";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -540,9 +550,9 @@ void printLogcat(const QString &formattedTime)
|
|||||||
|
|
||||||
static QString getDeviceABI()
|
static QString getDeviceABI()
|
||||||
{
|
{
|
||||||
const QString abiCmd = "%1 shell getprop ro.product.cpu.abi"_L1.arg(g_options.adbCommand);
|
const QStringList abiArgs = { "shell"_L1, "getprop"_L1, "ro.product.cpu.abi"_L1 };
|
||||||
QByteArray abi;
|
QByteArray abi;
|
||||||
if (!execCommand(abiCmd, &abi)) {
|
if (!execAdbCommand(abiArgs, &abi, false)) {
|
||||||
qWarning() << "Warning: failed to get the device abi, fallback to first libs dir";
|
qWarning() << "Warning: failed to get the device abi, fallback to first libs dir";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -552,10 +562,10 @@ static QString getDeviceABI()
|
|||||||
|
|
||||||
void printLogcatCrashBuffer(const QString &formattedTime)
|
void printLogcatCrashBuffer(const QString &formattedTime)
|
||||||
{
|
{
|
||||||
QString crashCmd = "%1 logcat -b crash -t '%2'"_L1.arg(g_options.adbCommand, formattedTime);
|
bool useNdkStack = false;
|
||||||
|
auto libsPath = "%1/libs/"_L1.arg(g_options.buildPath);
|
||||||
|
|
||||||
if (!g_options.ndkStackPath.isEmpty()) {
|
if (!g_options.ndkStackPath.isEmpty()) {
|
||||||
auto libsPath = "%1/libs/"_L1.arg(g_options.buildPath);
|
|
||||||
QString abi = getDeviceABI();
|
QString abi = getDeviceABI();
|
||||||
if (abi.isEmpty()) {
|
if (abi.isEmpty()) {
|
||||||
QStringList subDirs = QDir(libsPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
QStringList subDirs = QDir(libsPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
@ -565,7 +575,7 @@ void printLogcatCrashBuffer(const QString &formattedTime)
|
|||||||
|
|
||||||
if (!abi.isEmpty()) {
|
if (!abi.isEmpty()) {
|
||||||
libsPath += abi;
|
libsPath += abi;
|
||||||
crashCmd += " | %1 -sym %2"_L1.arg(g_options.ndkStackPath, libsPath);
|
useNdkStack = true;
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Warning: failed to get the libs abi, ndk-stack cannot be used.";
|
qWarning() << "Warning: failed to get the libs abi, ndk-stack cannot be used.";
|
||||||
}
|
}
|
||||||
@ -574,30 +584,57 @@ void printLogcatCrashBuffer(const QString &formattedTime)
|
|||||||
"using the ANDROID_NDK_ROOT environment variable.";
|
"using the ANDROID_NDK_ROOT environment variable.";
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray crashLogcat;
|
QProcess adbCrashProcess;
|
||||||
if (!execCommand(crashCmd, &crashLogcat)) {
|
QProcess ndkStackProcess;
|
||||||
qCritical() << "Error: failed to fetch logcat crash buffer";
|
|
||||||
|
if (useNdkStack) {
|
||||||
|
adbCrashProcess.setStandardOutputProcess(&ndkStackProcess);
|
||||||
|
ndkStackProcess.start(g_options.ndkStackPath, { "-sym"_L1, libsPath });
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList adbCrashArgs = { "logcat"_L1, "-b"_L1, "crash"_L1, "-t"_L1, formattedTime };
|
||||||
|
adbCrashProcess.start(g_options.adbCommand, adbCrashArgs);
|
||||||
|
|
||||||
|
if (!adbCrashProcess.waitForStarted()) {
|
||||||
|
qCritical() << "Error: failed to run adb logcat crash command.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crashLogcat.isEmpty()) {
|
if (useNdkStack && !ndkStackProcess.waitForStarted()) {
|
||||||
qDebug() << "The retrieved logcat crash buffer is empty";
|
qCritical() << "Error: failed to run ndk-stack command.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adbCrashProcess.waitForFinished()) {
|
||||||
|
qCritical() << "Error: adb command timed out.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useNdkStack && !ndkStackProcess.waitForFinished()) {
|
||||||
|
qCritical() << "Error: ndk-stack command timed out.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray crash = useNdkStack ? ndkStackProcess.readAllStandardOutput()
|
||||||
|
: adbCrashProcess.readAllStandardOutput();
|
||||||
|
if (crash.isEmpty()) {
|
||||||
|
qWarning() << "The retrieved crash logcat is empty";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "****** Begin logcat crash buffer output ******";
|
qDebug() << "****** Begin logcat crash buffer output ******";
|
||||||
qDebug().noquote() << crashLogcat;
|
qDebug().noquote() << crash;
|
||||||
qDebug() << "****** End logcat crash buffer output ******";
|
qDebug() << "****** End logcat crash buffer output ******";
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString getCurrentTimeString()
|
static QString getCurrentTimeString()
|
||||||
{
|
{
|
||||||
const QString timeFormat = (g_options.sdkVersion <= 23) ?
|
const QString timeFormat = (g_options.sdkVersion <= 23) ?
|
||||||
"%m-%d\\ %H:%M:%S.000"_L1 : "%Y-%m-%d\\ %H:%M:%S.%3N"_L1;
|
"%m-%d %H:%M:%S.000"_L1 : "%Y-%m-%d %H:%M:%S.%3N"_L1;
|
||||||
|
|
||||||
QString dateCmd = "%1 shell date +'%2'"_L1.arg(g_options.adbCommand, timeFormat);
|
QStringList dateArgs = { "shell"_L1, "date"_L1, "+'%1'"_L1.arg(timeFormat) };
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
if (!execCommand(dateCmd, &output)) {
|
if (!execAdbCommand(dateArgs, &output, false)) {
|
||||||
qWarning() << "Date/time adb command failed";
|
qWarning() << "Date/time adb command failed";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -655,15 +692,13 @@ int main(int argc, char *argv[])
|
|||||||
if (!execCommand(g_options.makeCommand, nullptr, true)) {
|
if (!execCommand(g_options.makeCommand, nullptr, true)) {
|
||||||
if (!g_options.skipAddInstallRoot) {
|
if (!g_options.skipAddInstallRoot) {
|
||||||
// we need to run make INSTALL_ROOT=path install to install the application file(s) first
|
// we need to run make INSTALL_ROOT=path install to install the application file(s) first
|
||||||
if (!execCommand(QStringLiteral("%1 INSTALL_ROOT=%2 install")
|
if (!execCommand(QStringLiteral("%1 INSTALL_ROOT=%2 install").arg(g_options.makeCommand,
|
||||||
.arg(g_options.makeCommand, QDir::toNativeSeparators(g_options.buildPath)), nullptr, g_options.verbose)) {
|
QDir::toNativeSeparators(g_options.buildPath)), nullptr)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!execCommand(QStringLiteral("%1")
|
if (!execCommand(g_options.makeCommand, nullptr))
|
||||||
.arg(g_options.makeCommand), nullptr, g_options.verbose)) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,10 +715,9 @@ int main(int argc, char *argv[])
|
|||||||
// do not install or run packages while another test is running
|
// do not install or run packages while another test is running
|
||||||
testRunnerLock.acquire();
|
testRunnerLock.acquire();
|
||||||
|
|
||||||
if (!execCommand(QStringLiteral("%1 install -r -g %2")
|
const QStringList installArgs = { "install"_L1, "-r"_L1, "-g"_L1, g_options.apkPath };
|
||||||
.arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose)) {
|
if (!execAdbCommand(installArgs, nullptr))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml");
|
QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml");
|
||||||
g_options.package = packageNameFromAndroidManifest(manifest);
|
g_options.package = packageNameFromAndroidManifest(manifest);
|
||||||
@ -697,8 +731,7 @@ int main(int argc, char *argv[])
|
|||||||
const QString formattedTime = getCurrentTimeString();
|
const QString formattedTime = getCurrentTimeString();
|
||||||
|
|
||||||
// start the tests
|
// start the tests
|
||||||
const auto startCmd = "%1 %2"_L1.arg(g_options.adbCommand, g_options.testArgs);
|
bool res = execAdbCommand(g_options.amStarttestArgs, nullptr);
|
||||||
bool res = execCommand(startCmd, nullptr, g_options.verbose);
|
|
||||||
|
|
||||||
waitForFinished();
|
waitForFinished();
|
||||||
|
|
||||||
@ -714,8 +747,7 @@ int main(int argc, char *argv[])
|
|||||||
printLogcat(formattedTime);
|
printLogcat(formattedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
res &= execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand, g_options.package),
|
res &= execAdbCommand({ "uninstall"_L1, g_options.package }, nullptr);
|
||||||
nullptr, g_options.verbose);
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
testRunnerLock.release();
|
testRunnerLock.release();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user