| # Copyright 2019 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """Test API for checkout.""" |
| |
| from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2 |
| from PB.recipe_modules.pigweed.checkout import properties as checkout_properties |
| from recipe_engine import post_process, recipe_test_api |
| |
| REPO = 'https://pigweed.googlesource.com/pigweed/pigweed' |
| MANIFEST_REPO = 'https://pigweed.googlesource.com/pigweed/manifest' |
| |
| DEFAULT_MANIFEST = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote |
| name="default_remote" |
| fetch="sso://default" |
| /> |
| |
| <remote |
| name="pigweed_remote" |
| revision="main" |
| fetch=".." |
| review="https://pigweed.googlesource.com" |
| /> |
| |
| <remote |
| name="pigweed-internal_remote" |
| revision="main" |
| fetch="https://pigweed-internal.googlesource.com" |
| review="https://pigweed-internal.googlesource.com" |
| /> |
| |
| <remote |
| name="prefixed" |
| fetch="https://foo.googlesource.com/prefix" |
| review="https://foo.googlesource.com/prefix" |
| /> |
| |
| <default |
| remote="default_remote" |
| revision="main" |
| /> |
| |
| <project |
| name="default_name" |
| path="default_path" |
| /> |
| |
| <project |
| name="pigweed_name" |
| path="pigweed_path" |
| remote="pigweed_remote" |
| revision="main" |
| /> |
| |
| <project |
| name="pigweed-internal_name" |
| path="pigweed-internal_path" |
| remote="pigweed-internal_remote" |
| /> |
| |
| <project |
| name="pinned" |
| path="pinned" |
| remote="pigweed_remote" |
| revision="0123456789012345678901234567890123456789" |
| upstream="main" |
| /> |
| |
| <project |
| name="suffix" |
| path="prefix/suffix" |
| remote="prefixed" |
| /> |
| </manifest> |
| """.strip() |
| |
| |
| class CheckoutTestApi(recipe_test_api.RecipeTestApi): |
| """Test API for checkout.""" |
| |
| @property |
| def manifest_repo(self): |
| return MANIFEST_REPO |
| |
| def git_properties(self, **kwargs): |
| props = checkout_properties.InputProperties() |
| props.remote = kwargs.pop('remote', REPO) |
| props.branch = kwargs.pop('branch', 'main') or 'main' |
| props.use_repo = kwargs.pop('use_repo', False) |
| for remotes in kwargs.pop('equivalent_remotes', ()): |
| remote_group = checkout_properties.EquivalentRemotes() |
| remote_group.remotes.extend(remotes) |
| props.equivalent_remotes.extend([remote_group]) |
| props.force_no_rebase = kwargs.pop('force_no_rebase', False) |
| props.match_branch = kwargs.pop('match_branch', True) |
| assert not kwargs |
| return {'$pigweed/checkout': props} |
| |
| def repo_properties(self, remote=MANIFEST_REPO, use_repo=True, **kwargs): |
| return self.git_properties(remote=remote, use_repo=use_repo, **kwargs) |
| |
| def ci_test_data( |
| self, git_repo=REPO, name='pigweed', branch=None, **kwargs |
| ): |
| if branch: |
| kwargs['git_ref'] = 'refs/heads/{}'.format(branch) |
| ret = self.m.buildbucket.ci_build(git_repo=git_repo, **kwargs) |
| if branch: |
| ret += self.override_step_data( |
| 'checkout {}.change data.process gitiles commit.number'.format( |
| name |
| ), |
| self.m.json.output([{'_number': '1234', 'branch': branch}]), |
| ) |
| return ret |
| |
| def cl(self, host, project, change, patchset=1): |
| return common_pb2.GerritChange( |
| host=host, project=project, change=change, patchset=patchset |
| ) |
| |
| def try_test_data(self, git_repo=REPO, **kwargs): |
| return self.m.buildbucket.try_build(git_repo=git_repo, **kwargs) |
| |
| def manifest_test_data(self, name='pigweed', raw_xml=DEFAULT_MANIFEST): |
| return self.step_data( |
| 'checkout {}.read manifest.read file'.format(name), |
| self.m.file.read_text(raw_xml), |
| ) |
| |
| def cl_branch(self, branch, index=0, name='pigweed'): |
| return self.override_step_data( |
| 'checkout {}.change data.process gerrit changes.{}.details'.format( |
| name, index |
| ), |
| self.m.json.output({'branch': branch}), |
| ) |
| |
| def manifest_has_matching_branch(self, branch, name='pigweed'): |
| # The contents of the returned JSON data don't matter--they just need to |
| # evaluate to True when converted to bool. Gitiles returns an empty |
| # dictionary when the branch does not exist. |
| return self.m.git.get_remote_branch_head( |
| 'checkout {}.manifest has branch.git ls-remote {}'.format( |
| name, branch, |
| ), |
| 'a' * 40, |
| ) |
| |
| def root_files(self, *files, **kwargs): |
| name = kwargs.pop('name', 'pigweed') |
| assert not kwargs |
| files = set(files) |
| files.add('.repo') |
| return self.step_data( |
| 'checkout {}.ls'.format(name), |
| stdout=self.m.raw_io.output_text( |
| ''.join(('{}\n'.format(x) for x in sorted(files))) |
| ), |
| ) |
| |
| def submodules( |
| self, |
| prefix='checkout pigweed.', |
| checkout_root='[START_DIR]/checkout', |
| raw_submodule_status=None, |
| **submodules |
| ): |
| # kwargs = { path: remote } |
| # (e.g., {'foo': 'https://x.googlesource.com/foo'}) |
| output = raw_submodule_status or ''.join( |
| '{} {} ({})\n'.format('a' * 40, path, 'foo') for path in submodules |
| ) |
| res = self.override_step_data( |
| '{}git submodule status'.format(prefix), |
| stdout=self.m.raw_io.output_text(output), |
| ) |
| for path, remote in submodules.items(): |
| res += self.step_data( |
| '{}parse submodules.git origin {}/{}'.format( |
| prefix, checkout_root, path |
| ), |
| stdout=self.m.raw_io.output_text(remote), |
| ) |
| |
| return res |
| |
| def all_changes_applied(self): |
| return self.some_changes_applied() + self.post_process( |
| post_process.DoesNotRunRE, '.*some changes were not applied.*' |
| ) |
| |
| def some_changes_applied(self): |
| return self.post_process( |
| post_process.DoesNotRunRE, '.*no changes were applied.*' |
| ) |
| |
| def no_changes_applied(self): |
| return self.post_process( |
| post_process.MustRunRE, '.*no changes were applied.*' |
| ) |
| |
| def change_applied(self, name): |
| return self.post_process( |
| post_process.DoesNotRunRE, '.*failed to apply {}.*'.format(name) |
| ) + self.post_process( |
| post_process.MustRunRE, r'.*apply {}.git.*'.format(name) |
| ) |
| |
| def change_not_applied(self, name): |
| return self.post_process( |
| post_process.MustRunRE, '.*failed to apply {}.*'.format(name) |
| ) + self.post_process( |
| post_process.DoesNotRunRE, r'.*apply {}.git.*'.format(name) |
| ) |