Exemple #1
0
def Run(exclude, classes_to_analyze, auxiliary_classes, output_file,
        findbug_args, jars):
    """Run FindBugs.

  Args:
    exclude: the exclude xml file, refer to FindBugs's -exclude command option.
    classes_to_analyze: the list of classes need to analyze, refer to FindBug's
                        -onlyAnalyze command line option.
    auxiliary_classes: the classes help to analyze, refer to FindBug's
                       -auxclasspath command line option.
    output_file: An optional path to dump XML results to.
    findbug_args: A list of addtional command line options to pass to Findbugs.
  """
    # TODO(jbudorick): Get this from the build system.
    system_classes = [
        os.path.join(constants.ANDROID_SDK_ROOT, 'platforms',
                     'android-%s' % constants.ANDROID_SDK_VERSION,
                     'android.jar')
    ]
    system_classes.extend(
        os.path.abspath(classes) for classes in auxiliary_classes or [])

    cmd = [
        'java', '-classpath',
        '%s:' % _FINDBUGS_JAR,
        '-Xmx%dm' % _FINDBUGS_MAX_HEAP,
        '-Dfindbugs.home="%s"' % _FINDBUGS_HOME, '-jar', _FINDBUGS_JAR,
        '-textui', '-sortByClass', '-pluginList', _FINDBUGS_PLUGIN_PATH,
        '-xml:withMessages'
    ]
    if system_classes:
        cmd.extend(['-auxclasspath', ':'.join(system_classes)])
    if classes_to_analyze:
        cmd.extend(['-onlyAnalyze', classes_to_analyze])
    if exclude:
        cmd.extend(['-exclude', os.path.abspath(exclude)])
    if output_file:
        cmd.extend(['-output', output_file])
    if findbug_args:
        cmd.extend(findbug_args)
    cmd.extend(os.path.abspath(j) for j in jars or [])

    if output_file:
        _, _, stderr = cmd_helper.GetCmdStatusOutputAndError(cmd)

        results_doc = xml.dom.minidom.parse(output_file)
    else:
        _, raw_out, stderr = cmd_helper.GetCmdStatusOutputAndError(cmd)
        results_doc = xml.dom.minidom.parseString(raw_out)

    for line in stderr.splitlines():
        logging.debug('  %s', line)

    current_warnings_set = _ParseXmlResults(results_doc)

    return (' '.join(cmd), current_warnings_set)
Exemple #2
0
def _ParseManifestFromBundle(bundle):
  cmd = [bundle.path, 'dump-manifest']
  status, stdout, stderr = cmd_helper.GetCmdStatusOutputAndError(cmd)
  if status != 0:
    raise Exception('Failed running {} with output\n{}\n{}'.format(
        ' '.join(cmd), stdout, stderr))
  return ParseManifestFromXml(stdout)
Exemple #3
0
def WriteZipFile(zip_path, zip_contents):
    """Writes the provided contents to the given zip file.

  Note that this uses python's zipfile module and is done in a separate
  process to avoid hogging the GIL.

  Args:
    zip_path: String path to the zip file to write.
    zip_contents: A list of (host path, archive path) tuples.

  Raises:
    ZipFailedError on failure.
  """
    zip_spec = {
        'zip_path': zip_path,
        'zip_contents': zip_contents,
    }
    with tempfile_ext.NamedTemporaryDirectory() as tmpdir:
        json_path = os.path.join(tmpdir, 'zip_spec.json')
        with open(json_path, 'w') as json_file:
            json.dump(zip_spec, json_file)
        ret, output, error = cmd_helper.GetCmdStatusOutputAndError([
            sys.executable,
            os.path.abspath(__file__), '--zip-spec', json_path
        ])

    if ret != 0:
        exc_msg = ['Failed to create %s' % zip_path]
        exc_msg.extend('stdout:  %s' % l for l in output.splitlines())
        exc_msg.extend('stderr:  %s' % l for l in error.splitlines())
        raise ZipFailedError('\n'.join(exc_msg))
Exemple #4
0
    def Authenticate(self, use_luci=True):
        """Authenticates with Skia Gold for this session.

    Args:
      use_luci: If true, authentication will use the service account provided
          by the LUCI context. If false, will attempt to use whatever is set up
          in gsutil, which is only supported for local runs.

    Returns:
      A tuple (return_code, output). |return_code| is the return code of the
      authentication process. |output| is the stdout + stderr of the
      authentication process.
    """
        if self._authenticated:
            return 0, None
        if self._gold_properties.bypass_skia_gold_functionality:
            logging.warning('Not actually authenticating with Gold due to '
                            '--bypass-skia-gold-functionality being present.')
            return 0, None

        auth_cmd = [GOLDCTL_BINARY, 'auth', '--work-dir', self._working_dir]
        if use_luci:
            auth_cmd.append('--luci')
        elif not self._gold_properties.local_pixel_tests:
            raise RuntimeError(
                'Cannot authenticate to Skia Gold with use_luci=False unless running '
                'local pixel tests')

        rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(
            auth_cmd, merge_stderr=True)
        if rc == 0:
            self._authenticated = True
        return rc, stdout
Exemple #5
0
    def get_cipd_dependency_rev(self):
        """Return CTS CIPD revision in the checkout's DEPS file."""
        deps_file = os.path.join(self._root_dir, DEPS_FILE)

        # Use the gclient command instead of gclient_eval since the latter is not
        # intended for direct use outside of depot_tools. The .bat file extension
        # must be explicitly specified when shell=False.
        gclient = 'gclient.bat' if os.name == 'nt' else 'gclient'
        cmd = [
            gclient, 'getdep', '--revision',
            '%s:%s' % (CTS_DEP_NAME, CTS_DEP_PACKAGE), '--deps-file', deps_file
        ]
        env = os.environ

        # Disable auto-update of depot tools since update_depot_tools may not be
        # available (for example, on the presubmit bot), and it's probably best not
        # to perform surprise updates anyways.
        env.update({'DEPOT_TOOLS_UPDATE': '0'})
        status, output, err = cmd_helper.GetCmdStatusOutputAndError(cmd,
                                                                    env=env)

        if status != 0:
            raise Exception('Command "%s" failed: %s' % (' '.join(cmd), err))

        return output.strip()
Exemple #6
0
    def Initialize(self):
        """Initializes the working directory if necessary.

    This can technically be skipped if the same information is passed to the
    command used for image comparison, but that is less efficient under the
    hood. Doing it that way effectively requires an initialization for every
    comparison (~250 ms) instead of once at the beginning.

    Returns:
      A tuple (return_code, output). |return_code| is the return code of the
      initialization process. |output| is the stdout + stderr of the
      initialization process.
    """
        if self._initialized:
            return 0, None
        if self._gold_properties.bypass_skia_gold_functionality:
            logging.warning('Not actually initializing Gold due to '
                            '--bypass-skia-gold-functionality being present.')
            return 0, None

        init_cmd = [
            GOLDCTL_BINARY,
            'imgtest',
            'init',
            '--passfail',
            '--instance',
            self._instance,
            '--corpus',
            self._corpus,
            '--keys-file',
            self._keys_file,
            '--work-dir',
            self._working_dir,
            '--failure-file',
            self._triage_link_file,
            '--commit',
            self._gold_properties.git_revision,
        ]
        if self._gold_properties.IsTryjobRun():
            init_cmd.extend([
                '--issue',
                str(self._gold_properties.issue),
                '--patchset',
                str(self._gold_properties.patchset),
                '--jobid',
                str(self._gold_properties.job_id),
                '--crs',
                str(self._gold_properties.code_review_system),
                '--cis',
                str(self._gold_properties.continuous_integration_system),
            ])
        rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(
            init_cmd, merge_stderr=True)
        if rc == 0:
            self._initialized = True
        return rc, stdout
Exemple #7
0
    def Compare(self, name, png_file):
        """Compares the given image to images known to Gold.

    Triage links can later be retrieved using GetTriageLink().

    Args:
      name: The name of the image being compared.
      png_file: A path to a PNG file containing the image to be compared.

    Returns:
      A tuple (return_code, output). |return_code| is the return code of the
      comparison process. |output| is the stdout + stderr of the comparison
      process.
    """
        if self._gold_properties.bypass_skia_gold_functionality:
            logging.warning('Not actually comparing with Gold due to '
                            '--bypass-skia-gold-functionality being present.')
            return 0, None

        compare_cmd = [
            GOLDCTL_BINARY,
            'imgtest',
            'add',
            '--test-name',
            name,
            '--png-file',
            png_file,
            '--work-dir',
            self._working_dir,
        ]
        if self._gold_properties.local_pixel_tests:
            compare_cmd.append('--dryrun')

        self._ClearTriageLinkFile()
        rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(
            compare_cmd, merge_stderr=True)

        self._comparison_results[name] = self.ComparisonResults()
        if rc == 0:
            self._comparison_results[name].triage_link_omission_reason = (
                'Comparison succeeded, no triage link')
        elif self._gold_properties.IsTryjobRun():
            cl_triage_link = ('https://{instance}-gold.skia.org/search?'
                              'issue={issue}')
            cl_triage_link = cl_triage_link.format(
                instance=self._instance, issue=self._gold_properties.issue)
            self._comparison_results[name].triage_link = cl_triage_link
        else:
            try:
                with open(self._triage_link_file) as tlf:
                    triage_link = tlf.read().strip()
                self._comparison_results[name].triage_link = triage_link
            except IOError:
                self._comparison_results[name].triage_link_omission_reason = (
                    'Failed to read triage link from file')
        return rc, stdout
Exemple #8
0
def ExtractApks(output_dir,
                apks_path,
                abis,
                locales,
                features,
                pixel_density,
                sdk_version,
                modules=None):
    """Extracts splits from APKS archive.

  Args:
    output_dir: Directory to extract splits into.
    apks_path: Path to APKS archive.
    abis: ABIs to support.
    locales: Locales to support.
    features: Device features to support.
    pixel_density: Pixel density to support.
    sdk_version: Target SDK version.
    modules: Extra modules to install.
  """
    device_spec = {
        'supportedAbis': abis,
        'supportedLocales': ['%s-%s' % l for l in locales],
        'deviceFeatures': features,
        'screenDensity': pixel_density,
        'sdkVersion': sdk_version,
    }
    with tempfile_ext.TemporaryFileName(suffix='.json') as device_spec_path:
        with open(device_spec_path, 'w') as f:
            json.dump(device_spec, f)
        cmd = [
            'java',
            '-jar',
            _bundletool_path.read(),
            'extract-apks',
            '--apks=%s' % apks_path,
            '--device-spec=%s' % device_spec_path,
            '--output-dir=%s' % output_dir,
        ]
        if modules:
            cmd += ['--modules=%s' % ','.join(modules)]
        status, stdout, stderr = cmd_helper.GetCmdStatusOutputAndError(cmd)
        if status != 0:
            raise base_error.BaseError(
                'Failed running {} with output\n{}\n{}'.format(
                    ' '.join(cmd), stdout, stderr))
Exemple #9
0
  def Install(self):
    """Installs the requested CIPD packages.

    Returns: None
    Raises: AvdException on failure to install.
    """
    pkgs_by_dir = {}
    for pkg in (self._config.emulator_package,
                self._config.system_image_package,
                self._config.avd_package):
      if not pkg.dest_path in pkgs_by_dir:
        pkgs_by_dir[pkg.dest_path] = []
      pkgs_by_dir[pkg.dest_path].append(pkg)

    for pkg_dir, pkgs in pkgs_by_dir.iteritems():
      logging.info('Installing packages in %s', pkg_dir)
      cipd_root = os.path.join(_SRC_ROOT, pkg_dir)
      if not os.path.exists(cipd_root):
        os.makedirs(cipd_root)
      ensure_path = os.path.join(cipd_root, '.ensure')
      with open(ensure_path, 'w') as ensure_file:
        # Make CIPD ensure that all files are present, even if
        # it thinks the package is installed.
        ensure_file.write('$ParanoidMode CheckPresence\n\n')
        for pkg in pkgs:
          ensure_file.write('%s %s\n' % (pkg.package_name, pkg.version))
          logging.info('  %s %s', pkg.package_name, pkg.version)
      ensure_cmd = [
          'cipd', 'ensure', '-ensure-file', ensure_path, '-root', cipd_root,
      ]
      status, output, error = cmd_helper.GetCmdStatusOutputAndError(ensure_cmd)
      if status:
        raise AvdException(
            'Failed to install CIPD package %s' % pkg.package_name,
            command=ensure_cmd,
            stdout=output,
            stderr=error)

    # The emulator requires that some files are writable.
    for dirname, _, filenames in os.walk(self._emulator_home):
      for f in filenames:
        path = os.path.join(dirname, f)
        if (os.lstat(path).st_mode &
            (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) == stat.S_IRUSR):
          os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
Exemple #10
0
 def _GetApksPath(self):
   apks_path = None
   try:
     fd, apks_path = tempfile.mkstemp(suffix='.apks')
     os.close(fd)
     cmd = [
         self._bundle_script_path,
         'build-bundle-apks',
         '--output-apks',
         apks_path,
     ]
     status, stdout, stderr = cmd_helper.GetCmdStatusOutputAndError(cmd)
     if status != 0:
       raise ApkHelperError('Failed running {} with output\n{}\n{}'.format(
           ' '.join(cmd), stdout, stderr))
     return _DeleteHelper(apks_path, apks_path)
   except:
     if apks_path:
       os.remove(apks_path)
     raise
Exemple #11
0
 def _RunCmdForRcAndOutput(cmd):
   rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(cmd,
                                                         merge_stderr=True)
   return rc, stdout
Exemple #12
0
 def check_call(self, *args):
   logging.debug('Calling command "%s"', str(args))
   return cmd_helper.GetCmdStatusOutputAndError(args)
Exemple #13
0
    def Diff(self, name, png_file, corpus, output_manager):
        """Performs a local image diff against the closest known positive in Gold.

    This is used for running tests on a workstation, where uploading data to
    Gold for ingestion is not allowed, and thus the web UI is not available.

    Image links can later be retrieved using Get*ImageLink().

    Args:
      name: The name of the image being compared.
      png_file: The path to a PNG file containing the image to be diffed.
      corpus: The corpus that the image belongs to.
      output_manager: The output manager used to save local diff images.

    Returns:
      A tuple (return_code, output). |return_code| is the return code of the
      diff process. |output| is the stdout + stderr of the diff process.
    """
        # Output managers only support archived files, not directories, so we have
        # to use a temporary directory and later move the data into the archived
        # files.
        output_dir = tempfile.mkdtemp(dir=self._working_dir)
        diff_cmd = [
            GOLDCTL_BINARY,
            'diff',
            '--corpus',
            corpus,
            '--instance',
            self._instance,
            '--input',
            png_file,
            '--test',
            name,
            '--work-dir',
            self._working_dir,
            '--out-dir',
            output_dir,
        ]
        rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(
            diff_cmd, merge_stderr=True)
        given_path = closest_path = diff_path = None
        # The directory should contain "input-<hash>.png", "closest-<hash>.png",
        # and "diff.png".
        for f in os.listdir(output_dir):
            filepath = os.path.join(output_dir, f)
            if f.startswith('input-'):
                given_path = filepath
            elif f.startswith('closest-'):
                closest_path = filepath
            elif f == 'diff.png':
                diff_path = filepath
        results = self._comparison_results.setdefault(name,
                                                      self.ComparisonResults())
        if given_path:
            with output_manager.ArchivedTempfile('given_%s.png' % name,
                                                 'gold_local_diffs',
                                                 Datatype.PNG) as given_file:
                shutil.move(given_path, given_file.name)
            results.local_diff_given_image = given_file.Link()
        if closest_path:
            with output_manager.ArchivedTempfile('closest_%s.png' % name,
                                                 'gold_local_diffs',
                                                 Datatype.PNG) as closest_file:
                shutil.move(closest_path, closest_file.name)
            results.local_diff_closest_image = closest_file.Link()
        if diff_path:
            with output_manager.ArchivedTempfile('diff_%s.png' % name,
                                                 'gold_local_diffs',
                                                 Datatype.PNG) as diff_file:
                shutil.move(diff_path, diff_file.name)
            results.local_diff_diff_image = diff_file.Link()
        return rc, stdout
Exemple #14
0
    def Compare(self, name, keys_file, png_file, corpus):
        """Compares the given image to images known to Gold.

    Triage links can later be retrieved using GetTriageLink().

    Args:
      name: The name of the image being compared.
      keys_file: A path to a JSON file containing various comparison config
          data such as corpus and debug information like the hardware/software
          configuration the image was produced on.
      png_file: A path to a PNG file containing the image to be compared.
      corpus: The corpus that the image belongs to.

    Returns:
      A tuple (return_code, output). |return_code| is the return code of the
      comparison process. |output| is the stdout + stderr of the comparison
      process.
    """
        compare_cmd = [
            GOLDCTL_BINARY,
            'imgtest',
            'add',
            '--passfail',
            '--test-name',
            name,
            '--instance',
            self._instance,
            '--corpus',
            corpus,
            '--keys-file',
            keys_file,
            '--png-file',
            png_file,
            '--work-dir',
            self._working_dir,
            '--failure-file',
            self._triage_link_file,
            '--commit',
            self._gold_properties.git_revision,
        ]
        if self._gold_properties.local_pixel_tests:
            compare_cmd.append('--dryrun')
        if self._gold_properties.IsTryjobRun():
            compare_cmd.extend([
                '--issue',
                str(self._gold_properties.issue),
                '--patchset',
                str(self._gold_properties.patchset),
                '--jobid',
                str(self._gold_properties.job_id),
                '--crs',
                str(self._gold_properties.code_review_system),
                '--cis',
                str(self._gold_properties.continuous_integration_system),
            ])

        rc, stdout, _ = cmd_helper.GetCmdStatusOutputAndError(
            compare_cmd, merge_stderr=True)

        self._comparison_results[name] = self.ComparisonResults()
        if rc == 0:
            self._comparison_results[name].triage_link_omission_reason = (
                'Comparison succeeded, no triage link')
        elif self._gold_properties.IsTryjobRun():
            # TODO(skbug.com/9879): Remove the explicit corpus when Gold's UI is
            # updated to show results from all corpora for tryjobs.
            cl_triage_link = ('https://{instance}-gold.skia.org/search?'
                              'issue={issue}&'
                              'new_clstore=true&'
                              'query=source_type%3D{corpus}')
            cl_triage_link = cl_triage_link.format(
                instance=self._instance,
                issue=self._gold_properties.issue,
                corpus=corpus)
            self._comparison_results[name].triage_link = cl_triage_link
        else:
            try:
                with open(self._triage_link_file) as tlf:
                    triage_link = tlf.read().strip()
                self._comparison_results[name].triage_link = triage_link
            except IOError:
                self._comparison_results[name].triage_link_omission_reason = (
                    'Failed to read triage link from file')
        return rc, stdout