| # 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. |
| |
| """Common mocks.""" |
| |
| import copy |
| import os |
| import sys |
| |
| ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| sys.path.insert(0, os.path.join(ROOT_DIR, '..')) |
| |
| import find_depot_tools # pylint: disable=W0611 |
| import breakpad |
| import patch |
| |
| import async_push |
| import context |
| import pending_manager |
| |
| from testing_support import auto_stub |
| |
| |
| SVN_PATCH = ( |
| 'Index: chrome/file.cc\n' |
| '===================================================================\n' |
| '--- chrome/file.cc\t(revision 74690)\n' |
| '+++ chrome/file.cc\t(working copy)\n' |
| '@@ -80,10 +80,10 @@\n' |
| ' // Foo\n' |
| ' // Bar\n' |
| ' void foo() {\n' |
| '- return bar;\n' |
| '+ return foo;\n' |
| ' }\n' |
| ' \n' |
| ' \n') |
| |
| |
| class RietveldMock(auto_stub.SimpleMock): |
| url = 'http://nowhere' |
| email = 'fake_email' |
| password = 'fake_password' |
| |
| def __init__(self, unit_test): |
| super(RietveldMock, self).__init__(unit_test) |
| self.issues = { |
| 31337: { |
| "description": u"foo", |
| "created": "2010-12-27 03:23:31.149045", |
| "cc": ["cc@example.com",], |
| "reviewers": ["rev@example.com"], |
| "owner_email": "author@example.com", |
| "patchsets": [1], |
| "modified": "2011-01-10 20:52:39.127231", |
| "private": False, |
| "base_url": "svn://fake/repo", |
| "closed": False, |
| "owner": "Author", |
| "issue": 31337, |
| "subject": 'foo', |
| "messages": [ |
| { |
| "date": "2010-12-27 03:23:32.489999", |
| "text": u"hi!", |
| "sender": "author@example.com", |
| "recipients": ["rev@example.com", "cc@example.com"], |
| "approval": False, |
| }, |
| { |
| "date": "2010-12-27 03:23:32.489999", |
| "text": u"hi!", |
| "sender": "rev@example.com", |
| "recipients": ["rev@example.com", "cc@example.com"], |
| "approval": True, |
| }, |
| ], |
| "commit": True, |
| }, |
| } |
| self.patchsets = [] |
| # Key is (issue, patchset) |
| self.patchsets_properties = {} |
| |
| def get_pending_issues(self): |
| return self.issues.keys() |
| |
| def get_issue_properties(self, issue_id, _): |
| return copy.deepcopy(self.issues[issue_id]) |
| |
| def get_patchset_properties(self, issue_id, patchset): |
| key = (issue_id, patchset) |
| self.unit_test.assertTrue( |
| key in self.patchsets_properties, (key, self.patchsets_properties)) |
| return copy.deepcopy(self.patchsets_properties[key]) |
| |
| def close_issue(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| def update_description(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| def set_flag(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| return True |
| |
| def add_comment(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| def get_patch(self, _issue, _patchset): |
| self.patchsets.append(patch.PatchSet([ |
| patch.FilePatchDiff('chrome/file.cc', SVN_PATCH, []), |
| patch.FilePatchDelete('other/place/foo', True), |
| patch.FilePatchBinary('foo', 'data', [], True), |
| ])) |
| return self.patchsets[-1] |
| |
| def _send(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| def trigger_try_jobs(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| @staticmethod |
| def xsrf_token(): |
| return 'XSRF-free' |
| |
| def post(self, *args, **kwargs): |
| self._register_call(*args, **kwargs) |
| |
| |
| class SvnCheckoutMock(auto_stub.SimpleMock): |
| def __init__(self, *args): |
| super(SvnCheckoutMock, self).__init__(*args) |
| self.project_path = os.getcwd() |
| self.project_name = os.path.basename(self.project_path) |
| self.post_processors = [] |
| |
| def prepare(self, revision): |
| self._register_call(revision) |
| # prepare() should always return a valid revision. |
| return revision or 124 |
| |
| def apply_patch(self, *args): |
| self._register_call(*args) |
| |
| def commit(self, *args): |
| self._register_call(*args) |
| return 125 |
| |
| @staticmethod |
| def get_settings(_key): |
| return None |
| |
| @staticmethod |
| def revisions(_revision1, _revision2): |
| """Number of revisions between 2 revisions.""" |
| return 3 |
| |
| |
| class AsyncPushMock(auto_stub.SimpleMock, async_push.AsyncPushNoop): |
| def __init__(self, *args): |
| auto_stub.SimpleMock.__init__(self, *args) |
| async_push.AsyncPushNoop.__init__(self) |
| self.queue = [] |
| |
| def send(self, packet, pending): |
| self.queue.append(self._package(packet, pending)) |
| |
| def pop_packets(self): |
| packets = self.queue |
| self.queue = [] |
| return packets |
| |
| def check_packets(self, expected): |
| self.assertEqual(expected, self.pop_packets()) |
| |
| def check_names(self, expected): |
| self.assertEqual(expected, [i['verification'] for i in self.pop_packets()]) |
| |
| |
| class BuildbotBuilder(object): |
| def __init__(self): |
| self.builds = {} |
| class Data(object): |
| def __init__(self): |
| self.data = {} |
| self.pending_builds = Data() |
| |
| |
| class BuildbotBuild(object): |
| def __init__(self, revision, key, completed, parent_key): |
| self.properties_as_dict = { |
| 'try_job_key': key, |
| 'parent_try_job_key': parent_key, |
| } |
| self.revision = revision |
| self.start_time = 1 |
| self.steps = [] |
| self.completed = completed |
| self.duration = 180 |
| |
| |
| class BuildbotBuildStep(object): |
| def __init__(self, name, result): |
| self.name = name |
| self.simplified_result = result |
| |
| |
| class BuildbotBuilders(object): |
| def __init__(self, initial): |
| self.values = initial.copy() |
| |
| def __getitem__(self, key): |
| return self.values[key] |
| |
| @property |
| def keys(self): |
| return self.values.keys() |
| |
| def setdefault(self, key, value): |
| return self.values.setdefault(key, value) |
| |
| |
| class BuildbotMock(auto_stub.SimpleMock): |
| """Stateful try server mock.""" |
| |
| def __init__(self, unit_test): |
| super(BuildbotMock, self).__init__(unit_test) |
| self.builders = BuildbotBuilders({ |
| u'mac': BuildbotBuilder(), |
| u'linux': BuildbotBuilder(), |
| }) |
| |
| def discard(self): |
| pass |
| |
| def add_build(self, builder, number, revision, key, completed, parent_key): |
| """Add a build to a builder.""" |
| builder = self.builders.setdefault(builder, BuildbotBuilder()) |
| builder.builds[number] = BuildbotBuild(revision, key, completed, parent_key) |
| return builder.builds[number] |
| |
| |
| class TestCase(auto_stub.TestCase): |
| def setUp(self): |
| super(TestCase, self).setUp() |
| self.mock(breakpad, 'SendStack', self._send_stack_mock) |
| self.context = context.Context( |
| RietveldMock(self), SvnCheckoutMock(self), AsyncPushMock(self), False) |
| self.pending = pending_manager.PendingCommit( |
| issue=42, |
| owner='owner@example.com', |
| reviewers=[], |
| patchset=23, |
| base_url='', |
| description=u'bleh', |
| messages=[]) |
| |
| def tearDown(self): |
| try: |
| if not self.has_failed(): |
| self.context.rietveld.check_calls([]) |
| self.context.checkout.check_calls([]) |
| self.context.status.check_packets([]) |
| finally: |
| super(TestCase, self).tearDown() |
| |
| def _send_stack_mock(self, last_tb, stack, *_args, **_kwargs): |
| """Fails a test that calls SendStack. |
| |
| In practice it doesn't happen when a test pass but will when a test fails so |
| hook it here so breakpad doesn't send too many stack traces to maintainers. |
| """ |
| self.fail('%s, %s' % (last_tb, stack)) |