Esempio n. 1
0
  def SetUp(self):
    available_devices = device_utils.DeviceUtils.HealthyDevices(
        self._blacklist, enable_device_files_cache=self._enable_device_cache)
    if not available_devices:
      raise device_errors.NoDevicesError
    if self._device_serial:
      self._devices = [d for d in available_devices
                       if d.adb.GetDeviceSerial() == self._device_serial]
      if not self._devices:
        raise device_errors.DeviceUnreachableError(
            'Could not find device %r' % self._device_serial)
    else:
      self._devices = available_devices

    if self._enable_device_cache:
      for d in self._devices:
        cache_path = _DeviceCachePath(d)
        if os.path.exists(cache_path):
          logging.info('Using device cache: %s', cache_path)
          with open(cache_path) as f:
            d.LoadCacheData(f.read())
          os.unlink(cache_path)
    if self._logcat_output_dir:
      for d in self._devices:
        logcat_file = os.path.join(
            self._logcat_output_dir,
            '%s_%s' % (d.adb.GetDeviceSerial(),
                       datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S')))
        monitor = logcat_monitor.LogcatMonitor(
            d.adb, clear=True, output_file=logcat_file)
        self._logcat_monitors.append(monitor)
        monitor.Start()
    def _ArchiveLogcat(self, device, test):
        if isinstance(test, str):
            desc = test
        else:
            desc = hash(tuple(test))

        stream_name = 'logcat_%s_%s_%s' % (
            desc, time.strftime('%Y%m%dT%H%M%S-UTC',
                                time.gmtime()), device.serial)

        logcat_file = None
        logmon = None
        try:
            with self._env.output_manager.ArchivedTempfile(
                    stream_name, 'logcat') as logcat_file:
                with logcat_monitor.LogcatMonitor(
                        device.adb,
                        filter_specs=local_device_environment.LOGCAT_FILTERS,
                        output_file=logcat_file.name,
                        check_error=False) as logmon:
                    with contextlib_ext.Optional(trace_event.trace(str(test)),
                                                 self._env.trace_output):
                        yield logcat_file
        finally:
            if logmon:
                logmon.Close()
            if logcat_file and logcat_file.Link():
                logging.info('Logcat saved to %s', logcat_file.Link())
Esempio n. 3
0
  def _ArchiveLogcat(self, device, test_name):
    stream_name = 'logcat_%s_%s_%s' % (
        test_name.replace('#', '.'),
        time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()),
        device.serial)

    logcat_file = None
    logmon = None
    try:
      with self._env.output_manager.ArchivedTempfile(
          stream_name, 'logcat') as logcat_file:
        with logcat_monitor.LogcatMonitor(
            device.adb,
            filter_specs=local_device_environment.LOGCAT_FILTERS,
            output_file=logcat_file.name,
            transform_func=self._test_instance.MaybeDeobfuscateLines,
            check_error=False) as logmon:
          with _LogTestEndpoints(device, test_name):
            with contextlib_ext.Optional(
                trace_event.trace(test_name),
                self._env.trace_output):
              yield logcat_file
    finally:
      if logmon:
        logmon.Close()
      if logcat_file and logcat_file.Link():
        logging.info('Logcat saved to %s', logcat_file.Link())
Esempio n. 4
0
  def SetUpProcess(cls):
    """Prepares the test device"""
    super(WebViewCrxSmokeTests, cls).SetUpProcess()
    assert cls._finder_options.crx_file, '--crx-file is required'
    assert cls._finder_options.component_name, '--component-name is required'

    cls.SetBrowserOptions(cls._finder_options)
    webview_package_name = cls._finder_options.webview_package_name

    if not webview_package_name:
      webview_provider_apk = (cls._browser_to_create
                              .settings.GetApkName(cls._device))
      webview_apk_path = util.FindLatestApkOnHost(
          cls._finder_options.chrome_root, webview_provider_apk)
      webview_package_name = apk_helper.GetPackageName(webview_apk_path)

    cls._device_components_dir = ('/data/data/%s/app_webview/components' %
                                  webview_package_name)
    logcat_output_dir = (
        os.path.dirname(cls._typ_runner.args.write_full_results_to or '') or
        os.getcwd())

    # Set up a logcat monitor
    cls._logcat_monitor = logcat_monitor.LogcatMonitor(
        cls._device.adb,
        output_file=os.path.join(logcat_output_dir,
                                 '%s_logcat.txt' % cls.Name()),
        filter_specs=_LOGCAT_FILTERS)
    cls._logcat_monitor.Start()

    cls._MaybeClearOutComponentsDir()
    component_id = _COMPONENT_NAME_TO_DATA.get(
        cls._finder_options.component_name).component_id
    with zipfile.ZipFile(cls._finder_options.crx_file) as crx_archive, \
        NamedTemporaryDirectory() as tmp_dir,                          \
        crx_archive.open('manifest.json') as manifest:
      crx_device_dir = posixpath.join(
          cls._device_components_dir, 'cps',
          component_id, '1_%s' % json.loads(manifest.read())['version'])

      try:
        # Create directory on the test device for the CRX files
        logger.info('Creating directory %r on device' % crx_device_dir)
        output = cls._device.RunShellCommand(
            ['mkdir', '-p', crx_device_dir])
        logger.debug('Recieved the following output from adb: %s' % output)
      except Exception as e:
        logger.exception('Exception %r was raised' % str(e))
        raise

      # Move CRX files to the device directory
      crx_archive.extractall(tmp_dir)
      cls._MoveNewCrxToDevice(tmp_dir, crx_device_dir)

    # Start the browser after the device is in a clean state and the CRX
    # files are loaded onto the device
    cls.StartBrowser()
Esempio n. 5
0
    def SetUp(self):
        device_arg = 'default'
        if self._target_devices_file:
            device_arg = device_list.GetPersistentDeviceList(
                self._target_devices_file)
            if not device_arg:
                logging.warning('No target devices specified. Falling back to '
                                'running on all available devices.')
                device_arg = 'default'
            else:
                logging.info('Read device list %s from target devices file.',
                             str(device_arg))
        elif self._device_serial:
            device_arg = self._device_serial

        self._devices = device_utils.DeviceUtils.HealthyDevices(
            self._blacklist,
            enable_device_files_cache=self._enable_device_cache,
            default_retries=self._max_tries - 1,
            device_arg=device_arg)
        if not self._devices:
            raise device_errors.NoDevicesError

        if self._enable_device_cache:
            for d in self._devices:
                cache_path = _DeviceCachePath(d)
                if os.path.exists(cache_path):
                    logging.info('Using device cache: %s', cache_path)
                    with open(cache_path) as f:
                        d.LoadCacheData(f.read())
                    # Delete cached file so that any exceptions cause it to be cleared.
                    os.unlink(cache_path)
        if self._logcat_output_file:
            self._logcat_output_dir = tempfile.mkdtemp()
        if self._logcat_output_dir:
            for d in self._devices:
                logcat_file = os.path.join(
                    self._logcat_output_dir, '%s_%s' %
                    (d.adb.GetDeviceSerial(),
                     datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S')))
                monitor = logcat_monitor.LogcatMonitor(d.adb,
                                                       clear=True,
                                                       output_file=logcat_file)
                self._logcat_monitors.append(monitor)
                monitor.Start()
    def prepare_device(d):
      if self._enable_device_cache:
        cache_path = _DeviceCachePath(d)
        if os.path.exists(cache_path):
          logging.info('Using device cache: %s', cache_path)
          with open(cache_path) as f:
            d.LoadCacheData(f.read())
          # Delete cached file so that any exceptions cause it to be cleared.
          os.unlink(cache_path)

      if self._logcat_output_dir:
        logcat_file = os.path.join(
            self._logcat_output_dir,
            '%s_%s' % (d.adb.GetDeviceSerial(),
                       datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S')))
        monitor = logcat_monitor.LogcatMonitor(
            d.adb, clear=True, output_file=logcat_file)
        self._logcat_monitors.append(monitor)
        monitor.Start()
  def testWaitFor_buffering(self):
    # Simulate an adb log stream which does not complete until the test tells it
    # to. This checks that the log matcher can receive individual lines from the
    # log reader thread even if adb is not producing enough output to fill an
    # entire file io buffer.
    finished_lock = threading.Lock()
    finished_lock.acquire()

    def LogGenerator():
      for line in type(self)._TEST_THREADTIME_LOGCAT_DATA:
        yield line
      finished_lock.acquire()

    test_adb = adb_wrapper.AdbWrapper('0123456789abcdef')
    test_adb.Logcat = mock.Mock(return_value=LogGenerator())
    test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False)
    test_log.Start()

    actual_match = test_log.WaitFor(r'.*last line.*', None)
    finished_lock.release()
    self.assertTrue(actual_match)
    test_log.Stop()
    test_log.Close()
def _CreateTestLog(raw_logcat=None):
  test_adb = adb_wrapper.AdbWrapper('0123456789abcdef')
  test_adb.Logcat = mock.Mock(return_value=(l for l in raw_logcat))
  test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False)
  return test_log
Esempio n. 9
0
    def _RunTest(self, device, test):
        extras = {}

        # Provide package name under test for apk_under_test.
        if self._test_instance.apk_under_test:
            package_name = self._test_instance.apk_under_test.GetPackageName()
            extras[_EXTRA_PACKAGE_UNDER_TEST] = package_name

        flags_to_add = []
        test_timeout_scale = None
        if self._test_instance.coverage_directory:
            coverage_basename = '%s.exec' % (
                '%s_%s_group' %
                (test[0]['class'], test[0]['method']) if isinstance(
                    test, list) else '%s_%s' % (test['class'], test['method']))
            extras['coverage'] = 'true'
            coverage_directory = os.path.join(device.GetExternalStoragePath(),
                                              'chrome', 'test', 'coverage')
            if not device.PathExists(coverage_directory):
                device.RunShellCommand(['mkdir', '-p', coverage_directory],
                                       check_return=True)
            coverage_device_file = os.path.join(coverage_directory,
                                                coverage_basename)
            extras['coverageFile'] = coverage_device_file
        # Save screenshot if screenshot dir is specified (save locally) or if
        # a GS bucket is passed (save in cloud).
        screenshot_device_file = device_temp_file.DeviceTempFile(
            device.adb, suffix='.png', dir=device.GetExternalStoragePath())
        extras[EXTRA_SCREENSHOT_FILE] = screenshot_device_file.name

        # Set up the screenshot directory. This needs to be done for each test so
        # that we only get screenshots created by that test. It has to be on
        # external storage since the default location doesn't allow file creation
        # from the instrumentation test app on Android L and M.
        ui_capture_dir = device_temp_file.NamedDeviceTemporaryDirectory(
            device.adb, dir=device.GetExternalStoragePath())
        extras[EXTRA_UI_CAPTURE_DIR] = ui_capture_dir.name

        if self._env.trace_output:
            trace_device_file = device_temp_file.DeviceTempFile(
                device.adb,
                suffix='.json',
                dir=device.GetExternalStoragePath())
            extras[EXTRA_TRACE_FILE] = trace_device_file.name

        if isinstance(test, list):
            if not self._test_instance.driver_apk:
                raise Exception('driver_apk does not exist. '
                                'Please build it and try again.')
            if any(t.get('is_junit4') for t in test):
                raise Exception('driver apk does not support JUnit4 tests')

            def name_and_timeout(t):
                n = instrumentation_test_instance.GetTestName(t)
                i = self._GetTimeoutFromAnnotations(t['annotations'], n)
                return (n, i)

            test_names, timeouts = zip(*(name_and_timeout(t) for t in test))

            test_name = ','.join(test_names)
            test_display_name = test_name
            target = '%s/%s' % (self._test_instance.driver_package,
                                self._test_instance.driver_name)
            extras.update(
                self._test_instance.GetDriverEnvironmentVars(
                    test_list=test_names))
            timeout = sum(timeouts)
        else:
            test_name = instrumentation_test_instance.GetTestName(test)
            test_display_name = self._GetUniqueTestName(test)
            if test['is_junit4']:
                target = '%s/%s' % (self._test_instance.test_package,
                                    self._test_instance.junit4_runner_class)
            else:
                target = '%s/%s' % (self._test_instance.test_package,
                                    self._test_instance.junit3_runner_class)
            extras['class'] = test_name
            if 'flags' in test and test['flags']:
                flags_to_add.extend(test['flags'])
            timeout = self._GetTimeoutFromAnnotations(test['annotations'],
                                                      test_display_name)

            test_timeout_scale = self._GetTimeoutScaleFromAnnotations(
                test['annotations'])
            if test_timeout_scale and test_timeout_scale != 1:
                valgrind_tools.SetChromeTimeoutScale(
                    device,
                    test_timeout_scale * self._test_instance.timeout_scale)

        if self._test_instance.wait_for_java_debugger:
            timeout = None
        logging.info('preparing to run %s: %s', test_display_name, test)

        render_tests_device_output_dir = None
        if _IsRenderTest(test):
            # TODO(mikecase): Add DeviceTempDirectory class and use that instead.
            render_tests_device_output_dir = posixpath.join(
                device.GetExternalStoragePath(), 'render_test_output_dir')
            flags_to_add.append('--render-test-output-dir=%s' %
                                render_tests_device_output_dir)

        if flags_to_add:
            self._CreateFlagChangerIfNeeded(device)
            self._flag_changers[str(device)].PushFlags(add=flags_to_add)

        time_ms = lambda: int(time.time() * 1e3)
        start_ms = time_ms()

        stream_name = 'logcat_%s_%s_%s' % (test_name.replace(
            '#', '.'), time.strftime('%Y%m%dT%H%M%S-UTC',
                                     time.gmtime()), device.serial)

        with ui_capture_dir:
            with self._env.output_manager.ArchivedTempfile(
                    stream_name, 'logcat') as logcat_file:
                try:
                    with logcat_monitor.LogcatMonitor(
                            device.adb,
                            filter_specs=local_device_environment.
                            LOGCAT_FILTERS,
                            output_file=logcat_file.name,
                            transform_func=self._test_instance.
                            MaybeDeobfuscateLines,
                            check_error=False) as logmon:
                        with _LogTestEndpoints(device, test_name):
                            with contextlib_ext.Optional(
                                    trace_event.trace(test_name),
                                    self._env.trace_output):
                                output = device.StartInstrumentation(
                                    target,
                                    raw=True,
                                    extras=extras,
                                    timeout=timeout,
                                    retries=0)
                finally:
                    logmon.Close()

            if logcat_file.Link():
                logging.info('Logcat saved to %s', logcat_file.Link())

            duration_ms = time_ms() - start_ms

            with contextlib_ext.Optional(trace_event.trace('ProcessResults'),
                                         self._env.trace_output):
                output = self._test_instance.MaybeDeobfuscateLines(output)
                # TODO(jbudorick): Make instrumentation tests output a JSON so this
                # doesn't have to parse the output.
                result_code, result_bundle, statuses = (
                    self._test_instance.ParseAmInstrumentRawOutput(output))
                results = self._test_instance.GenerateTestResults(
                    result_code, result_bundle, statuses, start_ms,
                    duration_ms, device.product_cpu_abi,
                    self._test_instance.symbolizer)

            if self._env.trace_output:
                self._SaveTraceData(trace_device_file, device, test['class'])

            def restore_flags():
                if flags_to_add:
                    self._flag_changers[str(device)].Restore()

            def restore_timeout_scale():
                if test_timeout_scale:
                    valgrind_tools.SetChromeTimeoutScale(
                        device, self._test_instance.timeout_scale)

            def handle_coverage_data():
                if self._test_instance.coverage_directory:
                    try:
                        if not os.path.exists(
                                self._test_instance.coverage_directory):
                            os.makedirs(self._test_instance.coverage_directory)
                        device.PullFile(coverage_device_file,
                                        self._test_instance.coverage_directory)
                        device.RemovePath(coverage_device_file, True)
                    except (OSError, base_error.BaseError) as e:
                        logging.warning(
                            'Failed to handle coverage data after tests: %s',
                            e)

            def handle_render_test_data():
                if _IsRenderTest(test):
                    # Render tests do not cause test failure by default. So we have to
                    # check to see if any failure images were generated even if the test
                    # does not fail.
                    try:
                        self._ProcessRenderTestResults(
                            device, render_tests_device_output_dir, results)
                    finally:
                        device.RemovePath(render_tests_device_output_dir,
                                          recursive=True,
                                          force=True)

            def pull_ui_screen_captures():
                screenshots = []
                for filename in device.ListDirectory(ui_capture_dir.name):
                    if filename.endswith('.json'):
                        screenshots.append(pull_ui_screenshot(filename))
                if screenshots:
                    json_archive_name = 'ui_capture_%s_%s.json' % (
                        test_name.replace('#', '.'),
                        time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
                    with self._env.output_manager.ArchivedTempfile(
                            json_archive_name, 'ui_capture',
                            output_manager.Datatype.JSON) as json_archive:
                        json.dump(screenshots, json_archive)
                    for result in results:
                        result.SetLink('ui screenshot', json_archive.Link())

            def pull_ui_screenshot(filename):
                source_dir = ui_capture_dir.name
                json_path = posixpath.join(source_dir, filename)
                json_data = json.loads(device.ReadFile(json_path))
                image_file_path = posixpath.join(source_dir,
                                                 json_data['location'])
                with self._env.output_manager.ArchivedTempfile(
                        json_data['location'], 'ui_capture',
                        output_manager.Datatype.PNG) as image_archive:
                    device.PullFile(image_file_path, image_archive.name)
                json_data['image_link'] = image_archive.Link()
                return json_data

            # While constructing the TestResult objects, we can parallelize several
            # steps that involve ADB. These steps should NOT depend on any info in
            # the results! Things such as whether the test CRASHED have not yet been
            # determined.
            post_test_steps = [
                restore_flags, restore_timeout_scale, handle_coverage_data,
                handle_render_test_data, pull_ui_screen_captures
            ]
            if self._env.concurrent_adb:
                post_test_step_thread_group = reraiser_thread.ReraiserThreadGroup(
                    reraiser_thread.ReraiserThread(f) for f in post_test_steps)
                post_test_step_thread_group.StartAll(will_block=True)
            else:
                for step in post_test_steps:
                    step()

        for result in results:
            if logcat_file:
                result.SetLink('logcat', logcat_file.Link())

        # Update the result name if the test used flags.
        if flags_to_add:
            for r in results:
                if r.GetName() == test_name:
                    r.SetName(test_display_name)

        # Add UNKNOWN results for any missing tests.
        iterable_test = test if isinstance(test, list) else [test]
        test_names = set(self._GetUniqueTestName(t) for t in iterable_test)
        results_names = set(r.GetName() for r in results)
        results.extend(
            base_test_result.BaseTestResult(
                u, base_test_result.ResultType.UNKNOWN)
            for u in test_names.difference(results_names))

        # Update the result type if we detect a crash.
        try:
            if DidPackageCrashOnDevice(self._test_instance.test_package,
                                       device):
                for r in results:
                    if r.GetType() == base_test_result.ResultType.UNKNOWN:
                        r.SetType(base_test_result.ResultType.CRASH)
        except device_errors.CommandTimeoutError:
            logging.warning(
                'timed out when detecting/dismissing error dialogs')
            # Attach screenshot to the test to help with debugging the dialog boxes.
            self._SaveScreenshot(device, screenshot_device_file,
                                 test_display_name, results,
                                 'dialog_box_screenshot')

        # Handle failures by:
        #   - optionally taking a screenshot
        #   - logging the raw output at INFO level
        #   - clearing the application state while persisting permissions
        if any(r.GetType() not in (base_test_result.ResultType.PASS,
                                   base_test_result.ResultType.SKIP)
               for r in results):
            self._SaveScreenshot(device, screenshot_device_file,
                                 test_display_name, results,
                                 'post_test_screenshot')

            logging.info('detected failure in %s. raw output:',
                         test_display_name)
            for l in output:
                logging.info('  %s', l)
            if (not self._env.skip_clear_data
                    and self._test_instance.package_info):
                permissions = (
                    self._test_instance.apk_under_test.GetPermissions()
                    if self._test_instance.apk_under_test else None)
                device.ClearApplicationState(
                    self._test_instance.package_info.package,
                    permissions=permissions)
        else:
            logging.debug('raw output from %s:', test_display_name)
            for l in output:
                logging.debug('  %s', l)
        if self._test_instance.store_tombstones:
            tombstones_url = None
            for result in results:
                if result.GetType() == base_test_result.ResultType.CRASH:
                    if not tombstones_url:
                        resolved_tombstones = tombstones.ResolveTombstones(
                            device,
                            resolve_all_tombstones=True,
                            include_stack_symbols=False,
                            wipe_tombstones=True,
                            tombstone_symbolizer=self._test_instance.symbolizer
                        )
                        tombstone_filename = 'tombstones_%s_%s' % (
                            time.strftime('%Y%m%dT%H%M%S-UTC',
                                          time.gmtime()), device.serial)
                        with self._env.output_manager.ArchivedTempfile(
                                tombstone_filename,
                                'tombstones') as tombstone_file:
                            tombstone_file.write(
                                '\n'.join(resolved_tombstones))
                        result.SetLink('tombstones', tombstone_file.Link())
        if self._env.concurrent_adb:
            post_test_step_thread_group.JoinAll()
        return results, None
Esempio n. 10
0
    def _RunTest(self, device, test):
        # Run the test.
        timeout = (self._test_instance.shard_timeout *
                   self.GetTool(device).GetTimeoutScale())
        if self._test_instance.wait_for_java_debugger:
            timeout = None
        if self._test_instance.store_tombstones:
            tombstones.ClearAllTombstones(device)
        test_perf_output_filename = next(self._test_perf_output_filenames)

        with device_temp_file.DeviceTempFile(
                adb=device.adb,
                dir=self._delegate.ResultsDirectory(device),
                suffix='.xml') as device_tmp_results_file:
            with contextlib_ext.Optional(
                    device_temp_file.NamedDeviceTemporaryDirectory(
                        adb=device.adb, dir='/sdcard/'), self._test_instance.
                    gs_test_artifacts_bucket) as test_artifacts_dir:
                with (contextlib_ext.Optional(
                        device_temp_file.DeviceTempFile(
                            adb=device.adb,
                            dir=self._delegate.ResultsDirectory(device)),
                        test_perf_output_filename)
                      ) as isolated_script_test_perf_output:

                    flags = list(self._test_instance.flags)
                    if self._test_instance.enable_xml_result_parsing:
                        flags.append('--gtest_output=xml:%s' %
                                     device_tmp_results_file.name)

                    if self._test_instance.gs_test_artifacts_bucket:
                        flags.append('--test_artifacts_dir=%s' %
                                     test_artifacts_dir.name)

                    if test_perf_output_filename:
                        flags.append('--isolated_script_test_perf_output=%s' %
                                     isolated_script_test_perf_output.name)

                    logging.info('flags:')
                    for f in flags:
                        logging.info('  %s', f)

                    stream_name = 'logcat_%s_%s_%s' % (
                        hash(tuple(test)),
                        time.strftime('%Y%m%dT%H%M%S-UTC',
                                      time.gmtime()), device.serial)

                    with self._env.output_manager.ArchivedTempfile(
                            stream_name, 'logcat') as logcat_file:
                        with logcat_monitor.LogcatMonitor(
                                device.adb,
                                filter_specs=local_device_environment.
                                LOGCAT_FILTERS,
                                output_file=logcat_file.name,
                                check_error=False) as logmon:
                            with contextlib_ext.Optional(
                                    trace_event.trace(str(test)),
                                    self._env.trace_output):
                                output = self._delegate.Run(
                                    test,
                                    device,
                                    flags=' '.join(flags),
                                    timeout=timeout,
                                    retries=0)
                        logmon.Close()

                    if logcat_file.Link():
                        logging.info('Logcat saved to %s', logcat_file.Link())

                    if self._test_instance.enable_xml_result_parsing:
                        try:
                            gtest_xml = device.ReadFile(
                                device_tmp_results_file.name, as_root=True)
                        except device_errors.CommandFailedError as e:
                            logging.warning(
                                'Failed to pull gtest results XML file %s: %s',
                                device_tmp_results_file.name, str(e))
                            gtest_xml = None

                    if test_perf_output_filename:
                        try:
                            device.PullFile(
                                isolated_script_test_perf_output.name,
                                test_perf_output_filename)
                        except device_errors.CommandFailedError as e:
                            logging.warning(
                                'Failed to pull chartjson results %s: %s',
                                isolated_script_test_perf_output.name, str(e))

                    test_artifacts_url = self._UploadTestArtifacts(
                        device, test_artifacts_dir)

        for s in self._servers[str(device)]:
            s.Reset()
        if self._test_instance.app_files:
            self._delegate.PullAppFiles(device, self._test_instance.app_files,
                                        self._test_instance.app_file_dir)
        if not self._env.skip_clear_data:
            self._delegate.Clear(device)

        for l in output:
            logging.info(l)

        # Parse the output.
        # TODO(jbudorick): Transition test scripts away from parsing stdout.
        if self._test_instance.enable_xml_result_parsing:
            results = gtest_test_instance.ParseGTestXML(gtest_xml)
        else:
            results = gtest_test_instance.ParseGTestOutput(
                output, self._test_instance.symbolizer, device.product_cpu_abi)

        tombstones_url = None
        for r in results:
            if logcat_file:
                r.SetLink('logcat', logcat_file.Link())

            if self._test_instance.gs_test_artifacts_bucket:
                r.SetLink('test_artifacts', test_artifacts_url)

            if r.GetType() == base_test_result.ResultType.CRASH:
                self._crashes.add(r.GetName())
                if self._test_instance.store_tombstones:
                    if not tombstones_url:
                        resolved_tombstones = tombstones.ResolveTombstones(
                            device,
                            resolve_all_tombstones=True,
                            include_stack_symbols=False,
                            wipe_tombstones=True)
                        stream_name = 'tombstones_%s_%s' % (time.strftime(
                            '%Y%m%dT%H%M%S', time.localtime()), device.serial)
                        tombstones_url = logdog_helper.text(
                            stream_name, '\n'.join(resolved_tombstones))
                    r.SetLink('tombstones', tombstones_url)

        tests_stripped_disabled_prefix = set()
        for t in test:
            tests_stripped_disabled_prefix.add(
                gtest_test_instance.TestNameWithoutDisabledPrefix(t))
        not_run_tests = tests_stripped_disabled_prefix.difference(
            set(r.GetName() for r in results))
        return results, list(not_run_tests) if results else None
def main(args):
    TEST_CASES.update({
        p.product_name(): p
        for p in
        [ChromeFinchTestCase, WebViewFinchTestCase, WebLayerFinchTestCase]
    })

    parser = argparse.ArgumentParser(prog='run_finch_smoke_tests_android.py')
    parser.add_argument(
        '--test-case',
        choices=TEST_CASES.keys(),
        # TODO(rmhasan): Remove default values after
        # adding arguments to test suites. Also make
        # this argument required.
        default='webview',
        help='Name of test case')
    parser.add_argument('--finch-seed-path',
                        default=TEST_SEED_PATH,
                        type=os.path.realpath,
                        help='Path to the finch seed')
    parser.add_argument('--browser-apk',
                        '--webview-shell-apk',
                        '--weblayer-shell-apk',
                        help='Path to the browser apk',
                        type=os.path.realpath,
                        required=True)
    parser.add_argument('--webview-provider-apk',
                        type=os.path.realpath,
                        help='Path to the WebView provider apk')
    parser.add_argument('--browser-activity-name',
                        action='store',
                        help='Browser activity name')
    parser.add_argument('--write-full-results-to',
                        '--isolated-script-test-output',
                        action='store',
                        type=os.path.realpath,
                        default=os.path.join(os.getcwd(), 'output.json'),
                        help='Path to output directory')
    add_emulator_args(parser)
    script_common.AddDeviceArguments(parser)
    script_common.AddEnvironmentArguments(parser)
    logging_common.AddLoggingArguments(parser)

    options, _ = parser.parse_known_args(args)
    devil_chromium.Initialize(adb_path=options.adb_path)

    logging_common.InitializeLogging(options)

    with get_device(options) as device, \
        TEST_CASES[options.test_case](device, options) as test_case, \
        test_case.install_apks():

        device.EnableRoot()
        log_mon = logcat_monitor.LogcatMonitor(
            device.adb,
            output_file=os.path.join(
                os.path.dirname(options.write_full_results_to),
                '%s_finch_smoke_tests_logcat.txt' % test_case.product_name()),
            filter_specs=_LOGCAT_FILTERS)
        log_mon.Start()

        device.RunShellCommand(
            ['pm', 'clear',
             get_package_name(options.browser_apk)],
            check_return=True)

        tests_pass = False
        with_seed_res = TestResult.Fail
        without_seed_res = TestResult.Fail
        if test_case.run_tests('without finch seed') != 0:
            test_case.install_seed()
            tests_pass = test_case.run_tests('with finch seed')
            without_seed_res = TestResult.Pass
            if tests_pass:
                with_seed_res = TestResult.Pass

        log_mon.Stop()
        json_results = get_json_results(with_seed_res, without_seed_res)
        with open(options.write_full_results_to, 'w') as json_out:
            json_out.write(json.dumps(json_results, indent=4))

    # Return zero exit code if tests pass
    return not tests_pass