Пример #1
0
    def testUpdateOwnerFromChartjson(self):
        chartjson_owner_dict_cache = {
            'ChromiumPerf/speedometer': {'*****@*****.**'},
            'ChromiumPerf/jetstream': {'*****@*****.**'},
        }
        master_owner_dict_cache = {
            'ChromiumPerf/speedometer':
            {'*****@*****.**', '*****@*****.**', '*****@*****.**'},
            'ChromiumPerf/jetstream': {'*****@*****.**'},
            'ChromiumPerf/octane': {'*****@*****.**'},
        }
        new_chartjson_owner_dict = {
            'ChromiumPerf/speedometer': {'*****@*****.**'},
            'ChromiumPerf/jetstream': None,
            'ChromiumPerf/spaceport': {'*****@*****.**'},
        }

        layered_cache.SetExternal(test_owner._CHARTJSON_OWNER_CACHE_KEY,
                                  chartjson_owner_dict_cache)
        layered_cache.SetExternal(test_owner._MASTER_OWNER_CACHE_KEY,
                                  master_owner_dict_cache)

        test_owner.UpdateOwnerFromChartjson(new_chartjson_owner_dict)

        updated_chartjson_owner_dict = layered_cache.GetExternal(
            test_owner._CHARTJSON_OWNER_CACHE_KEY)
        self.assertEqual(_ANOTHER_SAMPLE_OWNER_DICT,
                         updated_chartjson_owner_dict)

        updated_master_owner_dict = layered_cache.GetExternal(
            test_owner._MASTER_OWNER_CACHE_KEY)
        self.assertEqual(_COMBINED_SAMPLE_OWNER_DICT,
                         updated_master_owner_dict)
Пример #2
0
  def test_AdminAddsAndRemovesOther_Succeeds(self):
    self.SetCurrentUser('*****@*****.**', is_admin=True)
    self._SetOwnersDict(_SAMPLE_OWNER_DICT)

    # Test adding test owner.
    self.testapp.post('/edit_test_owners', {
        'action': 'add',
        'item': 'ChromiumPerf/speedometer',
        'sub_item': '*****@*****.**',
        'xsrf_token': xsrf.GenerateToken(users.get_current_user()),
    })
    owner_dict = layered_cache.GetExternal(test_owner._MASTER_OWNER_CACHE_KEY)
    self.assertIn('*****@*****.**', owner_dict['ChromiumPerf/speedometer'])

    # Test removing test owner.
    self.testapp.post('/edit_test_owners', {
        'action': 'remove',
        'item': 'ChromiumPerf/speedometer',
        'sub_item': '*****@*****.**',
        'xsrf_token': xsrf.GenerateToken(users.get_current_user()),
    })
    owner_dict = layered_cache.GetExternal(test_owner._MASTER_OWNER_CACHE_KEY)
    self.assertNotIn(
        '*****@*****.**', owner_dict['ChromiumPerf/speedometer'])

    # Test removing all test owners for a test suite path.
    self.testapp.post('/edit_test_owners', {
        'action': 'remove',
        'item': 'ChromiumPerf/speedometer',
        'xsrf_token': xsrf.GenerateToken(users.get_current_user()),
    })
    owner_dict = layered_cache.GetExternal(test_owner._MASTER_OWNER_CACHE_KEY)
    self.assertNotIn('ChromiumPerf/speedometer', owner_dict)
Пример #3
0
 def testRemoveOwnerFromDict(self):
     layered_cache.SetExternal(test_owner._MASTER_OWNER_CACHE_KEY,
                               _SAMPLE_OWNER_DICT)
     test_owner.RemoveOwnerFromDict(_SAMPLE_OWNER_DICT)
     owner_dict = layered_cache.GetExternal(
         test_owner._MASTER_OWNER_CACHE_KEY)
     self.assertEqual({}, owner_dict)
Пример #4
0
 def testAddOwner(self):
     test_owner.AddOwner('ChromiumPerf/speedometer', '*****@*****.**')
     test_owner.AddOwner('ChromiumPerf/speedometer', '*****@*****.**')
     test_owner.AddOwner('ChromiumPerf/octane', '*****@*****.**')
     owner_dict = layered_cache.GetExternal(
         test_owner._MASTER_OWNER_CACHE_KEY)
     self.assertEqual(_SAMPLE_OWNER_DICT, owner_dict)
Пример #5
0
  def testGet_PositiveResult_StoresCommitHash(self):
    self._AddTryJob(12345, 'started', 'win_perf',
                    results_data=_SAMPLE_BISECT_RESULTS_JSON)

    self.testapp.get('/update_bug_with_results')
    self.assertEqual('12345',
                     layered_cache.GetExternal('commit_hash_2a1781d64d'))
Пример #6
0
    def testGet_BisectCulpritHasAuthor_DoesNotMergeIntoBugWithMultipleCulprits(
            self, mock_update_bug):
        data = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
        self._AddTryJob(123, 'completed', 'win_perf', results_data=data)
        layered_cache.SetExternal('commit_hash_2a1781d64d', '123')

        data = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
        data['culprit_data']['email'] = '*****@*****.**'
        data['culprit_data']['cl'] = 'BBBBBBBB'
        self._AddTryJob(123, 'completed', 'linux_perf', results_data=data)
        layered_cache.SetExternal('commit_hash_BBBBBBBB', '123')

        self._AddTryJob(456,
                        'started',
                        'win_perf',
                        results_data=_SAMPLE_BISECT_RESULTS_JSON)

        self.testapp.get('/update_bug_with_results')
        mock_update_bug.assert_called_once_with(
            mock.ANY,
            mock.ANY,
            cc_list=['*****@*****.**', '*****@*****.**'],
            merge_issue=None,
            labels=None,
            owner='*****@*****.**',
            status='Assigned')

        # Should have skipped updating cache.
        self.assertEqual(layered_cache.GetExternal('commit_hash_2a1781d64d'),
                         '456')
Пример #7
0
 def testAddOwnerFromDict(self):
     layered_cache.SetExternal(test_owner._MASTER_OWNER_CACHE_KEY,
                               _SAMPLE_OWNER_DICT)
     test_owner.AddOwnerFromDict(_ANOTHER_SAMPLE_OWNER_DICT)
     owner_dict = layered_cache.GetExternal(
         test_owner._MASTER_OWNER_CACHE_KEY)
     self.assertEqual(_COMBINED_SAMPLE_OWNER_DICT, owner_dict)
Пример #8
0
def _PostSuccessfulResult(job, issue_tracker):
    """Posts successful bisect results on issue tracker."""
    # From the results, get the list of people to CC (if applicable), the bug
    # to merge into (if applicable) and the commit hash cache key, which
    # will be used below.
    if job.bug_id < 0:
        return

    results_data = job.results_data
    authors_to_cc = []
    commit_cache_key = _GetCommitHashCacheKey(results_data)

    merge_issue = layered_cache.GetExternal(commit_cache_key)
    if not merge_issue:
        authors_to_cc = _GetAuthorsToCC(results_data)

    comment = bisect_report.GetReport(job)

    # Add a friendly message to author of culprit CL.
    owner = None
    if authors_to_cc:
        comment = '%s%s%s' % (_GetAutoAssignHeader(results_data),
                              _AUTO_ASSIGN_MSG % {
                                  'author': authors_to_cc[0]
                              }, comment)
        owner = authors_to_cc[0]
    # Set restrict view label if the bisect results are internal only.
    labels = ['Restrict-View-Google'] if job.internal_only else None
    comment_added = issue_tracker.AddBugComment(job.bug_id,
                                                comment,
                                                cc_list=authors_to_cc,
                                                merge_issue=merge_issue,
                                                labels=labels,
                                                owner=owner)
    if not comment_added:
        raise BugUpdateFailure('Failed to update bug %s with comment %s' %
                               (job.bug_id, comment))

    logging.info('Updated bug %s with results from %s', job.bug_id,
                 job.rietveld_issue_id)

    if merge_issue:
        _MapAnomaliesToMergeIntoBug(merge_issue, job.bug_id)
        # Mark the duplicate bug's Bug entity status as closed so that
        # it doesn't get auto triaged.
        bug = ndb.Key('Bug', job.bug_id).get()
        if bug:
            bug.status = bug_data.BUG_STATUS_CLOSED
            bug.put()

    # Cache the commit info and bug ID to datastore when there is no duplicate
    # issue that this issue is getting merged into. This has to be done only
    # after the issue is updated successfully with bisect information.
    if commit_cache_key and not merge_issue:
        layered_cache.SetExternal(commit_cache_key,
                                  str(job.bug_id),
                                  days_to_keep=30)
        logging.info('Cached bug id %s and commit info %s in the datastore.',
                     job.bug_id, commit_cache_key)
Пример #9
0
  def testPost_NonAdminAddsAndRemovesSelf_Succeeds(self):
    self.SetCurrentUser('*****@*****.**', is_admin=False)
    self._SetOwnersDict(_SAMPLE_OWNER_DICT)

    self.testapp.post('/edit_test_owners', {
        'action': 'add',
        'item': 'ChromiumPerf/spaceport',
        'xsrf_token': xsrf.GenerateToken(users.get_current_user()),
    })
    owner_dict = layered_cache.GetExternal(test_owner._MASTER_OWNER_CACHE_KEY)
    self.assertIn('ChromiumPerf/spaceport', owner_dict)
    self.assertIn('*****@*****.**', owner_dict['ChromiumPerf/spaceport'])

    self.testapp.post('/edit_test_owners', {
        'action': 'remove',
        'item': 'ChromiumPerf/spaceport',
        'xsrf_token': xsrf.GenerateToken(users.get_current_user()),
    })
    owner_dict = layered_cache.GetExternal(test_owner._MASTER_OWNER_CACHE_KEY)
    self.assertNotIn('ChromiumPerf/spaceport', owner_dict)
 def testGetAndSet_External(self):
     layered_cache.SetExternal('str', 'Hello, World!')
     layered_cache.SetExternal('dict', {'hello': [1, 2, 3]})
     self.assertEqual(
         'Hello, World!',
         cPickle.loads(
             ndb.Key('CachedPickledString',
                     'externally_visible__str').get().value))
     self.assertEqual(
         None,
         ndb.Key('CachedPickledString', 'internal_only__str').get())
     self.assertEqual('Hello, World!', layered_cache.GetExternal('str'))
     self.assertEqual({'hello': [1, 2, 3]},
                      cPickle.loads(
                          ndb.Key('CachedPickledString',
                                  'externally_visible__dict').get().value))
     self.assertEqual(
         None,
         ndb.Key('CachedPickledString', 'internal_only__dict').get())
     self.assertEqual({'hello': [1, 2, 3]},
                      layered_cache.GetExternal('dict'))
  def testGet_BisectCulpritHasAuthor_MergesBugWithExisting(
      self, mock_update_bug, mock_merge_anomalies):
    layered_cache.SetExternal('commit_hash_2a1781d64d', 111222)
    self._AddTryJob(12345, 'started', 'win_perf',
                    results_data=_SAMPLE_BISECT_RESULTS_JSON)

    self.testapp.get('/update_bug_with_results')
    mock_update_bug.assert_called_once_with(
        mock.ANY, mock.ANY,
        cc_list=[], merge_issue='111222', labels=None, owner=None,
        status=None)
    # Should have skipped updating cache.
    self.assertEqual(
        layered_cache.GetExternal('commit_hash_2a1781d64d'), 111222)
    mock_merge_anomalies.assert_called_once_with('111222', 12345)
  def testGet_BisectCulpritHasAuthor_DoesNotMergeDuplicate(
      self, mock_update_bug, mock_merge_anomalies):
    layered_cache.SetExternal('commit_hash_2a1781d64d', 111222)
    self._AddTryJob(12345, 'started', 'win_perf',
                    results_data=_SAMPLE_BISECT_RESULTS_JSON)

    self.testapp.get('/update_bug_with_results')
    mock_update_bug.assert_called_once_with(
        mock.ANY, mock.ANY,
        cc_list=['*****@*****.**', '*****@*****.**'],
        merge_issue=None, labels=None, owner='*****@*****.**',
        status='Assigned')
    # Should have skipped updating cache.
    self.assertEqual(
        layered_cache.GetExternal('commit_hash_2a1781d64d'), 111222)
    # Should have skipped mapping anomalies.
    self.assertEqual(0, mock_merge_anomalies.call_count)
Пример #13
0
def _GetMergeIssueDetails(issue_tracker, commit_cache_key):
  """Get's the issue this one might be merged into.

  Returns: A dict with the following fields:
    issue: The issue details from the issue tracker service.
    id: The id of the issue we should merge into. This may be set to None if
        either there is no other bug with this culprit, or we shouldn't try to
        merge into that bug.
    comments: Additional comments to add to the bug.
  """
  merge_issue_key = layered_cache.GetExternal(commit_cache_key)
  if not merge_issue_key:
    return {'issue': {}, 'id': None, 'comments': ''}

  merge_issue = issue_tracker.GetIssue(merge_issue_key)
  if not merge_issue:
    return {'issue': {}, 'id': None, 'comments': ''}

  # Check if we can duplicate this issue against an existing issue.
  merge_issue_id = None
  additional_comments = ""

  # We won't duplicate against an issue that itself is already
  # a duplicate though. Could follow the whole chain through but we'll
  # just keep things simple and flat for now.
  if merge_issue.get('status') != issue_tracker_service.STATUS_DUPLICATE:
    merge_issue_id = str(merge_issue.get('id'))

  # We also don't want to duplicate against an issue that already has a bunch
  # of bisects pointing at different culprits.
  if merge_issue_id:
    jobs = try_job.TryJob.query(
        try_job.TryJob.bug_id == int(merge_issue_id)).fetch()
    culprits = set([j.GetCulpritCL() for j in jobs if j.GetCulpritCL()])
    if len(culprits) >= 2:
      additional_comments += _NOT_DUPLICATE_MULTIPLE_BUGS_MSG % merge_issue_id
      merge_issue_id = None

  return {
      'issue': merge_issue,
      'id': merge_issue_id,
      'comments': additional_comments
  }
Пример #14
0
def UpdateBisectStats(bot_name, status):
  """Updates bisect run stat by bot name and status.

  Bisect stats stored in a layered_cache entity have the form below.  Each
  tick is one week and count is the sum of failed or completed bisect runs.

  {
    'failed': {
      bot_name: [[week_timestamp, count], [week_timestamp, count]],
    },
    'completed': {
      bot_name: [[week_timestamp, count], [week_timestamp, count]],
    }
  }

  Args:
    bot_name: Name of the bisect bot.
    status: Bisect status.  Either 'failed' or 'completed'.
  """
  # TODO(chrisphan): Add stats for staled bisect.
  if status not in ['failed', 'completed']:
    return
  series_name = _GetSeriesNameFromBotName(bot_name)
  week_timestamp = _GetLastMondayTimestamp()

  bisect_stats = layered_cache.GetExternal(_BISECT_STATS_CACHE_KEY)
  if not bisect_stats:
    bisect_stats = {
        'failed': {},
        'completed': {},
    }

  series_map = bisect_stats[status]
  if series_name not in series_map:
    series_map[series_name] = [[week_timestamp, 1]]
  else:
    series = series_map[series_name]
    if week_timestamp == series[-1][0]:
      series[-1][1] += 1
    else:
      series.append([week_timestamp, 1])

  layered_cache.SetExternal(_BISECT_STATS_CACHE_KEY, bisect_stats)
Пример #15
0
    def get(self):
        """Renders the UI with charts."""
        bisect_stats = layered_cache.GetExternal(_BISECT_STATS_CACHE_KEY)
        if not bisect_stats:
            bisect_stats = {'failed': [], 'completed': []}

        series_data = {
            'failed': bisect_stats['failed'],
            'completed': bisect_stats['completed']
        }

        total_series_data = {
            'failed': self._GetTotalBisectRunSeries(bisect_stats['failed']),
            'completed':
            self._GetTotalBisectRunSeries(bisect_stats['completed'])
        }

        self.RenderHtml(
            'bisect_stats.html', {
                'series_data': json.dumps(series_data),
                'total_series_data': json.dumps(total_series_data),
            })
Пример #16
0
def UpdateOwnerFromChartjson(owner_dict):
    """Updates test owners with test owner data from chartjson.

  Checks if tests owners have changed by matching |owner_dict| with the stored
  owner dict for chartjson and update the master owner dict accordingly.

  Args:
    owner_dict: A dictionary of Master/Test suite to set of owners.
  """
    add_owner_dict = {}
    remove_owner_dict = {}
    owner_dict_cache = layered_cache.GetExternal(
        _CHARTJSON_OWNER_CACHE_KEY) or {}

    for path, owners in owner_dict.iteritems():
        owners = owners or set()
        owners_cache = owner_dict_cache.get(path, set())
        if owners_cache:
            diff = owners_cache - owners
            if diff:
                remove_owner_dict[path] = diff
            diff = owners - owners_cache
            if diff:
                add_owner_dict[path] = diff
        else:
            add_owner_dict[path] = owners

        if owners:
            owner_dict_cache[path] = owners
        elif path in owner_dict_cache:
            del owner_dict_cache[path]

    if add_owner_dict or remove_owner_dict:
        layered_cache.SetExternal(_CHARTJSON_OWNER_CACHE_KEY, owner_dict_cache)
    if add_owner_dict:
        AddOwnerFromDict(add_owner_dict)
    if remove_owner_dict:
        RemoveOwnerFromDict(remove_owner_dict)
Пример #17
0
def GetMasterCachedOwner():
    """Gets test owner cached dictionary from layered_cache."""
    return layered_cache.GetExternal(_MASTER_OWNER_CACHE_KEY) or {}
Пример #18
0
def _GetMergeIssue(issue_tracker, commit_cache_key):
    """Get's the issue this one might be merged into."""
    merge_issue = layered_cache.GetExternal(commit_cache_key)
    if merge_issue:
        return issue_tracker.GetIssue(merge_issue)
    return {}