Index: commit-queue/tests/project_test.py |
=================================================================== |
--- commit-queue/tests/project_test.py (revision 249146) |
+++ commit-queue/tests/project_test.py (working copy) |
@@ -1,508 +0,0 @@ |
-#!/usr/bin/env python |
-# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-"""Integration tests for project.py.""" |
- |
-import logging |
-import os |
-import random |
-import shutil |
-import string |
-import StringIO |
-import sys |
-import tempfile |
-import time |
-import unittest |
-import urllib2 |
- |
-ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) |
-sys.path.insert(0, os.path.join(ROOT_DIR, '..')) |
- |
-import projects |
-from verification import base |
-from verification import presubmit_check |
-from verification import try_job_on_rietveld |
- |
-# From /tests |
-import mocks |
- |
- |
-def _try_comment(pc, issue=31337): |
- return ( |
- "add_comment(%d, u'%shttp://localhost/user@example.com/%d/1\\n')" % |
- (issue, pc.TRYING_PATCH.replace('\n', '\\n'), |
- issue)) |
- |
- |
-class TestCase(mocks.TestCase): |
- def setUp(self): |
- super(TestCase, self).setUp() |
- self.mock(projects, '_read_lines', self._read_lines) |
- self.mock( |
- projects.async_push, |
- 'AsyncPush', lambda _1, _2: mocks.AsyncPushMock(self)) |
- class Dummy(object): |
- @staticmethod |
- def get_list(): |
- return [] |
- if not projects.chromium_committers: |
- projects.chromium_committers = Dummy() |
- self.mock( |
- projects.chromium_committers, 'get_list', self._get_committers_list) |
- if not projects.nacl_committers: |
- projects.nacl_committers = Dummy() |
- self.mock(projects.nacl_committers, 'get_list', self._get_committers_list) |
- self.mock(presubmit_check.subprocess2, 'check_output', self._check_output) |
- self.mock(urllib2, 'urlopen', self._urlopen) |
- self.mock(time, 'time', self._time) |
- self.check_output = [] |
- self.read_lines = [] |
- self.urlrequests = [] |
- self.time = [] |
- |
- def tearDown(self): |
- try: |
- if not self.has_failed(): |
- self.assertEqual([], self.check_output) |
- self.assertEqual([], self.read_lines) |
- self.assertEqual([], self.urlrequests) |
- self.assertEqual([], self.time) |
- finally: |
- super(TestCase, self).tearDown() |
- |
- # Mocks |
- def _urlopen(self, url): |
- if not self.urlrequests: |
- self.fail(url) |
- expected_url, data = self.urlrequests.pop(0) |
- self.assertEqual(expected_url, url) |
- return StringIO.StringIO(data) |
- |
- @staticmethod |
- def _get_committers_list(): |
- return ['user@example.com', 'user@example.org'] |
- |
- def _read_lines(self, root, error): |
- if not self.read_lines: |
- self.fail(root) |
- a = self.read_lines.pop(0) |
- self.assertEqual(a[0], root) |
- self.assertEqual(a[1], error) |
- return a[2] |
- |
- def _check_output(self, *args, **kwargs): |
- # For now, ignore the arguments. Change if necessary. |
- if not self.check_output: |
- self.fail((args, kwargs)) |
- return self.check_output.pop(0) |
- |
- def _time(self): |
- self.assertTrue(self.time) |
- return self.time.pop(0) |
- |
- |
-class ProjectTest(TestCase): |
- def setUp(self): |
- super(ProjectTest, self).setUp() |
- |
- def test_loaded(self): |
- members = ( |
- 'blink', 'chromium', 'chromium_deps', 'gyp', 'nacl', 'skia', 'tools') |
- self.assertEqual(sorted(members), sorted(projects.supported_projects())) |
- |
- def test_all(self): |
- # Make sure it's possible to load each project. |
- self.time = [1] * 2 |
- root_dir = os.path.join(os.getcwd(), 'root_dir') |
- chromium_status_pwd = os.path.join(root_dir, '.chromium_status_pwd') |
- skia_status_pwd = os.path.join(root_dir, '.skia_status_pwd') |
- mapping = { |
- 'blink': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['try job rietveld', 'tree status'], |
- }, |
- 'chromium': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['try job rietveld', 'tree status'], |
- }, |
- 'chromium_deps': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['presubmit'], |
- }, |
- 'gyp': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['tree status'], |
- }, |
- 'nacl': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['presubmit', 'tree status'], |
- }, |
- 'skia': { |
- 'lines': [ |
- skia_status_pwd, 'skia-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['presubmit', 'tree status'], |
- }, |
- 'tools': { |
- 'lines': [ |
- chromium_status_pwd, 'chromium-status password', ['foo'], |
- ], |
- 'pre_patch_verifiers': ['project_bases', 'reviewer_lgtm'], |
- 'verifiers': ['presubmit'], |
- }, |
- } |
- for project in sorted(projects.supported_projects()): |
- logging.debug(project) |
- self.assertEqual([], self.read_lines) |
- expected = mapping.pop(project) |
- self.read_lines = [expected['lines']] |
- p = projects.load_project( |
- project, 'user', root_dir, self.context.rietveld, True) |
- self.assertEqual( |
- expected['pre_patch_verifiers'], |
- [x.name for x in p.pre_patch_verifiers], |
- (expected['pre_patch_verifiers'], |
- [x.name for x in p.pre_patch_verifiers], |
- project)) |
- self.assertEqual( |
- expected['verifiers'], [x.name for x in p.verifiers], |
- (expected['verifiers'], |
- [x.name for x in p.verifiers], |
- project)) |
- if project == 'tools': |
- # Add special checks for it. |
- project_bases_verifier = p.pre_patch_verifiers[0] |
- branch = '\\@[a-zA-Z0-9\\-_\\.]+$' |
- self.assertEqual( |
- [ |
- # svn |
- '^svn\\:\\/\\/svn\\.chromium\\.org\\/chrome/trunk/tools(|/.*)$', |
- '^svn\\:\\/\\/chrome\\-svn\\/chrome/trunk/tools(|/.*)$', |
- '^svn\\:\\/\\/chrome\\-svn\\.corp\\/chrome/trunk/tools(|/.*)$', |
- '^svn\\:\\/\\/chrome\\-svn\\.corp\\.google\\.com\\/chrome/trunk/' |
- 'tools(|/.*)$', |
- '^http\\:\\/\\/src\\.chromium\\.org\\/svn/trunk/tools(|/.*)$', |
- '^https\\:\\/\\/src\\.chromium\\.org\\/svn/trunk/tools(|/.*)$', |
- '^http\\:\\/\\/src\\.chromium\\.org\\/chrome/trunk/tools(|/.*)$', |
- '^https\\:\\/\\/src\\.chromium\\.org\\/chrome/trunk/tools(|/.*)$', |
- |
- # git |
- '^https?\\:\\/\\/git\\.chromium\\.org\\/git\\/chromium\\/tools\\/' |
- '([a-z0-9\\-_]+)(?:\\.git)?' + branch, |
- '^https?\\:\\/\\/git\\.chromium\\.org\\/chromium\\/tools\\/' |
- '([a-z0-9\\-_]+)(?:\\.git)?' + branch, |
- '^https?\\:\\/\\/chromium\\.googlesource\\.com\\/chromium\\/tools' |
- '\\/([a-z0-9\\-_]+)(?:\\.git)?' + branch, |
- '^https?\\:\\/\\/chromium\\.googlesource\\.com\\/a\\/chromium\\/' |
- 'tools\\/([a-z0-9\\-_]+)(?:\\.git)?' + branch, |
- ], |
- project_bases_verifier.project_bases) |
- self.assertEqual({}, mapping) |
- |
- |
-class ChromiumStateLoad(TestCase): |
- # Load a complete state and ensure the code is reacting properly. |
- def setUp(self): |
- super(ChromiumStateLoad, self).setUp() |
- self.buildbot = mocks.BuildbotMock(self) |
- self.mock( |
- try_job_on_rietveld.buildbot_json, 'Buildbot', lambda _: self.buildbot) |
- self.tempdir = tempfile.mkdtemp(prefix='project_test') |
- self.now = None |
- |
- def tearDown(self): |
- try: |
- shutil.rmtree(self.tempdir) |
- finally: |
- super(ChromiumStateLoad, self).tearDown() |
- |
- def _add_build(self, builder, buildnumber, revision, steps, completed): |
- """Adds a build with a randomly generated key.""" |
- key = ''.join(random.choice(string.ascii_letters) for _ in xrange(8)) |
- build = self.buildbot.add_build( |
- builder, buildnumber, revision, key, completed, None) |
- build.steps.extend(steps) |
- return key |
- |
- def _LoadPendingManagerState(self, issue): |
- self.urlrequests = [ |
- ( 'http://chromium-status.appspot.com/allstatus?format=json&endTime=%d' % |
- (self.now - 300), |
- # In theory we should return something but nothing works fine. |
- '[]'), |
- ] |
- self.read_lines = [ |
- [ |
- os.path.join(self.tempdir, '.chromium_status_pwd'), |
- 'chromium-status password', |
- ['foo'], |
- ], |
- ] |
- self.context.rietveld.patchsets_properties[(issue, 1)] = {} |
- |
- self.time = [self.now] * 1 |
- pc = projects.load_project( |
- 'chromium', 'invalid', self.tempdir, self.context.rietveld, False) |
- self.assertEqual(0, len(self.time)) |
- pc.context = self.context |
- pc.load(os.path.join(ROOT_DIR, 'chromium.%d.json' % issue)) |
- |
- # Verify the content a bit. |
- self.assertEqual(1, len(pc.queue.iterate())) |
- self.assertEqual(issue, pc.queue.get(issue).issue) |
- expected = [ |
- u'presubmit', |
- u'project_bases', |
- u'reviewer_lgtm', |
- u'tree status', |
- u'try job rietveld', |
- ] |
- self.assertEqual(expected, sorted(pc.queue.get(issue).verifications)) |
- |
- return pc |
- |
- def _verify_final_state(self, verifications, why_not, rietveld_calls): |
- for name, obj in verifications.iteritems(): |
- if name == 'try job rietveld': |
- self.assertEqual(base.PROCESSING, obj.get_state(), name) |
- self.assertEqual(why_not, obj.why_not()) |
- else: |
- self.assertEqual(base.SUCCEEDED, obj.get_state(), name) |
- self.assertEqual(None, obj.why_not()) |
- |
- if name == 'tree status': |
- self.time = [self.now] * 1 |
- self.assertEqual(False, obj.postpone(), name) |
- self.assertEqual(0, len(self.time)) |
- else: |
- self.assertEqual(False, obj.postpone(), name) |
- self.context.rietveld.check_calls(rietveld_calls) |
- |
- def testLoadState(self): |
- self.now = 1354207000. |
- issue = 31337 |
- pending_manager = self._LoadPendingManagerState(issue) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 3 |
- pending_manager.update_status() |
- self.assertEqual(0, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = (u'Waiting for the following jobs:\n' |
- ' win_rel: sync_integration_tests\n') |
- rietveld_calls = [ |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'win_rel': " |
- "[u'sync_integration_tests']})" % issue |
- ] |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def testLoadState11299256(self): |
- # Loads a saved state and try to revive it. |
- self.now = 1354551606. |
- issue = 11299256 |
- pending_manager = self._LoadPendingManagerState(issue) |
- self._add_build('ios_rel_device', 1, 2, [], 4) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 3 |
- pending_manager.update_status() |
- self.assertEqual(1, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = (u'Waiting for the following jobs:\n' |
- ' ios_rel_device: compile\n') |
- rietveld_calls = [] |
- # ios_rel_device seems lost. CQ should not reissue it now to avoid |
- # overloading the tryserver. |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def testLoadState12208028(self): |
- # Loads a saved state and try to revive it. |
- self.now = 1360256000. |
- issue = 12208028 |
- pending_manager = self._LoadPendingManagerState(issue) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 3 |
- pending_manager.update_status() |
- self.assertEqual(0, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = (u'Waiting for the following jobs:\n' |
- ' android_dbg_triggered_tests: build\n') |
- rietveld_calls = [ |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'android_dbg': " |
- "[u'build']})" % issue |
- ] |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def testLoadState12253015(self): |
- # Loads a saved state and try to revive it. |
- self.now = 1360256000. |
- issue = 12253015 |
- pending_manager = self._LoadPendingManagerState(issue) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 3 |
- pending_manager.update_status() |
- self.assertEqual(0, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = ( |
- u'Waiting for the following jobs:\n' |
- ' win7_aura: browser_tests\n' |
- ' win_rel: chrome_frame_tests,chrome_frame_net_tests,browser_tests,' |
- 'nacl_integration,sync_integration_tests,installer_util_unittests,' |
- 'content_browsertests,chrome_frame_unittests,mini_installer_test\n') |
- rietveld_calls = [ |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'win7_aura': " |
- "[u'browser_tests']})" % issue, |
- ] |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def testLoadState12633013(self): |
- # Loads a saved state and try to revive it. |
- self.now = 1363610000. |
- issue = 12633013 |
- pending_manager = self._LoadPendingManagerState(issue) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 3 |
- pending_manager.update_status() |
- self.assertEqual(0, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = ( |
- u'Waiting for the following jobs:\n' |
- ' android_dbg_triggered_tests: slave_steps\n') |
- rietveld_calls = [ |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'android_dbg': " |
- "[u'slave_steps']})" % issue, |
- ] |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def testLoadStateSwarm(self): |
- # Loads a saved state and try to revive it. |
- self.now = 1360256000. |
- issue = 666 |
- pending_manager = self._LoadPendingManagerState(issue) |
- |
- # Then fix the crap out of it. |
- self.time = [self.now] * 5 |
- pending_manager.update_status() |
- self.assertEqual(0, len(self.time)) |
- self.assertEqual(1, len(pending_manager.queue.iterate())) |
- |
- why_not = (u'Waiting for the following jobs:\n' |
- ' linux_rel: browser_tests\n' |
- ' mac_rel: browser_tests\n' |
- ' win_rel: browser_tests\n') |
- # TODO(csharp): These triggered events should be the swarm versions, |
- # change them once swarm tests are enabled by default. |
- rietveld_calls = [ |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'linux_rel': " |
- "[u'browser_tests']})" % issue, |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'mac_rel': " |
- "[u'browser_tests']})" % issue, |
- "trigger_try_jobs(%d, 1, 'CQ', False, 'HEAD', {u'win_rel': " |
- "[u'browser_tests']})" % issue, |
- ] |
- self._verify_final_state(pending_manager.queue.get(issue).verifications, |
- why_not, rietveld_calls) |
- |
- def test_tbr(self): |
- self.time = map(lambda x: float(x*35), range(15)) |
- self.urlrequests = [ |
- ('https://chromium-status.appspot.com/allstatus?format=json&endTime=85', |
- # Cheap hack here. |
- '[]'), |
- ] |
- root_dir = os.path.join(os.getcwd(), 'root_dir') |
- self.read_lines = [ |
- [ |
- os.path.join(root_dir, '.chromium_status_pwd'), |
- 'chromium-status password', |
- ['foo'], |
- ], |
- ] |
- pc = projects.load_project( |
- 'chromium', 'commit-bot-test', root_dir, self.context.rietveld, True) |
- pc.context = self.context |
- issue = self.context.rietveld.issues[31337] |
- self.context.rietveld.patchsets_properties[(31337, 1)] = {} |
- |
- # A TBR= patch without reviewer nor messages, like a webkit roll. |
- issue['description'] += '\nTBR=' |
- issue['reviewers'] = [] |
- issue['messages'] = [] |
- issue['owner_email'] = u'user@example.com' |
- issue['base_url'] = u'svn://svn.chromium.org/chrome/trunk/src' |
- pc.look_for_new_pending_commit() |
- pc.process_new_pending_commit() |
- pc.update_status() |
- pc.scan_results() |
- self.assertEqual(1, len(pc.queue.iterate())) |
- key = self._add_build('chromium_presubmit', 123456, 124, |
- [mocks.BuildbotBuildStep('presubmit', False)], True) |
- self.context.rietveld.patchsets_properties[(31337, 1)] = { |
- 'try_job_results': [{ |
- 'builder': "chromium_presubmit", |
- 'key': key, |
- 'buildnumber': "123456", |
- }]} |
- build = self.buildbot.builders['chromium_presubmit'].builds[123456] |
- build.steps[0].simplified_result = True |
- pc.update_status() |
- pc.scan_results() |
- self.assertEqual(0, len(pc.queue.iterate())) |
- # check_calls |
- self.context.rietveld.check_calls([ |
- _try_comment(pc), |
- "trigger_try_jobs(31337, 1, 'CQ', False, 'HEAD', " |
- "{u'chromium_presubmit': ['presubmit']})", |
- 'close_issue(31337)', |
- "update_description(31337, u'foo\\nTBR=')", |
- "add_comment(31337, 'Change committed as 125')", |
- ]) |
- self.context.checkout.check_calls([ |
- 'prepare(None)', |
- 'apply_patch(%r)' % self.context.rietveld.patchsets[0], |
- 'prepare(None)', |
- 'apply_patch(%r)' % self.context.rietveld.patchsets[1], |
- "commit(u'foo\\nTBR=\\n\\nReview URL: http://nowhere/31337', " |
- "u'user@example.com')", |
- ]) |
- self.context.status.check_names(['initial', 'why not', 'why not', |
- 'why not', 'commit']) |
- |
- |
- |
-if __name__ == '__main__': |
- logging.basicConfig( |
- level=logging.DEBUG if '-v' in sys.argv else logging.WARNING, |
- format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s') |
- unittest.main() |