Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-105524

androidtestrunner: don't execute subcommand using popen() in order to avoid shell-quoting

    XMLWordPrintable

Details

    • 10a706df2 (dev), 2e3b4fc53 (dev), a1b1759ab (dev), 73521467d (6.7)
    • 2023wk48FOQtforAndroid

    Description

      Currently androidtestrunner invokes popen() with a large complicated multi-quoted string as argument:

      • /Users/user/Library/Android/sdk/platform-tools/adb shell am start -e applicationArguments "'-o output.xml,xml -o output.txt,txt \"levelOfDetail:4:1, 4:1\"'" -n org.qtproject.example.tst_qgraphicsview/org.qtproject.qt.android.bindings.QtActivity

      This is needed since popen() calls the system shell (bash) and passes this string to it. Instead we can invoke the adb command directly with this list of arguments:

      • shell
      • am
      • start
      • -e
      • applicationArguments
      • -o output.xml,xml -o output.txt,txt "levelOfDetail:4:1, 4:1"
      • -n
      • org.qtproject.example.tst_qgraphicsview/org.qtproject.qt.android.bindings.QtActivity

      We can definitely avoid one level of quotes by avoiding bash. Possibly some extra quoting is needed because of `adb shell` itself, experiments are needed to decide that.

      Current code

      static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = false)
      {
          if (verbose)
              fprintf(stdout, "Execute %s.\n", command.toUtf8().constData());
          FILE *process = popen(command.toUtf8().constData(), QT_POPEN_READ);
          if (!process) {
              fprintf(stderr, "Cannot execute command %s.\n", qPrintable(command));
              return false;
          }
          char buffer[512];
          while (fgets(buffer, sizeof(buffer), process)) {
              if (output)
                  output->append(buffer);
              if (verbose)
                  fprintf(stdout, "%s", buffer);
          }
          fflush(stdout);
          fflush(stderr);
          return pclose(process) == 0;
      }
      

      [ and later ...]

      int main(int argc, char *argv[])
      {
          // [ ... ]
      
          // start the tests
          bool res = execCommand(QStringLiteral("%1 %2").arg(g_options.adbCommand, g_options.testArgs),
                                 nullptr, g_options.verbose)
                  && waitToFinish();
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              assam Assam Boudjelthia
              jimis Dimitrios Apostolou
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes