AndroidTestRunner: use proper file names for output files

On device, use proper file names the same as the one passed
to the test. Also, along the way, make sure to also pull the
output of the same format of the stdout result. Currently,
it's not the case, for example, if we pass `-o name.txt,txt -o -,txt`,
the name.txt is not being pulled from the device, and
with this patch it will be.

Change-Id: I5ecd22e6c37e5abfbe68b19ae102a852b01dd7e0
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
(cherry picked from commit 61468b3411c6f88180a9b22535f420beada97495)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Assam Boudjelthia 2024-10-21 18:24:39 +03:00 committed by Qt Cherry-pick Bot
parent fb3ee1ac25
commit a3376af2c7

View File

@ -12,6 +12,7 @@
#include <QtCore/QSystemSemaphore> #include <QtCore/QSystemSemaphore>
#include <QtCore/QThread> #include <QtCore/QThread>
#include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamReader>
#include <QtCore/QFileInfo>
#include <atomic> #include <atomic>
#include <csignal> #include <csignal>
@ -41,7 +42,7 @@ struct Options
QString package; QString package;
QString activity; QString activity;
QStringList testArgsList; QStringList testArgsList;
QString stdoutFormat; QString stdoutFileName;
QHash<QString, QString> outFiles; QHash<QString, QString> outFiles;
QStringList amStarttestArgs; QStringList amStarttestArgs;
QString apkPath; QString apkPath;
@ -266,15 +267,20 @@ static QString activityFromAndroidManifest(const QString &androidManifestPath)
static void setOutputFile(QString file, QString format) static void setOutputFile(QString file, QString format)
{ {
if (file.isEmpty())
file = u'-';
if (format.isEmpty()) if (format.isEmpty())
format = "txt"_L1; format = "txt"_L1;
if (file == u'-') if ((file.isEmpty() || file == u'-')) {
g_options.stdoutFormat = format; if (g_options.outFiles.contains(format)) {
file = g_options.outFiles.value(format);
g_options.outFiles[format] = file; } else {
file = "stdout.%1"_L1.arg(format);
g_options.outFiles[format] = file;
}
g_options.stdoutFileName = QFileInfo(file).fileName();
} else {
g_options.outFiles[format] = file;
}
} }
static bool parseTestArgs() static bool parseTestArgs()
@ -321,8 +327,8 @@ static bool parseTestArgs()
setOutputFile(file, logType); setOutputFile(file, logType);
QString testAppArgs; QString testAppArgs;
for (const auto &format : g_options.outFiles.keys()) for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.constEnd(); ++it)
testAppArgs += "-o output.%1,%1 "_L1.arg(format); testAppArgs += "-o %1,%2 "_L1.arg(QFileInfo(it.value()).fileName(), it.key());
testAppArgs += unhandledArgs.join(u' ').trimmed(); testAppArgs += unhandledArgs.join(u' ').trimmed();
testAppArgs = "\"%1\""_L1.arg(testAppArgs.trimmed()); testAppArgs = "\"%1\""_L1.arg(testAppArgs.trimmed());
@ -410,7 +416,7 @@ static void waitForStarted()
static void waitForLoggingStarted() static void waitForLoggingStarted()
{ {
const QString lsCmd = "ls files/output.%1"_L1.arg(g_options.stdoutFormat); const QString lsCmd = "ls files/%1"_L1.arg(g_options.stdoutFileName);
const QStringList adbLsCmd = { "shell"_L1, runCommandAsUserArgs(lsCmd) }; const QStringList adbLsCmd = { "shell"_L1, runCommandAsUserArgs(lsCmd) };
QDeadlineTimer deadline(5000); QDeadlineTimer deadline(5000);
@ -424,7 +430,7 @@ static void waitForLoggingStarted()
static bool setupStdoutLogger() static bool setupStdoutLogger()
{ {
// Start tail to get results to stdout as soon as they're available // Start tail to get results to stdout as soon as they're available
const QString tailPipeCmd = "tail -n +1 -f files/output.%1"_L1.arg(g_options.stdoutFormat); const QString tailPipeCmd = "tail -n +1 -f files/%1"_L1.arg(g_options.stdoutFileName);
const QStringList adbTailCmd = { "shell"_L1, runCommandAsUserArgs(tailPipeCmd) }; const QStringList adbTailCmd = { "shell"_L1, runCommandAsUserArgs(tailPipeCmd) };
g_options.stdoutLogger.emplace(); g_options.stdoutLogger.emplace();
@ -530,10 +536,11 @@ static QStringList runningDevices()
static bool pullResults() static bool pullResults()
{ {
for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.end(); ++it) { for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.constEnd(); ++it) {
const QString filePath = it.value();
const QString fileName = QFileInfo(filePath).fileName();
// 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 catCmd = "cat files/%1 2> /dev/null"_L1.arg(fileName);
const QString catCmd = "cat files/output.%1 2> /dev/null"_L1.arg(outSuffix);
const QStringList fullCatArgs = { "shell"_L1, runCommandAsUserArgs(catCmd) }; const QStringList fullCatArgs = { "shell"_L1, runCommandAsUserArgs(catCmd) };
bool catSuccess = false; bool catSuccess = false;
@ -548,21 +555,21 @@ static bool pullResults()
} }
if (!catSuccess) { if (!catSuccess) {
qCritical() << "Error: failed to retrieve the test's output.%1 file."_L1.arg(outSuffix); qCritical() << "Error: failed to retrieve the test result file %1."_L1.arg(fileName);
return false; return false;
} }
if (output.isEmpty()) { if (output.isEmpty()) {
qCritical() << "Error: the test's output.%1 is empty."_L1.arg(outSuffix); qCritical() << "Error: the test result file %1 is empty."_L1.arg(fileName);
return false; return false;
} }
if (it.value() != u'-') { QFile out{filePath};
QFile out{it.value()}; if (!out.open(QIODevice::WriteOnly)) {
if (!out.open(QIODevice::WriteOnly)) qCritical() << "Error: failed to open %1 to write results to host."_L1.arg(filePath);
return false; return false;
out.write(output);
} }
out.write(output);
} }
return true; return true;