tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

results_uploader.py (6518B)


      1 # Copyright 2012 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Uploads the results to the flakiness dashboard server."""
      6 # pylint: disable=R0201
      7 
      8 import logging
      9 import os
     10 import shutil
     11 import tempfile
     12 import xml
     13 
     14 
     15 from devil.utils import cmd_helper
     16 from pylib.constants import host_paths
     17 from pylib.results.flakiness_dashboard import json_results_generator
     18 from pylib.utils import repo_utils
     19 
     20 
     21 
     22 class JSONResultsGenerator(json_results_generator.JSONResultsGeneratorBase):
     23  """Writes test results to a JSON file and handles uploading that file to
     24  the test results server.
     25  """
     26  def __init__(self, builder_name, build_name, build_number, tmp_folder,
     27               test_results_map, test_results_server, test_type, master_name):
     28    super().__init__(builder_name=builder_name,
     29                     build_name=build_name,
     30                     build_number=build_number,
     31                     results_file_base_path=tmp_folder,
     32                     builder_base_url=None,
     33                     test_results_map=test_results_map,
     34                     svn_repositories=(('webkit', 'third_party/WebKit'),
     35                                       ('chrome', '.')),
     36                     test_results_server=test_results_server,
     37                     test_type=test_type,
     38                     master_name=master_name)
     39 
     40  #override
     41  def _GetModifierChar(self, test_name):
     42    if test_name not in self._test_results_map:
     43      return self.__class__.NO_DATA_RESULT
     44 
     45    return self._test_results_map[test_name].modifier
     46 
     47  #override
     48  def _GetSVNRevision(self, in_directory):
     49    """Returns the git/svn revision for the given directory.
     50 
     51    Args:
     52      in_directory: The directory relative to src.
     53    """
     54    def _is_git_directory(in_directory):
     55      """Returns true if the given directory is in a git repository.
     56 
     57      Args:
     58        in_directory: The directory path to be tested.
     59      """
     60      if os.path.exists(os.path.join(in_directory, '.git')):
     61        return True
     62      parent = os.path.dirname(in_directory)
     63      if parent in (host_paths.DIR_SOURCE_ROOT, in_directory):
     64        return False
     65      return _is_git_directory(parent)
     66 
     67    in_directory = os.path.join(host_paths.DIR_SOURCE_ROOT, in_directory)
     68 
     69    if not os.path.exists(os.path.join(in_directory, '.svn')):
     70      if _is_git_directory(in_directory):
     71        return repo_utils.GetGitHeadSHA1(in_directory)
     72      return ''
     73 
     74    output = cmd_helper.GetCmdOutput(['svn', 'info', '--xml'], cwd=in_directory)
     75    try:
     76      dom = xml.dom.minidom.parseString(output)
     77      return dom.getElementsByTagName('entry')[0].getAttribute('revision')
     78    except xml.parsers.expat.ExpatError:
     79      return ''
     80    return ''
     81 
     82 
     83 class ResultsUploader:
     84  """Handles uploading buildbot tests results to the flakiness dashboard."""
     85  def __init__(self, tests_type):
     86    self._build_number = os.environ.get('BUILDBOT_BUILDNUMBER')
     87    self._master_name = os.environ.get('BUILDBOT_MASTERNAME')
     88    self._builder_name = os.environ.get('BUILDBOT_BUILDERNAME')
     89    self._tests_type = tests_type
     90    self._build_name = None
     91 
     92    if not self._build_number or not self._builder_name:
     93      raise Exception('You should not be uploading tests results to the server'
     94                      'from your local machine.')
     95 
     96    upstream = (tests_type != 'Chromium_Android_Instrumentation')
     97    if not upstream:
     98      self._build_name = 'chromium-android'
     99      buildbot_branch = os.environ.get('BUILDBOT_BRANCH')
    100      if not buildbot_branch:
    101        buildbot_branch = 'master'
    102      else:
    103        # Ensure there's no leading "origin/"
    104        buildbot_branch = buildbot_branch[buildbot_branch.find('/') + 1:]
    105      self._master_name = '%s-%s' % (self._build_name, buildbot_branch)
    106 
    107    self._test_results_map = {}
    108 
    109  def AddResults(self, test_results):
    110    # TODO(frankf): Differentiate between fail/crash/timeouts.
    111    conversion_map = [
    112        (test_results.GetPass(), False,
    113            json_results_generator.JSONResultsGeneratorBase.PASS_RESULT),
    114        (test_results.GetFail(), True,
    115            json_results_generator.JSONResultsGeneratorBase.FAIL_RESULT),
    116        (test_results.GetCrash(), True,
    117            json_results_generator.JSONResultsGeneratorBase.FAIL_RESULT),
    118        (test_results.GetTimeout(), True,
    119            json_results_generator.JSONResultsGeneratorBase.FAIL_RESULT),
    120        (test_results.GetUnknown(), True,
    121            json_results_generator.JSONResultsGeneratorBase.NO_DATA_RESULT),
    122        ]
    123 
    124    for results_list, failed, modifier in conversion_map:
    125      for single_test_result in results_list:
    126        test_result = json_results_generator.TestResult(
    127            test=single_test_result.GetName(),
    128            failed=failed,
    129            elapsed_time=single_test_result.GetDuration() / 1000)
    130        # The WebKit TestResult object sets the modifier it based on test name.
    131        # Since we don't use the same test naming convention as WebKit the
    132        # modifier will be wrong, so we need to overwrite it.
    133        test_result.modifier = modifier
    134 
    135        self._test_results_map[single_test_result.GetName()] = test_result
    136 
    137  def Upload(self, test_results_server):
    138    if not self._test_results_map:
    139      return
    140 
    141    tmp_folder = tempfile.mkdtemp()
    142 
    143    try:
    144      results_generator = JSONResultsGenerator(
    145          builder_name=self._builder_name,
    146          build_name=self._build_name,
    147          build_number=self._build_number,
    148          tmp_folder=tmp_folder,
    149          test_results_map=self._test_results_map,
    150          test_results_server=test_results_server,
    151          test_type=self._tests_type,
    152          master_name=self._master_name)
    153 
    154      json_files = ["incremental_results.json", "times_ms.json"]
    155      results_generator.GenerateJSONOutput()
    156      results_generator.GenerateTimesMSFile()
    157      results_generator.UploadJSONFiles(json_files)
    158    except Exception as e: # pylint: disable=broad-except
    159      logging.error("Uploading results to test server failed: %s.", e)
    160    finally:
    161      shutil.rmtree(tmp_folder)
    162 
    163 
    164 def Upload(results, flakiness_dashboard_server, test_type):
    165  """Reports test results to the flakiness dashboard for Chrome for Android.
    166 
    167  Args:
    168    results: test results.
    169    flakiness_dashboard_server: the server to upload the results to.
    170    test_type: the type of the tests (as displayed by the flakiness dashboard).
    171  """
    172  uploader = ResultsUploader(test_type)
    173  uploader.AddResults(results)
    174  uploader.Upload(flakiness_dashboard_server)