def _MockFetch(url=None): if start_try_job._BISECT_CONFIG_PATH in url: return testing_common.FakeResponseObject( 200, base64.encodestring(_BISECT_CONFIG_CONTENTS)) elif start_try_job._PERF_CONFIG_PATH in url: return testing_common.FakeResponseObject( 200, base64.encodestring(_PERF_CONFIG_CONTENTS))
def _MockFetch(unused_url): # pylint: disable=unused-argument response_text = _UNIT_JSON if malformed_json: response_text = 'this is not json' if base64_encoded: response_text = base64.b64encode(response_text) return testing_common.FakeResponseObject(status, response_text)
def _MockMakeRequest(path, *args, **kwargs): # pylint: disable=unused-argument """Mocks out a request, returning a canned response.""" if path.endswith('xsrf_token'): assert kwargs['headers']['X-Requesting-XSRF-Token'] == 1 return testing_common.FakeResponseObject(200, _FAKE_XSRF_TOKEN) if path == 'upload': assert kwargs['method'] == 'POST' assert _EXPECTED_CONFIG_DIFF in kwargs['body'], ( '%s\nnot in\n%s\n' % (_EXPECTED_CONFIG_DIFF, kwargs['body'])) return testing_common.FakeResponseObject(200, _ISSUE_CREATED_RESPONSE) if path == '33001/upload_content/1/1001': assert kwargs['method'] == 'POST' assert _TEST_EXPECTED_CONFIG_CONTENTS in kwargs['body'] return testing_common.FakeResponseObject(200, 'Dummy content') if path == '33001/upload_complete/1': assert kwargs['method'] == 'POST' return testing_common.FakeResponseObject(200, 'Dummy content') if path == '33001/try/1': assert _TEST_EXPECTED_BOT in kwargs['body'] return testing_common.FakeResponseObject(200, 'Dummy content') assert False, 'Invalid url %s requested!' % path
def _MockFetch(url=None): url_to_response_map = { 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20798': [200, _REVISION_RESPONSE], 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20799': [200, 'REVISION REQUEST FAILED!'], 'https://codereview.chromium.org/api/17504006': [200, json.dumps(json.loads(_ISSUE_RESPONSE))], } if url not in url_to_response_map: assert False, 'Bad url %s' % url response_code = url_to_response_map[url][0] response = url_to_response_map[url][1] return testing_common.FakeResponseObject(response_code, response)
class FileBugTest(testing_common.TestCase): def setUp(self): super(FileBugTest, self).setUp() app = webapp2.WSGIApplication([('/file_bug', file_bug.FileBugHandler)]) self.testapp = webtest.TestApp(app) testing_common.SetSheriffDomains(['chromium.org']) testing_common.SetIsInternalUser('*****@*****.**', True) testing_common.SetIsInternalUser('*****@*****.**', False) self.SetCurrentUser('*****@*****.**') # Add a fake issue tracker service that we can get call values from. file_bug.issue_tracker_service = mock.MagicMock() self.original_service = file_bug.issue_tracker_service.IssueTrackerService self.service = MockIssueTrackerService file_bug.issue_tracker_service.IssueTrackerService = self.service def tearDown(self): super(FileBugTest, self).tearDown() file_bug.issue_tracker_service.IssueTrackerService = self.original_service self.UnsetCurrentUser() def _AddSampleAlerts(self): """Adds sample data and returns a dict of rev to anomaly key.""" # Add sample sheriff, masters, bots, and tests. sheriff_key = sheriff.Sheriff(id='Sheriff').put() testing_common.AddTests( ['ChromiumPerf'], ['linux'], {'scrolling': { 'first_paint': {}, 'mean_frame_time': {}, }}) test_key1 = utils.TestKey('ChromiumPerf/linux/scrolling/first_paint') test_key2 = utils.TestKey( 'ChromiumPerf/linux/scrolling/mean_frame_time') anomaly_key1 = self._AddAnomaly(111995, 112005, test_key1, sheriff_key) anomaly_key2 = self._AddAnomaly(112000, 112010, test_key2, sheriff_key) return (anomaly_key1, anomaly_key2) def _AddAnomaly(self, start_rev, end_rev, test_key, sheriff_key): return anomaly.Anomaly(start_revision=start_rev, end_revision=end_rev, test=test_key, median_before_anomaly=100, median_after_anomaly=200, sheriff=sheriff_key).put() def testGet_WithNoKeys_ShowsError(self): # When a request is made and no keys parameter is given, # an error message is shown in the reply. response = self.testapp.get( '/file_bug?summary=s&description=d&finish=true') self.assertIn('<div class="error">', response.body) self.assertIn('No alerts specified', response.body) def testGet_WithNoFinish_ShowsForm(self): # When a GET request is sent with keys specified but the finish parameter # is not given, the response should contain a form for the sheriff to fill # in bug details (summary, description, etc). alert_keys = self._AddSampleAlerts() response = self.testapp.get( '/file_bug?summary=s&description=d&keys=%s' % alert_keys[0].urlsafe()) self.assertEqual(1, len(response.html('form'))) def testInternalBugLabel(self): # If any of the alerts are marked as internal-only, which should happen # when the corresponding test is internal-only, then the create bug dialog # should suggest adding a Restrict-View-Google label. self.SetCurrentUser('*****@*****.**') alert_keys = self._AddSampleAlerts() anomaly_entity = alert_keys[0].get() anomaly_entity.internal_only = True anomaly_entity.put() response = self.testapp.get( '/file_bug?summary=s&description=d&keys=%s' % alert_keys[0].urlsafe()) self.assertIn('Restrict-View-Google', response.body) def testGet_SetsBugLabelsComponents(self): self.SetCurrentUser('*****@*****.**') alert_keys = self._AddSampleAlerts() bug_label_patterns.AddBugLabelPattern('label1-foo', '*/*/*/first_paint') bug_label_patterns.AddBugLabelPattern('Cr-Performance-Blink', '*/*/*/mean_frame_time') response = self.testapp.get( '/file_bug?summary=s&description=d&keys=%s,%s' % (alert_keys[0].urlsafe(), alert_keys[1].urlsafe())) self.assertIn('label1-foo', response.body) self.assertIn('Performance>Blink', response.body) @mock.patch( 'google.appengine.api.app_identity.get_default_version_hostname', mock.MagicMock(return_value='chromeperf.appspot.com')) @mock.patch.object(file_bug.auto_bisect, 'StartNewBisectForBug', mock.MagicMock(return_value={ 'issue_id': 123, 'issue_url': 'foo.com' })) def _PostSampleBug(self): alert_keys = self._AddSampleAlerts() response = self.testapp.post('/file_bug', [ ('keys', '%s,%s' % (alert_keys[0].urlsafe(), alert_keys[1].urlsafe())), ('summary', 's'), ('description', 'd\n'), ('finish', 'true'), ('label', 'one'), ('label', 'two'), ('component', 'Foo>Bar'), ]) return response @mock.patch.object(file_bug, '_GetAllCurrentVersionsFromOmahaProxy', mock.MagicMock(return_value=[])) @mock.patch.object(file_bug.auto_bisect, 'StartNewBisectForBug', mock.MagicMock(return_value={ 'issue_id': 123, 'issue_url': 'foo.com' })) def testGet_WithFinish_CreatesBug(self): # When a POST request is sent with keys specified and with the finish # parameter given, an issue will be created using the issue tracker # API, and the anomalies will be updated, and a response page will # be sent which indicates success. self.service.bug_id = 277761 response = self._PostSampleBug() # The response page should have a bug number. self.assertIn('277761', response.body) # The anomaly entities should be updated. for anomaly_entity in anomaly.Anomaly.query().fetch(): if anomaly_entity.end_revision in [112005, 112010]: self.assertEqual(277761, anomaly_entity.bug_id) else: self.assertIsNone(anomaly_entity.bug_id) # Two HTTP requests are made when filing a bug; only test 2nd request. comment = self.service.add_comment_args[1] self.assertIn( 'https://chromeperf.appspot.com/group_report?bug_id=277761', comment) self.assertIn('https://chromeperf.appspot.com/group_report?keys=', comment) self.assertIn( '\n\n\nBot(s) for this bug\'s original alert(s):\n\nlinux', comment) @mock.patch.object(file_bug, '_GetAllCurrentVersionsFromOmahaProxy', mock.MagicMock(return_value=[{ 'versions': [{ 'branch_base_position': '112000', 'current_version': '2.0' }, { 'branch_base_position': '111990', 'current_version': '1.0' }] }])) @mock.patch.object(file_bug.auto_bisect, 'StartNewBisectForBug', mock.MagicMock(return_value={ 'issue_id': 123, 'issue_url': 'foo.com' })) def testGet_WithFinish_LabelsBugWithMilestone(self): # Here, we expect the bug to have the following start revisions: # [111995, 112005] and the milestones are M-1 for rev 111990 and # M-2 for 11200. Hence the expected behavior is to label the bug # M-2 since 111995 (lowest possible revision introducing regression) # is less than 112000 (revision for M-2). self._PostSampleBug() self.assertIn('M-2', self.service.new_bug_kwargs['labels']) @unittest.skip('Flaky; see #1555.') @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, json.dumps([{ 'versions': [{ 'branch_base_position': '111999', 'current_version': '3.0.1234.32' }, { 'branch_base_position': '112000', 'current_version': '2.0' }, { 'branch_base_position': '111990', 'current_version': '1.0' }] }])))) def testGet_WithFinish_LabelsBugWithLowestMilestonePossible(self): # Here, we expect the bug to have the following start revisions: # [111995, 112005] and the milestones are M-1 for rev 111990, M-2 # for 112000 and M-3 for 111999. Hence the expected behavior is to # label the bug M-2 since 111995 is less than 112000 (M-2) and 111999 # (M-3) AND M-2 is lower than M-3. self._PostSampleBug() self.assertIn('M-2', self.service.new_bug_kwargs['labels']) @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock( return_value=testing_common.FakeResponseObject(200, '[]'))) def testGet_WithFinish_SucceedsWithNoVersions(self): # Here, we test that we don't label the bug with an unexpected value when # there is no version information from omahaproxy (for whatever reason) self._PostSampleBug() labels = self.service.new_bug_kwargs['labels'] self.assertEqual(0, len([x for x in labels if x.startswith(u'M-')])) @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock( return_value=testing_common.FakeResponseObject(200, '[]'))) def testGet_WithFinish_SucceedsWithComponents(self): # Here, we test that components are posted separately from labels. self._PostSampleBug() self.assertIn('Foo>Bar', self.service.new_bug_kwargs['components']) @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, json.dumps([{ 'versions': [{ 'branch_base_position': '0', 'current_version': '1.0' }] }])))) def testGet_WithFinish_SucceedsWithRevisionOutOfRange(self): # Here, we test that we label the bug with the highest milestone when the # revision introducing regression is beyond all milestones in the list. self._PostSampleBug() self.assertIn('M-1', self.service.new_bug_kwargs['labels']) @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, json.dumps([{ 'versions': [{ 'branch_base_position': 'N/A', 'current_version': 'N/A' }] }])))) @mock.patch('logging.warn') def testGet_WithFinish_SucceedsWithNAAndLogsWarning(self, mock_warn): self._PostSampleBug() labels = self.service.new_bug_kwargs['labels'] self.assertEqual(0, len([x for x in labels if x.startswith(u'M-')])) self.assertEqual(1, mock_warn.call_count)
class EmailSheriffTest(testing_common.TestCase): def _AddTestToStubDataStore(self): """Adds a test which will be used in the methods below.""" bug_label_patterns.AddBugLabelPattern('label1', '*/*/dromaeo/dom') bug_label_patterns.AddBugLabelPattern('label2', '*/*/other/test') testing_common.AddTests(['ChromiumPerf'], ['Win7'], {'dromaeo': { 'dom': {} }}) test = utils.TestKey('ChromiumPerf/Win7/dromaeo/dom').get() test.improvement_direction = anomaly.DOWN sheriff.Sheriff(id='Chromium Perf Sheriff', url=_SHERIFF_URL, email=_SHERIFF_EMAIL).put() return test def _GetDefaultMailArgs(self): """Adds an Anomaly and returns arguments for email_sheriff.EmailSheriff.""" test_entity = self._AddTestToStubDataStore() sheriff_entity = ndb.Key('Sheriff', 'Chromium Perf Sheriff').get() anomaly_entity = anomaly.Anomaly( median_before_anomaly=5.0, median_after_anomaly=10.0, start_revision=10002, end_revision=10004, sheriff=sheriff_entity.key, test=utils.TestKey('ChromiumPerf/Win7/dromaeo/dom')) return { 'sheriff': sheriff_entity, 'test': test_entity, 'anomaly': anomaly_entity } @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, 'document.write(\'sullivan\')'))) def testEmailSheriff_ContentAndRecipientAreCorrect(self): email_sheriff.EmailSheriff(**self._GetDefaultMailArgs()) messages = self.mail_stub.get_sent_messages() self.assertEqual(1, len(messages)) self.assertEqual('*****@*****.**', messages[0].sender) self.assertEqual('[email protected],[email protected]', messages[0].to) name = 'dromaeo/dom on Win7' expected_subject = '100.0%% regression in %s at 10002:10004' % name self.assertEqual(expected_subject, messages[0].subject) body = str(messages[0].body) self.assertIn('10002 - 10004', body) self.assertIn('100.0%', body) self.assertIn('ChromiumPerf', body) self.assertIn('Win7', body) self.assertIn('dromaeo/dom', body) html = str(messages[0].html) self.assertIn('<b>10002 - 10004</b>', html) self.assertIn('<b>100.0%</b>', html) self.assertIn('<b>ChromiumPerf</b>', html) self.assertIn('<b>Win7</b>', html) self.assertIn('<b>dromaeo/dom</b>', html) # Bug links self.assertIn(urllib.quote(expected_subject), body) self.assertIn( 'labels=Type-Bug-Regression,Pri-2,Performance-Sheriff,label1', html) # Sheriff link self.assertIn( '/alerts?sheriff=%s' % urllib.quote('Chromium Perf Sheriff'), html) @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, 'document.write(\'sonnyrao, digit\')'))) def testEmailSheriff_MultipleSheriffs_AllGetEmailed(self): email_sheriff.EmailSheriff(**self._GetDefaultMailArgs()) messages = self.mail_stub.get_sent_messages() self.assertEqual(1, len(messages)) self.assertEqual('*****@*****.**', messages[0].sender) self.assertEqual( '[email protected],[email protected],[email protected]', messages[0].to) def testEmail_NoSheriffUrl_EmailSentToSheriffRotationEmailAddress(self): args = self._GetDefaultMailArgs() args['sheriff'].url = None email_sheriff.EmailSheriff(**args) messages = self.mail_stub.get_sent_messages() self.assertEqual(1, len(messages)) # An email is only sent to the general sheriff rotation email; # There is no other specific sheriff to send it to. self.assertEqual('*****@*****.**', messages[0].to) @mock.patch( 'google.appengine.api.urlfetch.fetch', mock.MagicMock( return_value=testing_common.FakeResponseObject(200, 'garbage'))) def testEmailSheriff_RotationUrlHasInvalidContent_EmailStillSent(self): """Tests the email to list when the rotation URL returns garbage.""" args = self._GetDefaultMailArgs() email_sheriff.EmailSheriff(**args) messages = self.mail_stub.get_sent_messages() self.assertEqual(1, len(messages)) # An email is only sent to the general sheriff rotation email. self.assertEqual('*****@*****.**', messages[0].to) def testEmailSheriff_PercentChangeMaxFloat_ContentSaysAlertSize(self): """Tests the email content for "freakin huge" alert.""" args = self._GetDefaultMailArgs() args['sheriff'].url = None args['anomaly'].median_before_anomaly = 0.0 email_sheriff.EmailSheriff(**args) messages = self.mail_stub.get_sent_messages() self.assertEqual(1, len(messages)) self.assertIn(anomaly.FREAKIN_HUGE, str(messages[0].subject)) self.assertNotIn(str(sys.float_info.max), str(messages[0].body)) self.assertIn(anomaly.FREAKIN_HUGE, str(messages[0].body)) self.assertNotIn(str(sys.float_info.max), str(messages[0].html)) self.assertIn(anomaly.FREAKIN_HUGE, str(messages[0].html))
def _MockFailedFetch(url=None): # pylint: disable=unused-argument return testing_common.FakeResponseObject(404, {})
class AssociateAlertsTest(testing_common.TestCase): def setUp(self): super(AssociateAlertsTest, self).setUp() app = webapp2.WSGIApplication([ ('/associate_alerts', associate_alerts.AssociateAlertsHandler) ]) self.testapp = webtest.TestApp(app) testing_common.SetSheriffDomains(['chromium.org']) self.SetCurrentUser('*****@*****.**', is_admin=True) def _AddSheriff(self): """Adds a Sheriff and returns its key.""" return sheriff.Sheriff(id='Chromium Perf Sheriff', email='*****@*****.**').put() def _AddTests(self): """Adds sample Tests and returns a list of their keys.""" testing_common.AddTests(['ChromiumGPU'], ['linux-release'], { 'scrolling-benchmark': { 'first_paint': {}, 'mean_frame_time': {}, } }) return map(utils.TestKey, [ 'ChromiumGPU/linux-release/scrolling-benchmark/first_paint', 'ChromiumGPU/linux-release/scrolling-benchmark/mean_frame_time', ]) def _AddAnomalies(self): """Adds sample Anomaly data and returns a dict of revision to key.""" sheriff_key = self._AddSheriff() test_keys = self._AddTests() key_map = {} # Add anomalies to the two tests alternately. for end_rev in range(10000, 10120, 10): test_key = test_keys[0] if end_rev % 20 == 0 else test_keys[1] anomaly_key = anomaly.Anomaly(start_revision=(end_rev - 5), end_revision=end_rev, test=test_key, median_before_anomaly=100, median_after_anomaly=200, sheriff=sheriff_key).put() key_map[end_rev] = anomaly_key.urlsafe() # Add an anomaly that overlaps. anomaly_key = anomaly.Anomaly(start_revision=9990, end_revision=9996, test=test_keys[0], median_before_anomaly=100, median_after_anomaly=200, sheriff=sheriff_key).put() key_map[9996] = anomaly_key.urlsafe() # Add an anomaly that overlaps and has bug ID. anomaly_key = anomaly.Anomaly(start_revision=9990, end_revision=9997, test=test_keys[0], median_before_anomaly=100, median_after_anomaly=200, sheriff=sheriff_key, bug_id=12345).put() key_map[9997] = anomaly_key.urlsafe() return key_map def testGet_NoKeys_ShowsError(self): response = self.testapp.get('/associate_alerts') self.assertIn('<div class="error">', response.body) def testGet_SameAsPost(self): get_response = self.testapp.get('/associate_alerts') post_response = self.testapp.post('/associate_alerts') self.assertEqual(get_response.body, post_response.body) def testGet_InvalidBugId_ShowsError(self): key_map = self._AddAnomalies() response = self.testapp.get('/associate_alerts?keys=%s&bug_id=foo' % key_map[9996]) self.assertIn('<div class="error">', response.body) self.assertIn('Invalid bug ID', response.body) # In this test method, the request handler is expected to use urlfetch.fetch # to request recent bug information. Below is some sample data in the format # returned by this request. @mock.patch('google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject( 200, json.dumps({ 'items': [ { 'id': 12345, 'summary': '5% regression in bot/suite/x at 10000:20000', 'state': 'open', 'status': 'New', 'author': { 'name': '*****@*****.**' }, }, { 'id': 13579, 'summary': '1% regression in bot/suite/y at 10000:20000', 'state': 'closed', 'status': 'WontFix', 'author': { 'name': '*****@*****.**' }, }, ] })))) def testGet_NoBugId_ShowsDialog(self): # When a GET request is made with some anomaly keys but no bug ID, # A HTML form is shown for the user to input a bug number. key_map = self._AddAnomalies() response = self.testapp.get('/associate_alerts?keys=%s' % key_map[10000]) # The response contains a table of recent bugs and a form. self.assertIn('12345', response.body) self.assertIn('13579', response.body) self.assertIn('<form', response.body) def testGet_WithBugId_AlertIsAssociatedWithBugId(self): # When the bug ID is given and the alerts overlap, then the Anomaly # entities are updated and there is a resopnse indicating success. key_map = self._AddAnomalies() response = self.testapp.get( '/associate_alerts?keys=%s,%s&bug_id=12345' % (key_map[9996], key_map[10000])) # The response page should have a bug number. self.assertIn('12345', response.body) # The Anomaly entities should be updated. for anomaly_entity in anomaly.Anomaly.query().fetch(): if anomaly_entity.end_revision in (10000, 9996): self.assertEqual(12345, anomaly_entity.bug_id) elif anomaly_entity.end_revision != 9997: self.assertIsNone(anomaly_entity.bug_id) def testGet_WithStoppageAlert_ChangesAlertBugId(self): test_keys = self._AddTests() rows = testing_common.AddRows(utils.TestPath(test_keys[0]), {10, 20}) alert_key = stoppage_alert.CreateStoppageAlert(test_keys[0].get(), rows[0]).put() self.testapp.get('/associate_alerts?bug_id=123&keys=%s' % alert_key.urlsafe()) self.assertEqual(123, alert_key.get().bug_id) def testGet_TargetBugHasNoAlerts_DoesNotAskForConfirmation(self): # Associating alert with bug ID that has no alerts is always OK. key_map = self._AddAnomalies() response = self.testapp.get('/associate_alerts?keys=%s,%s&bug_id=578' % (key_map[9996], key_map[10000])) # The response page should have a bug number. self.assertIn('578', response.body) # The Anomaly entities should be updated. self.assertEqual( 578, anomaly.Anomaly.query( anomaly.Anomaly.end_revision == 9996).get().bug_id) self.assertEqual( 578, anomaly.Anomaly.query( anomaly.Anomaly.end_revision == 10000).get().bug_id) def testGet_NonOverlappingAlerts_AsksForConfirmation(self): # Associating alert with bug ID that contains non-overlapping revision # ranges should show a confirmation page. key_map = self._AddAnomalies() response = self.testapp.get( '/associate_alerts?keys=%s,%s&bug_id=12345' % (key_map[10000], key_map[10010])) # The response page should show confirmation page. self.assertIn('Do you want to continue?', response.body) # The Anomaly entities should not be updated. for anomaly_entity in anomaly.Anomaly.query().fetch(): if anomaly_entity.end_revision != 9997: self.assertIsNone(anomaly_entity.bug_id) def testGet_WithConfirm_AssociatesWithNewBugId(self): # Associating alert with bug ID and with confirmed non-overlapping revision # range should update alert with bug ID. key_map = self._AddAnomalies() response = self.testapp.get( '/associate_alerts?confirm=true&keys=%s,%s&bug_id=12345' % (key_map[10000], key_map[10010])) # The response page should have the bug number. self.assertIn('12345', response.body) # The Anomaly entities should be updated. for anomaly_entity in anomaly.Anomaly.query().fetch(): if anomaly_entity.end_revision in (10000, 10010): self.assertEqual(12345, anomaly_entity.bug_id) elif anomaly_entity.end_revision != 9997: self.assertIsNone(anomaly_entity.bug_id) def testRevisionRangeFromSummary(self): # If the summary is in the expected format, a pair is returned. self.assertEqual( (10000, 10500), associate_alerts._RevisionRangeFromSummary( '1% regression in bot/my_suite/test at 10000:10500')) # Otherwise None is returned. self.assertIsNone( associate_alerts._RevisionRangeFromSummary( 'Regression in rev ranges 12345 to 20000')) def testRangesOverlap_NonOverlapping_ReturnsFalse(self): self.assertFalse(associate_alerts._RangesOverlap((1, 5), (6, 9))) self.assertFalse(associate_alerts._RangesOverlap((6, 9), (1, 5))) def testRangesOverlap_NoneGiven_ReturnsFalse(self): self.assertFalse(associate_alerts._RangesOverlap((1, 5), None)) self.assertFalse(associate_alerts._RangesOverlap(None, (1, 5))) self.assertFalse(associate_alerts._RangesOverlap(None, None)) def testRangesOverlap_OneIncludesOther_ReturnsTrue(self): # True if one range envelopes the other. self.assertTrue(associate_alerts._RangesOverlap((1, 9), (2, 5))) self.assertTrue(associate_alerts._RangesOverlap((2, 5), (1, 9))) def testRangesOverlap_PartlyOverlap_ReturnsTrue(self): self.assertTrue(associate_alerts._RangesOverlap((1, 6), (5, 9))) self.assertTrue(associate_alerts._RangesOverlap((5, 9), (1, 6))) def testRangesOverlap_CommonBoundary_ReturnsTrue(self): self.assertTrue(associate_alerts._RangesOverlap((1, 6), (6, 9))) self.assertTrue(associate_alerts._RangesOverlap((6, 9), (1, 6)))
def _MockFetch(_): response_text = json.dumps({'key': 'this is well-formed JSON.'}) if base64_encoded: response_text = base64.b64encode(response_text) return testing_common.FakeResponseObject(status, response_text)
def _MockFetch(url=None): url_to_response_map = { 'https://test-rietveld.appspot.com/api/200034/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/508' }] }) ], 'https://test-rietveld.appspot.com/api/302304/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '2', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/509' }] }) ], 'https://test-rietveld.appspot.com/api/100001/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '6', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/510' }] }) ], 'https://test-rietveld.appspot.com/api/200035/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/511' }] }) ], 'https://test-rietveld.appspot.com/api/200036/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/512' }] }) ], 'https://test-rietveld.appspot.com/api/200037/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/513' }] }) ], 'https://test-rietveld.appspot.com/api/200038/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/514' }] }) ], 'https://test-rietveld.appspot.com/api/200039/1': [ 200, json.dumps({ 'try_job_results': [{ 'result': '0', 'builder': 'win_perf_bisect', 'url': 'http://build.chromium.org/builders/515' }] }) ], 'http://build.chromium.org/json/builders/515': [ 200, json.dumps({ 'steps': [{ 'name': 'Working on abc', 'results': [0] }, { 'name': 'Working on def', 'results': [2] }], 'times': [1411501756.293642, 1411545237.89049], 'text': ['failed', 'slave_steps', 'failed', 'Working on def'] }) ], 'http://build.chromium.org/bb1234567/steps/Results/logs/stdio/text': [200, _BISECT_LOG_SINGLE_OWNER], 'http://build.chromium.org/bb66666': [ 200, json.dumps({ 'steps': [{ 'name': 'Working on abc', 'results': [0] }, { 'name': 'Working on def', 'results': [2] }], 'times': [1411501756.293642, 1411545237.89049], 'text': ['failed', 'slave_steps', 'failed', 'Working on def'] }) ], ('http://build.chromium.org/builders/bb66666' '/steps/Results/logs/stdio/text'): [404, ''], 'http://build.chromium.org/json/builders/516': [200, json.dumps({'steps': [{ 'name': 'gclient', 'results': [2] }]})], 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20798': [200, _REVISION_RESPONSE], 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20799': [200, 'REVISION REQUEST FAILED!'], 'https://codereview.chromium.org/api/17504006': [200, json.dumps(json.loads(_ISSUE_RESPONSE))], 'http://build.chromium.org/508/steps/Results/logs/stdio/text': [200, '===== BISECT JOB RESULTS ====='], 'http://build.chromium.org/509/steps/Results/logs/stdio/text': [200, 'BISECT FAILURE! '], 'http://build.chromium.org/511/steps/Results/logs/stdio/text': [200, _BISECT_LOG_MULTI_OWNER], 'http://build.chromium.org/512/steps/Results/logs/stdio/text': [200, _BISECT_LOG_MULTI_SAME_OWNER], 'http://build.chromium.org/513/steps/Results/logs/stdio/text': [200, _BISECT_LOG_SINGLE_OWNER], 'http://build.chromium.org/514/steps/Results/logs/stdio/text': [200, _BISECT_LOG_FAILED_REVISION], 'http://build.chromium.org/builders/515/steps/Results/logs/stdio/text': [404, ''], 'http://build.chromium.org/builders/515/steps/Working%20on%20abc/logs/' 'stdio/text': [200, _BISECT_LOG_PARTIAL_RESULT], 'http://build.chromium.org/builders/516/steps/slave_steps/logs/stdio/' 'text': [200, _BISECT_LOG_INFRA_FAILURE], 'http://build.chromium.org/508/steps/Running%20Bisection/logs/stdio/' 'text': [200, _PERF_LOG_WITH_RESULTS], 'http://build.chromium.org/511/steps/Running%20Bisection/logs/stdio/' 'text': [200, ''], } if url not in url_to_response_map: assert False, 'Bad url %s' % url response_code = url_to_response_map[url][0] response = url_to_response_map[url][1] return testing_common.FakeResponseObject(response_code, response)
class MainTest(testing_common.TestCase): def setUp(self): super(MainTest, self).setUp() app = webapp2.WSGIApplication([('/', main.MainHandler)]) self.testapp = webtest.TestApp(app) @mock.patch( 'google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject(500, '')) ) def testGet_BugRequestFails_PageIsStillShown(self): # Even if the recent bugs list can't be fetched, the page should load. response = self.testapp.get('/') self.assertIn('<html>', response.body) def testGetColorClass(self): self.assertEqual('over-50', main._GetColorClass(95)) self.assertEqual('over-40', main._GetColorClass(45)) self.assertEqual('over-30', main._GetColorClass(31)) self.assertEqual('over-20', main._GetColorClass(30)) self.assertEqual('over-10', main._GetColorClass(12.0)) self.assertEqual('under-10', main._GetColorClass(0.1)) def testGetTopBugsResult_DeadlineExceededError_ReturnsEmptyList(self): mock_rpc = mock.MagicMock() mock_rpc.get_result = mock.MagicMock( side_effect=urlfetch_errors.DeadlineExceededError) self.assertEqual([], main._GetTopBugsResult(mock_rpc)) def testGetTopBugsResult_DownloadError_ReturnsEmptyList(self): mock_rpc = mock.MagicMock() mock_rpc.get_result = mock.MagicMock( side_effect=urlfetch.DownloadError) self.assertEqual([], main._GetTopBugsResult(mock_rpc)) def testAnomalyInfoDicts(self): testing_common.AddTests(['M'], ['b'], {'t': {'foo': {}}}) foo_key = utils.TestKey('M/b/t/foo') foo_anomaly = anomaly.Anomaly(start_revision=14999, end_revision=15000, test=foo_key, bug_id=12345, median_before_anomaly=100, median_after_anomaly=200) anomaly_key = foo_anomaly.put() self.assertEqual([{ 'master': 'M', 'bot': 'b', 'testsuite': 't', 'test': 'foo', 'bug_id': 12345, 'start_revision': 14999, 'end_revision': 15000, 'key': anomaly_key.urlsafe(), 'dashboard_link': ('https://chromeperf.appspot.com' '/group_report?keys=%s' % anomaly_key.urlsafe()), 'percent_changed': '100.0%', 'color_class': 'over-50', 'improvement': False, }], main._AnomalyInfoDicts([foo_anomaly], {foo_key: foo_key.get()})) def testAnomalyInfoDicts_MissingTest_AnomalySkipped(self): testing_common.AddTests(['M'], ['b'], {'t': {'foo': {}}}) foo_key = utils.TestKey('M/b/t/foo') foo_anomaly = anomaly.Anomaly(start_revision=14999, end_revision=15000, test=foo_key, bug_id=12345, median_before_anomaly=100, median_after_anomaly=200) foo_anomaly.put() self.assertEqual([], main._AnomalyInfoDicts([foo_anomaly], {}))