Fix android and robocop mach commands draft
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Mon, 27 Apr 2015 17:59:53 -0400
changeset 260519 7675e7faba0dfcecda22145f71ee5e55befc5b84
parent 260517 29d191d08485cbc7f75f5c836b0b3116764422ae
child 506381 b1f813377e94a6d8a4dff4f4ff3cdaee7a48a823
push id1817
push userahalberstadt@mozilla.com
push dateThu, 30 Apr 2015 16:08:11 +0000
milestone40.0a1
Fix android and robocop mach commands
testing/config/mozharness/android_arm_4_3_config.py
testing/config/mozharness/android_arm_config.py
testing/mochitest/mach_commands.py
testing/mochitest/mochitest_options.py
testing/mochitest/runtestsremote.py
--- a/testing/config/mozharness/android_arm_4_3_config.py
+++ b/testing/config/mozharness/android_arm_4_3_config.py
@@ -31,19 +31,19 @@ config = {
             "run_filename": "runtestsremote.py",
             "testsdir": "mochitest",
             "options": ["--dm_trans=adb", "--app=%(app)s", "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s",
                 "--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s",
                 "--quiet", "--log-raw=%(raw_log_file)s",
                 "--total-chunks=4",
-                "--robocop-path=../..",
+                "--robocop-apk=../../robocop.apk",
                 "--robocop-ids=fennec_ids.txt",
-                "--robocop=robocop.ini",
+                "--robocop-ini=robocop.ini",
             ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [ "--app=%(app)s", "--ignore-window-size",
                 "--dm_trans=adb",
                 "--bootstrap",
--- a/testing/config/mozharness/android_arm_config.py
+++ b/testing/config/mozharness/android_arm_config.py
@@ -34,19 +34,19 @@ config = {
             "testsdir": "mochitest",
             "options": ["--dm_trans=sut", "--app=%(app)s", "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s", "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s",
                 "--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s",
                 "--quiet", "--log-raw=%(raw_log_file)s",
                 "--total-chunks=4",
-                "--robocop-path=../..",
+                "--robocop-apk=../../robocop.apk",
                 "--robocop-ids=fennec_ids.txt",
-                "--robocop=robocop.ini",
+                "--robocop-ini=robocop.ini",
             ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [ "--app=%(app)s", "--ignore-window-size",
                 "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -276,27 +276,31 @@ class MochitestRunner(MozbuildObject):
             options.manifestFile = manifest
 
         # We need this to enable colorization of output.
         self.log_manager.enable_unstructured()
         result = mochitest.run_test_harness(options)
         self.log_manager.disable_unstructured()
         return result
 
-    def run_android_test(self, args):
+    def run_android_test(self, test_path, **kwargs):
         self.tests_dir = os.path.join(self.topobjdir, '_tests')
         self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
         import imp
         path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
         with open(path, 'r') as fh:
             imp.load_module('runtestsremote', fh, path,
                             ('.py', 'r', imp.PY_SOURCE))
         import runtestsremote
 
-        sys.exit(runtestsremote.main(args))
+        options = Namespace(**kwargs)
+        if test_path:
+            options.testPath = test_path
+
+        sys.exit(runtestsremote.run_test_harness(options))
 
 
 # parser
 
 def TestPathArg(func):
     test_paths = CommandArgument('test_paths', nargs='*', metavar='TEST', default=None,
         help='Test to run. Can be a single test file or a directory of tests to '
              '(run recursively). If omitted, the entire suite is run.')
@@ -593,83 +597,51 @@ class MachCommands(MachCommandBase):
         self._ensure_state_subdir_exists('.')
 
         driver = self._spawn(BuildDriver)
         driver.install_tests(remove=False)
 
         mochitest = self._spawn(MochitestRunner)
         return mochitest.run_b2g_test(test_paths=test_paths, **kwargs)
 
-    def run_mochitest_android(self, test_paths, chrome=False, **kwargs):
+    def run_mochitest_android(self, test_paths, **kwargs):
         host_ret = verify_host_bin()
         if host_ret != 0:
             return host_ret
 
-        args = [
-            '--xre-path=' + os.environ.get('MOZ_HOST_BIN'),
-            '--dm_trans=adb',
-            '--deviceIP=',
-            '--console-level=INFO',
-            '--app=' + self.substs['ANDROID_PACKAGE_NAME'],
-            '--log-mach=-',
-            '--autorun',
-            '--close-when-done',
-            '--testing-modules-dir=' + os.path.join(self.topobjdir, '_tests', 'modules'),
-        ]
+        test_path = None
         if test_paths:
             if len(test_paths) > 1:
                 print('Warning: Only the first test path will be used.')
             test_path = self._wrap_path_argument(test_paths[0]).relpath()
-            args.append('--test-path=%s' % test_path)
-        if chrome:
-            args.append('--chrome')
 
         mochitest = self._spawn(MochitestRunner)
-        return mochitest.run_android_test(args)
+        return mochitest.run_android_test(test_path, **kwargs)
 
 
 @CommandProvider
 class AndroidCommands(MachCommandBase):
 
     @Command('robocop', category='testing',
              conditions=[conditions.is_android],
-             description='Run a Robocop test.')
+             description='Run a Robocop test.',
+             parser=setup_argument_parser)
     @CommandArgument(
         'test_path',
         default=None,
         nargs='?',
         metavar='TEST',
         help='Test to run. Can be specified as a Robocop test name (like "testLoad"), '
         'or omitted. If omitted, the entire test suite is executed.')
-    def run_robocop(self, test_path):
+    def run_robocop(self, test_path, **kwargs):
         host_ret = verify_host_bin()
         if host_ret != 0:
             return host_ret
 
-        args = [
-            '--xre-path=' + os.environ.get('MOZ_HOST_BIN'),
-            '--dm_trans=adb',
-            '--deviceIP=',
-            '--console-level=INFO',
-            '--app=' +
-            self.substs['ANDROID_PACKAGE_NAME'],
-            '--robocop-apk=' +
-            os.path.join(
-                self.topobjdir,
-                'build',
-                'mobile',
-                'robocop',
-                'robocop-debug.apk'),
-            '--robocop-ini=' +
-            os.path.join(
-                self.topobjdir,
-                'build',
-                'mobile',
-                'robocop',
-                'robocop.ini'),
-            '--log-mach=-',
-        ]
+        if not kwargs.get('robocopIni'):
+            kwargs['robocopIni'] = os.path.join(self.topobjdir, 'build', 'mobile',
+                                                'robocop', 'robocop.ini')
 
-        if test_path:
-            args.append('--test-path=%s' % test_path)
-
+        if not kwargs.get('robocopApk'):
+            kwargs['robocopApk'] = os.path.join(self.topobjdir, 'build', 'mobile',
+                                                'robocop', 'robocop-debug.apk')
         mochitest = self._spawn(MochitestRunner)
-        return mochitest.run_android_test(args)
+        return mochitest.run_android_test(test_path, **kwargs)
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -513,17 +513,17 @@ class MochitestArguments(ArgumentContain
         'webSocketPort': '9988',
         # The default websocket port is incorrect in mozprofile; it is
         # set to the SSL proxy setting. See:
         # see https://bugzilla.mozilla.org/show_bug.cgi?id=916517
         # args.webSocketPort = DEFAULT_PORTS['ws']
     }
 
     def validate(self, parser, options, context):
-        """ verify correct options and cleanup paths """
+        """Validate generic options."""
 
         # for test manifest parsing.
         mozinfo.update({"strictContentSandbox": options.strictContentSandbox})
         # for test manifest parsing.
         mozinfo.update({"nested_oop": options.nested_oop})
 
         # b2g and android don't use 'app' the same way, so skip validation
         if parser.app not in ('b2g', 'android'):
@@ -845,16 +845,18 @@ class B2GArguments(ArgumentContainer):
     defaults = {
         'logFile': 'mochitest.log',
         'extensionsToExclude': ['specialpowers'],
         # See dependencies of bug 1038943.
         'defaultLeakThreshold': 5536,
     }
 
     def validate(self, parser, options, context):
+        """Validate b2g options."""
+
         if options.desktop and not options.app:
             if not (build_obj and conditions.is_b2g_desktop(build_obj)):
                 parser.error(
                     "--desktop specified, but no b2g desktop build detected! Either "
                     "build for b2g desktop, or point --appname to a b2g desktop binary.")
         elif build_obj and conditions.is_b2g_desktop(build_obj):
             options.desktop = True
             if not options.app:
@@ -945,96 +947,93 @@ class AndroidArguments(ArgumentContainer
          {"dest": "deviceSerial",
           "help": "ip address of remote device to test",
           "default": None,
           }],
         [["--dm_trans"],
          {"choices": ["adb", "sut"],
           "default": "adb",
           "help": "The transport to use for communication with the device [default: adb].",
+          "suppress": True,
           }],
         [["--devicePort"],
          {"dest": "devicePort",
           "type": int,
           "default": 20701,
           "help": "port of remote device to test",
           }],
         [["--remote-product-name"],
          {"dest": "remoteProductName",
           "default": "fennec",
           "help": "The executable's name of remote product to test - either \
                    fennec or firefox, defaults to fennec",
+          "suppress": True,
           }],
         [["--remote-logfile"],
          {"dest": "remoteLogFile",
           "default": None,
           "help": "Name of log file on the device relative to the device \
                    root. PLEASE ONLY USE A FILENAME.",
           }],
         [["--remote-webserver"],
          {"dest": "remoteWebServer",
           "default": None,
           "help": "ip address where the remote web server is hosted at",
           }],
         [["--http-port"],
          {"dest": "httpPort",
           "default": DEFAULT_PORTS['http'],
           "help": "http port of the remote web server",
+          "suppress": True,
           }],
         [["--ssl-port"],
          {"dest": "sslPort",
           "default": DEFAULT_PORTS['https'],
           "help": "ssl port of the remote web server",
+          "suppress": True,
           }],
         [["--robocop-ini"],
          {"dest": "robocopIni",
           "default": "",
           "help": "name of the .ini file containing the list of tests to run",
           }],
-        [["--robocop"],
-         {"dest": "robocop",
-          "default": "",
-          "help": "name of the .ini file containing the list of tests to run. \
-                   [DEPRECATED- please use --robocop-ini",
-          }],
         [["--robocop-apk"],
          {"dest": "robocopApk",
           "default": "",
           "help": "name of the Robocop APK to use for ADB test running",
           }],
-        [["--robocop-path"],
-         {"dest": "robocopPath",
-          "default": "",
-          "help": "Path to the folder where robocop.apk is located at. \
-                   Primarily used for ADB test running. \
-                   [DEPRECATED- please use --robocop-apk]",
-          }],
         [["--robocop-ids"],
          {"dest": "robocopIds",
           "default": "",
           "help": "name of the file containing the view ID map \
                    (fennec_ids.txt)",
           }],
         [["--remoteTestRoot"],
          {"dest": "remoteTestRoot",
           "default": None,
           "help": "remote directory to use as test root \
                    (eg. /mnt/sdcard/tests or /data/local/tests)",
+          "suppress": True,
           }],
     ]
 
     defaults = {
         'dm': None,
         'logFile': 'mochitest.log',
         'utilityPath': None,
     }
 
     def validate(self, parser, options, context):
+        """Validate android options."""
+
+        if build_obj:
+            options.log_mach = '-'
+
         if options.dm_trans == "adb":
-            if (options.deviceIP):
+            if options.deviceIP:
                 options.dm = DroidADB(
                     options.deviceIP,
                     options.devicePort,
                     deviceRoot=options.remoteTestRoot)
             elif options.deviceSerial:
                 options.dm = DroidADB(
                     None,
                     None,
@@ -1073,53 +1072,46 @@ class AndroidArguments(ArgumentContainer
                 '/' + options.remoteLogFile
 
         if options.remoteAppPath and options.app:
             parser.error(
                 "You cannot specify both the remoteAppPath and the app setting")
         elif options.remoteAppPath:
             options.app = options.remoteTestRoot + "/" + options.remoteAppPath
         elif options.app is None:
-            # Neither remoteAppPath nor app are set -- error
-            parser.error("You must specify either appPath or app")
+            if build_obj:
+                options.app = build_obj.substs['ANDROID_PACKAGE_NAME']
+            else:
+                # Neither remoteAppPath nor app are set -- error
+                parser.error("You must specify either appPath or app")
+
+        if 'MOZ_HOST_BIN' in os.environ:
+            options.xrePath = os.environ['MOZ_HOST_BIN']
 
         # Only reset the xrePath if it wasn't provided
         if options.xrePath is None:
             options.xrePath = options.utilityPath
 
         if options.pidFile != "":
             f = open(options.pidFile, 'w')
             f.write("%s" % os.getpid())
             f.close()
 
-        # Robocop specific deprecated options.
-        if options.robocop:
-            if options.robocopIni:
-                parser.error(
-                    "can not use deprecated --robocop and replacement --robocop-ini together")
-            options.robocopIni = options.robocop
-            del options.robocop
-
-        if options.robocopPath:
-            if options.robocopApk:
-                parser.error(
-                    "can not use deprecated --robocop-path and replacement --robocop-apk together")
-            options.robocopApk = os.path.join(
-                options.robocopPath,
-                'robocop.apk')
-            del options.robocopPath
-
         # Robocop specific options
         if options.robocopIni != "":
             if not os.path.exists(options.robocopIni):
                 parser.error(
                     "Unable to find specified robocop .ini manifest '%s'" %
                     options.robocopIni)
             options.robocopIni = os.path.abspath(options.robocopIni)
 
+            if not options.robocopApk and build_obj:
+                options.robocopApk = os.path.join(build_obj.topobjdir, 'build', 'mobile',
+                                                  'robocop', 'robocop-debug.apk')
+
         if options.robocopApk != "":
             if not os.path.exists(options.robocopApk):
                 parser.error(
                     "Unable to find robocop APK '%s'" %
                     options.robocopApk)
             options.robocopApk = os.path.abspath(options.robocopApk)
 
         if options.robocopIds != "":
@@ -1165,17 +1157,17 @@ class MochitestArgumentParser(ArgumentPa
                 self.app = 'android'
             elif conditions.is_b2g(build_obj):
                 self.app = 'b2g'
         if not self.app:
             # platform can't be determined and app wasn't specified explicitly,
             # so just use generic arguments and hope for the best
             self.app = 'generic'
 
-        if self.app not in container_map.keys():
+        if self.app not in container_map:
             self.error("Unrecognized app '{}'! Must be one of: {}".format(
                 self.app, ', '.join(container_map.keys())))
 
         defaults = {}
         for container in self.containers:
             defaults.update(container.defaults)
             group = self.add_argument_group(container.__class__.__name__, container.__doc__)
 
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -454,24 +454,21 @@ class MochiRemote(Mochitest):
         kwargs['runSSLTunnel'] = False
 
         if 'quiet' in kwargs:
             kwargs.pop('quiet')
 
         return self._automation.runApp(*args, **kwargs)
 
 
-def main(args):
+def run_test_harness(options):
     message_logger = MessageLogger(logger=None)
     process_args = {'messageLogger': message_logger}
     auto = RemoteAutomation(None, "fennec", processArgs=process_args)
 
-    parser = MochitestArgumentParser(app='android')
-    options = parser.parse_args(args)
-
     dm = options.dm
     auto.setDeviceManager(dm)
     mochitest = MochiRemote(auto, dm, options)
 
     log = mochitest.log
     message_logger.logger = log
     mochitest.message_logger = message_logger
 
@@ -708,10 +705,17 @@ def main(args):
 
         mochitest.printDeviceInfo(printLogcat=True)
 
     message_logger.finish()
 
     return retVal
 
 
+def main(args=sys.argv[1:]):
+    parser = MochitestArgumentParser(app='android')
+    options = parser.parse_args(args)
+
+    return run_test_harness(options)
+
+
 if __name__ == "__main__":
-    sys.exit(main(sys.argv[1:]))
+    sys.exit(main())