# Copyright 2014 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. import hashlib import struct from recipe_engine import recipe_test_api class BotUpdateTestApi(recipe_test_api.RecipeTestApi): def output_json(self, root, first_sln, revision_mapping, fail_patch=False, fixed_revisions=None, commit_positions=True): """Deterministically synthesize json.output test data for gclient's --output-json option. """ output = { 'did_run': True, 'patch_failure': False } revisions = { project_name: self.gen_revision(project_name) for project_name in set(revision_mapping.values()) } if fixed_revisions: for project_name, revision in fixed_revisions.items(): if revision == 'HEAD': revision = self.gen_revision(project_name) elif revision.startswith('refs/') or revision.startswith('origin/'): revision = self.gen_revision('{}@{}'.format(project_name, revision)) revisions[project_name] = revision properties = { property_name: revisions[project_name] for property_name, project_name in revision_mapping.items() } if commit_positions: properties.update({ '%s_cp' % property_name: ('refs/heads/master@{#%s}' % self.gen_commit_position(project_name)) for property_name, project_name in revision_mapping.items() }) output.update({ 'patch_root': root or first_sln, 'root': first_sln, 'properties': properties, 'step_text': 'Some step text' }) output.update({ 'manifest': { project_name: { 'repository': 'https://fake.org/%s.git' % project_name, 'revision': revision, } for project_name, revision in revisions.items() } }) output.update({ 'source_manifest': { 'version': 0, 'directories': { project_name: { 'git_checkout': { 'repo_url': 'https://fake.org/%s.git' % project_name, 'revision': revision } } for project_name, revision in revisions.items() } } }) if fixed_revisions: output['fixed_revisions'] = fixed_revisions if fail_patch: output['patch_failure'] = True output['failed_patch_body'] = '\n'.join([ 'Downloading patch...', 'Applying the patch...', 'Patch: foo/bar.py', 'Index: foo/bar.py', 'diff --git a/foo/bar.py b/foo/bar.py', 'index HASH..HASH MODE', '--- a/foo/bar.py', '+++ b/foo/bar.py', 'context', '+something', '-something', 'more context', ]) output['patch_apply_return_code'] = 1 if fail_patch == 'download': output['patch_apply_return_code'] = 3 return self.m.json.output(output) @staticmethod def gen_revision(project): """Hash project to bogus deterministic git hash values.""" h = hashlib.sha1(project) return h.hexdigest() @staticmethod def gen_commit_position(project): """Hash project to bogus deterministic Cr-Commit-Position values.""" h = hashlib.sha1(project) return struct.unpack('!I', h.digest()[:4])[0] % 300000