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() |