| Index: appengine/chromium_try_flakes/status/test/cq_status_test.py
|
| diff --git a/appengine/chromium_try_flakes/status/test/cq_status_test.py b/appengine/chromium_try_flakes/status/test/cq_status_test.py
|
| index 43b306f8361ee80107d4e30ec23e5996f6ddcc7d..6ce616907da008b02baddbc2377b7af0e26658b5 100644
|
| --- a/appengine/chromium_try_flakes/status/test/cq_status_test.py
|
| +++ b/appengine/chromium_try_flakes/status/test/cq_status_test.py
|
| @@ -13,65 +13,12 @@ from google.appengine.runtime import DeadlineExceededError
|
|
|
| import main
|
| from model.fetch_status import FetchStatus
|
| -from model.flake import Flake, FlakyRun
|
| +from model.flake import Flake
|
| from model.build_run import BuildRun, PatchsetBuilderRuns
|
| from status import cq_status
|
| from testing_utils import testing
|
|
|
|
|
| -TEST_BUILDBOT_JSON_REPLY = json.dumps({
|
| - 'steps': [
|
| - # Simple case.
|
| - {'results': [2], 'name': 'foo1', 'text': ['bar1']},
|
| -
|
| - # Invalid test results.
|
| - {'results': [2], 'name': 'foo2', 'text': ['TEST RESULTS WERE INVALID']},
|
| -
|
| - # GTest tests.
|
| - {
|
| - 'results': [2],
|
| - 'name': 'foo3',
|
| - 'text': ['failures:<br/>bar2<br/>bar3<br/><br/>ignored:<br/>bar4']
|
| - },
|
| -
|
| - # GPU tests.
|
| - {
|
| - 'results': [2],
|
| - 'name': 'foo4',
|
| - 'text': ['<"http://url/path?query&tests=bar5,bar6,,bar7">']
|
| - },
|
| -
|
| - # Ignore non-success non-failure results (7 is TRY_PENDING).
|
| - {'results': [7], 'name': 'foo5', 'text': ['bar8']},
|
| -
|
| - # Ignore steps that are failing without patch too (ToT is broken).
|
| - {'results': [2], 'name': 'foo6 (with patch)', 'text': ['bar9']},
|
| - {'results': [2], 'name': 'foo6 (without patch)', 'text': ['bar9']},
|
| -
|
| - # Ignore steps that are duplicating error in another step.
|
| - {'results': [2], 'name': 'steps', 'text': ['bar10']},
|
| - {'results': [2], 'name': '[swarming] foo7', 'text': ['bar11']},
|
| - {'results': [2], 'name': 'presubmit', 'text': ['bar12']},
|
| - {'results': [2], 'name': 'recipe failure reason', 'text': ['bar12a']},
|
| - {'results': [2], 'name': 'test results', 'text': ['bar12b']},
|
| - {'results': [2], 'name': 'Uncaught Exception', 'text': ['bar12c']},
|
| - {'results': [2], 'name': 'bot_update', 'text': ['bot_update PATCH FAILED']},
|
| -
|
| - # Only count first step (with patch) and ignore summary step.
|
| - {'results': [2], 'name': 'foo8 (with patch)', 'text': ['bar13']},
|
| - {'results': [0], 'name': 'foo8 (without patch)', 'text': ['bar14']},
|
| - {'results': [2], 'name': 'foo8', 'text': ['bar15']},
|
| -
|
| - # GTest without flakes.
|
| - {
|
| - 'results': [2],
|
| - 'name': 'foo9',
|
| - 'text': ['failures:<br/><br/><br/>']
|
| - },
|
| -
|
| - ]
|
| -})
|
| -
|
| # Test results below capture various variants in which results may be processed.
|
| # Special attention should be paid to the 'issue' and 'patchset' fields as code
|
| # is expected to correctly process results from different issues and patchsets
|
| @@ -404,82 +351,6 @@ class CQStatusTestCase(testing.AppengineTestCase):
|
| self.assertEqual(tasks[1].url, '/issues/update-if-stale/234')
|
| self.assertEqual(tasks[2].url, '/issues/update-if-stale/345')
|
|
|
| - def _create_flaky_run(self, ts, tf):
|
| - pbr = PatchsetBuilderRuns(
|
| - issue=123456789, patchset=20001, master='test.master',
|
| - builder='test-builder').put()
|
| - br_f = BuildRun(parent=pbr, buildnumber=100, result=2, time_started=ts,
|
| - time_finished=tf).put()
|
| - br_s = BuildRun(parent=pbr, buildnumber=101, result=0, time_started=ts,
|
| - time_finished=tf).put()
|
| - return FlakyRun(failure_run=br_f, success_run=br_s,
|
| - failure_run_time_started=ts,
|
| - failure_run_time_finished=tf).put()
|
| -
|
| - def test_get_flaky_run_reason_ignores_invalid_json(self):
|
| - now = datetime.datetime.utcnow()
|
| - fr_key = self._create_flaky_run(now - datetime.timedelta(hours=1), now)
|
| -
|
| - urlfetch_mock = mock.Mock()
|
| - urlfetch_mock.return_value.content = 'invalid-json'
|
| -
|
| - with mock.patch('google.appengine.api.urlfetch.fetch', urlfetch_mock):
|
| - cq_status.get_flaky_run_reason(fr_key)
|
| -
|
| - def test_get_flaky_run_reason(self):
|
| - now = datetime.datetime.utcnow()
|
| - fr_key = self._create_flaky_run(now - datetime.timedelta(hours=1), now)
|
| -
|
| - urlfetch_mock = mock.Mock()
|
| - urlfetch_mock.return_value.content = TEST_BUILDBOT_JSON_REPLY
|
| -
|
| - # We also create one Flake to test that it is correctly updated. Other Flake
|
| - # entities will be created automatically.
|
| - Flake(id='bar5', name='bar5', occurrences=[],
|
| - last_time_seen=datetime.datetime.min).put()
|
| -
|
| - with mock.patch('google.appengine.api.urlfetch.fetch', urlfetch_mock):
|
| - cq_status.get_flaky_run_reason(fr_key)
|
| -
|
| - # Verify that we've used correct URL to access buildbot JSON endpoint.
|
| - urlfetch_mock.assert_called_once_with(
|
| - 'http://build.chromium.org/p/test.master/json/builders/test-builder/'
|
| - 'builds/100')
|
| -
|
| - # Expected flakes to be found: list of (step_name, test_name).
|
| - expected_flakes = [
|
| - ('foo1', 'bar1'), ('foo2', 'TEST RESULTS WERE INVALID'),
|
| - ('foo3', 'bar2'), ('foo3', 'bar3'), ('foo4', 'bar5'), ('foo4', 'bar6'),
|
| - ('foo4', 'bar7'), ('foo8 (with patch)', 'bar13'),
|
| - ]
|
| -
|
| - flake_occurrences = fr_key.get().flakes
|
| - print flake_occurrences
|
| - self.assertEqual(len(flake_occurrences), len(expected_flakes))
|
| - actual_flake_occurrences = [
|
| - (fo.name, fo.failure) for fo in flake_occurrences]
|
| - self.assertEqual(expected_flakes, actual_flake_occurrences)
|
| -
|
| - # We compare sets below, because order of flakes returned by datastore
|
| - # doesn't have to be same as steps above.
|
| - flakes = Flake.query().fetch()
|
| - self.assertEqual(len(flakes), len(expected_flakes))
|
| - expected_flake_names = set([ef[1] for ef in expected_flakes])
|
| - actual_flake_names = set([f.name for f in flakes])
|
| - self.assertEqual(expected_flake_names, actual_flake_names)
|
| -
|
| - for flake in flakes:
|
| - self.assertEqual(flake.occurrences, [fr_key])
|
| - self.assertEqual(flake.last_time_seen, now)
|
| - self.assertEqual(flake.count_hour, 1)
|
| - self.assertEqual(flake.count_day, 1)
|
| - self.assertEqual(flake.count_week, 1)
|
| - self.assertEqual(flake.count_month, 1)
|
| - self.assertEqual(flake.last_hour, True)
|
| - self.assertEqual(flake.last_day, True)
|
| - self.assertEqual(flake.last_week, True)
|
| - self.assertEqual(flake.last_month, True)
|
| -
|
| def _mock_response(self, content):
|
| m = mock.Mock()
|
| if isinstance(content, basestring):
|
| @@ -631,36 +502,40 @@ class CQStatusTestCase(testing.AppengineTestCase):
|
| with mock.patch('google.appengine.api.urlfetch.fetch', urlfetch_mock):
|
| cq_status.fetch_cq_status()
|
|
|
| - flaky_runs = FlakyRun.query().fetch(100)
|
| - self.assertEqual(len(flaky_runs), 3)
|
| + tasks = self.taskqueue_stub.get_filtered_tasks(queue_names='issue-updates')
|
| + self.assertEqual(len(tasks), 3)
|
|
|
| - # We only compare select few properties of the created FlakyRun entities.
|
| - flaky_run_tuples = set()
|
| - for flaky_run in flaky_runs:
|
| - failure_run = flaky_run.failure_run.get()
|
| - success_run = flaky_run.success_run.get()
|
| + # We only compare select few properties of the created BuildRun entities.
|
| + build_run_tuples = set()
|
| + for task in tasks:
|
| + params = task.extract_params()
|
| + failure_run = ndb.Key(urlsafe=params['failure_run_key']).get()
|
| + success_run = ndb.Key(urlsafe=params['success_run_key']).get()
|
| self.assertEqual(failure_run.key.parent(), success_run.key.parent())
|
| pbr = failure_run.key.parent().get()
|
| - flaky_run_tuple = (pbr.master, pbr.builder, pbr.issue, pbr.patchset,
|
| + build_run_tuple = (pbr.master, pbr.builder, pbr.issue, pbr.patchset,
|
| failure_run.buildnumber, success_run.buildnumber)
|
| - flaky_run_tuples.add(flaky_run_tuple)
|
| + build_run_tuples.add(build_run_tuple)
|
|
|
| - expected_flaky_runs = set([
|
| + expected_build_runs = set([
|
| ('tryserver.test', 'test-builder', 987654321, 20001, 105, 110),
|
| ('tryserver.test', 'test-builder', 123456789, 20001, 109, 101),
|
| ('tryserver.test', 'test-builder', 123456789, 20001, 106, 101),
|
| ])
|
| - self.assertEqual(flaky_run_tuples, expected_flaky_runs)
|
| + self.assertEqual(build_run_tuples, expected_build_runs)
|
|
|
| - def test_cq_status_fetch_creates_deferred_tasks_correctly(self):
|
| + def test_cq_status_fetch_creates_tasks_correctly(self):
|
| urlfetch_mock = mock.Mock()
|
| urlfetch_mock.return_value.content = TEST_CQ_STATUS_RESPONSE
|
|
|
| with mock.patch('google.appengine.api.urlfetch.fetch', urlfetch_mock):
|
| cq_status.fetch_cq_status()
|
|
|
| - tasks = self.taskqueue_stub.get_filtered_tasks()
|
| + tasks = self.taskqueue_stub.get_filtered_tasks(queue_names='issue-updates')
|
| self.assertEqual(len(tasks), 3)
|
| + self.assertEqual(tasks[0].url, '/issues/create_flaky_run')
|
| + self.assertEqual(tasks[1].url, '/issues/create_flaky_run')
|
| + self.assertEqual(tasks[2].url, '/issues/create_flaky_run')
|
|
|
| def test_cq_status_processes_timestamp_in_raw_json(self):
|
| urlfetch_mock = mock.Mock()
|
|
|