def test_reminder(self): """Test reminders.""" # Return the same status for all build types. self.mock.get.return_value = MockResponse( json.dumps({ 'projects': [ { 'history': [{ 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj0-id', 'success': False }], 'name': 'proj0', }, { 'history': [{ 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj0-id', 'success': False }], 'name': 'proj1', }, ] })) data_types.OssFuzzProject(id='proj0', name='proj0', ccs=['*****@*****.**']).put() data_types.OssFuzzBuildFailure( id='proj0', project_name='proj0', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id='1', consecutive_failures=7, build_type='fuzzing').put() data_types.OssFuzzProject(id='proj1', name='proj1', ccs=['*****@*****.**']).put() data_types.OssFuzzBuildFailure( id='proj1', project_name='proj1', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id='2', consecutive_failures=3, build_type='fuzzing').put() self.itm.issues[1] = Issue() self.itm.issues[2] = Issue() self.app.get('/build-status') self.assertEqual( 'Friendly reminder that the the build is still failing.\n' 'Please try to fix this failure to ensure that fuzzing remains ' 'productive.\n' 'Latest build log: https://oss-fuzz-build-logs.storage.googleapis.com/' 'log-proj0-id.txt\n', self.itm.issues[1].comment) self.assertEqual('', self.itm.issues[2].comment)
def create_build_failure(failure, build_type): """Create new build failure.""" return data_types.OssFuzzBuildFailure( id=_get_ndb_key(failure['name'], build_type), project_name=failure['name'], last_checked_timestamp=get_build_time(failure), build_type=build_type)
def test_disabled_project(self): """Test disabled project.""" # Return the same status for all build types. self.mock.get.return_value = MockResponse( json.dumps({ 'projects': [ { 'history': [{ 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj2-id', 'success': False }], 'name': 'disabled_proj', }, ] })) # Only fuzzing build type failure should be stored. data_types.OssFuzzBuildFailure( id='disabled_proj', project_name='disabled_proj', last_checked_timestamp=datetime.datetime(2018, 1, 31), consecutive_failures=1, build_type='fuzzing').put() self.app.get('/build-status') six.assertCountEqual(self, [ { 'build_type': 'fuzzing', 'consecutive_failures': 1, 'issue_id': None, 'last_checked_timestamp': datetime.datetime(2018, 1, 31, 0, 0), 'project_name': u'disabled_proj', }, ], [ failure.to_dict() for failure in data_types.OssFuzzBuildFailure.query() ]) self.assertEqual(0, len(self.itm.issues))
def test_recovered_build_failure(self): """Test fixed build failures.""" # Use the same status for all build types. self.mock.get.return_value = MockResponse( json.dumps({ 'successes': [ { 'name': 'proj0', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj0-id', }, ], 'failures': [], })) data_types.OssFuzzBuildFailure( id='proj0', project_name='proj0', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id='1', consecutive_failures=2, build_type='fuzzing').put() issue = Issue() issue.open = True issue.add_label('Type-Build-Failure') issue.add_label('Proj-proj2') issue.summary = 'Build failure in proj2' issue.body = 'Build failure' self.itm.issues[1] = issue self.app.get('/build-status') self.assertEqual(0, data_types.OssFuzzBuildFailure.query().count()) issue = self.itm.issues[1] self.assertFalse(issue.open) self.assertEqual('Verified', issue.status) self.assertEqual('The latest build has succeeded, closing this issue.', issue.comment)
def test_build_failures(self): """Test run with multiple build failures of different type.""" def _mock_requests_get(url): """Mock requests.get.""" if url == oss_fuzz_build_status.FUZZING_STATUS_URL: return MockResponse( json.dumps({ 'successes': [ # Both fuzzing and coverage build types are successful. { 'name': 'proj0', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj0-id-f', }, # Only coverage build type is broken for a while. { 'name': 'proj5', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj5-id-f', }, # Only coverage build type broken. { 'name': 'proj6', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj6-id-f', }, ], 'failures': [ # New failure (first 1). { 'name': 'proj1', 'finish_time': '2018-02-01T00:00:00.000000000Z', 'build_id': 'proj1-id-f', }, # Seen failure (second consecutive). { 'name': 'proj2', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj2-id-f', }, # Seen failure (not updated). { 'name': 'proj3', 'finish_time': '2018-01-31T00:00:00.000000Z', 'build_id': 'proj3-id-f', }, # Seen failure (third consecutive, bug already filed). { 'name': 'proj4', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj4-id-f', }, ], })) assert url == oss_fuzz_build_status.COVERAGE_STATUS_URL return MockResponse( json.dumps({ 'successes': [ # Both fuzzing and coverage build types are successful. { 'name': 'proj0', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj0-id-c', }, ], 'failures': [ # New failure (first 1). { 'name': 'proj1', 'finish_time': '2018-02-01T00:00:00.000000000Z', 'build_id': 'proj1-id-c', }, # Seen failure (second consecutive). { 'name': 'proj2', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj2-id-c', }, # Seen failure (not updated). { 'name': 'proj3', 'finish_time': '2018-01-31T00:00:00.000000Z', 'build_id': 'proj3-id-c', }, # Seen failure (third consecutive, bug already filed). { 'name': 'proj4', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj4-id-c', }, # Coverage build type is broken for a while. { 'name': 'proj5', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj5-id-c', }, # Only coverage build type broken (second consecutive). { 'name': 'proj6', 'finish_time': '2018-02-01T00:00:00.000000Z', 'build_id': 'proj6-id-c', }, ], })) self.mock.get.side_effect = _mock_requests_get data_types.OssFuzzBuildFailure( id='proj2', project_name='proj2', last_checked_timestamp=datetime.datetime(2018, 1, 31), consecutive_failures=1, build_type='fuzzing').put() data_types.OssFuzzBuildFailure( id='proj3', project_name='proj3', last_checked_timestamp=datetime.datetime(2018, 1, 31), consecutive_failures=1, build_type='fuzzing').put() data_types.OssFuzzBuildFailure( id='proj4', project_name='proj4', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id='1337', consecutive_failures=2, build_type='fuzzing').put() data_types.OssFuzzBuildFailure( id='proj5-coverage', project_name='proj5', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id='31337', consecutive_failures=5, build_type='coverage').put() data_types.OssFuzzBuildFailure( id='proj6-coverage', project_name='proj6', last_checked_timestamp=datetime.datetime(2018, 1, 31), issue_id=None, consecutive_failures=1, build_type='coverage').put() data_types.OssFuzzProject(id='proj2', name='proj2', ccs=['*****@*****.**']).put() data_types.OssFuzzProject(id='proj6', name='proj7', ccs=['*****@*****.**']).put() self.app.get('/build-status') self.assertItemsEqual([ { 'build_type': 'fuzzing', 'consecutive_failures': 1, 'issue_id': None, 'last_checked_timestamp': datetime.datetime(2018, 2, 1, 0, 0), 'project_name': u'proj1' }, { 'build_type': 'fuzzing', 'consecutive_failures': 2, 'issue_id': '1', 'last_checked_timestamp': datetime.datetime(2018, 2, 1, 0, 0), 'project_name': u'proj2' }, { 'build_type': 'fuzzing', 'consecutive_failures': 1, 'issue_id': None, 'last_checked_timestamp': datetime.datetime(2018, 1, 31, 0, 0), 'project_name': u'proj3' }, { 'build_type': 'fuzzing', 'consecutive_failures': 3, 'issue_id': '1337', 'last_checked_timestamp': datetime.datetime(2018, 2, 1, 0, 0), 'project_name': u'proj4' }, { 'build_type': 'coverage', 'consecutive_failures': 6, 'issue_id': '31337', 'last_checked_timestamp': datetime.datetime(2018, 2, 1, 0, 0), 'project_name': u'proj5' }, { 'build_type': 'coverage', 'consecutive_failures': 2, 'issue_id': '2', 'last_checked_timestamp': datetime.datetime(2018, 2, 1, 0, 0), 'project_name': u'proj6' }, ], [ failure.to_dict() for failure in data_types.OssFuzzBuildFailure.query() ]) self.assertEqual(2, len(self.itm.issues)) issue = self.itm.issues[1] self.assertItemsEqual(['*****@*****.**'], issue.cc) self.assertEqual('New', issue.status) self.assertEqual('proj2: Build failure', issue.summary) self.assertEqual( 'The last 2 builds for proj2 have been failing.\n' '<b>Build log:</b> ' 'https://oss-fuzz-build-logs.storage.googleapis.com/' 'log-proj2-id-f.txt\n' 'Build type: fuzzing\n\n' 'To reproduce locally, please see: ' 'https://github.com/google/oss-fuzz/' 'blob/master/docs/reproducing.md#reproducing-build-failures\n\n' 'If you have any questions, please file a bug on ' 'https://github.com/google/oss-fuzz/issues/new.\n\n' '**This bug will be automatically closed within a ' 'day once it is fixed.**', issue.body) self.assertTrue(issue.has_label('Proj-proj2')) self.assertTrue(issue.has_label('Type-Build-Failure')) issue = self.itm.issues[2] self.assertItemsEqual(['*****@*****.**'], issue.cc) self.assertEqual('New', issue.status) self.assertEqual('proj6: Build failure', issue.summary) self.assertEqual( 'The last 2 builds for proj6 have been failing.\n' '<b>Build log:</b> ' 'https://oss-fuzz-build-logs.storage.googleapis.com/' 'log-proj6-id-c.txt\n' 'Build type: coverage\n\n' 'To reproduce locally, please see: ' 'https://github.com/google/oss-fuzz/' 'blob/master/docs/reproducing.md#reproducing-build-failures\n\n' 'If you have any questions, please file a bug on ' 'https://github.com/google/oss-fuzz/issues/new.\n\n' '**This bug will be automatically closed within a ' 'day once it is fixed.**', issue.body) self.assertTrue(issue.has_label('Proj-proj6')) self.assertTrue(issue.has_label('Type-Build-Failure'))