1#!/usr/bin/env python3 2# Copyright 2022 The Pigweed Authors 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); you may not 5# use this file except in compliance with the License. You may obtain a copy of 6# the License at 7# 8# https://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13# License for the specific language governing permissions and limitations under 14# the License. 15"""Tests for gitmodules.""" 16 17from pathlib import Path 18import tempfile 19from typing import Optional 20import unittest 21from unittest.mock import MagicMock 22 23from pw_presubmit import gitmodules, PresubmitFailure 24 25 26def dotgitmodules( 27 name: str = 'foo', 28 url: Optional[str] = None, 29 host: Optional[str] = None, 30 branch: Optional[str] = 'main', 31): 32 cfg = f'[submodule "{name}"]\n' 33 cfg += f'path = {name}\n' 34 if url is None and host is None: 35 host = 'host' 36 if host: 37 cfg += f'url = https://{host}.googlesource.com/{name}\n' 38 else: 39 assert url 40 cfg += f'url = {url}\n' 41 if branch: 42 cfg += f'branch = {branch}\n' 43 return cfg 44 45 46class TestGitmodules(unittest.TestCase): 47 """Test gitmodules check.""" 48 49 def setUp(self): 50 self.ctx: MagicMock = None 51 52 def _run(self, config: gitmodules.Config, contents: str) -> None: 53 self.ctx = MagicMock() 54 self.ctx.fail = MagicMock() 55 56 with tempfile.TemporaryDirectory() as tempdir: 57 path = Path(tempdir) / '.gitmodules' 58 with path.open('w') as outs: 59 outs.write(contents) 60 61 gitmodules.process_gitmodules(self.ctx, config, path) 62 63 def test_ok_default(self) -> None: 64 self._run(gitmodules.Config(), dotgitmodules(url='../foo')) 65 self.ctx.fail.assert_not_called() 66 67 def test_ok_restrictive(self) -> None: 68 cfg: gitmodules.Config = gitmodules.Config( 69 allow_non_googlesource_hosts=False, 70 allowed_googlesource_hosts=('host',), 71 require_relative_urls=True, 72 allow_sso=False, 73 allow_git_corp_google_com=False, 74 require_branch=True, 75 ) 76 self._run(cfg, dotgitmodules(url='../foo')) 77 self.ctx.fail.assert_not_called() 78 79 def test_validate_ok(self) -> None: 80 def validator(ctx, path, name, props) -> None: 81 _ = name 82 if 'bad' in props['url']: 83 ctx.fail('bad', path) 84 85 cfg: gitmodules.Config = gitmodules.Config(validator=validator) 86 self._run(cfg, dotgitmodules(host='host')) 87 self.ctx.fail.assert_not_called() 88 89 def test_validate_fail(self) -> None: 90 def validator(ctx, path, name, props) -> None: 91 _ = name 92 if 'bad' in props['url']: 93 ctx.fail('bad', path) 94 95 cfg: gitmodules.Config = gitmodules.Config(validator=validator) 96 self._run(cfg, dotgitmodules(host='badhost')) 97 self.ctx.fail.assert_called() 98 99 def test_non_google_ok(self) -> None: 100 cfg: gitmodules.Config = gitmodules.Config( 101 allow_non_googlesource_hosts=True 102 ) 103 self._run(cfg, dotgitmodules(url='https://github.com/foo/bar')) 104 self.ctx.fail.assert_not_called() 105 106 def test_non_google_fail(self) -> None: 107 cfg: gitmodules.Config = gitmodules.Config( 108 allow_non_googlesource_hosts=False 109 ) 110 self._run(cfg, dotgitmodules(url='https://github.com/foo/bar')) 111 self.ctx.fail.assert_called() 112 113 def test_bad_allowed_googlesource_hosts(self) -> None: 114 with self.assertRaises(PresubmitFailure): 115 cfg: gitmodules.Config = gitmodules.Config( 116 allowed_googlesource_hosts=('pigweed-review',) 117 ) 118 self._run(cfg, dotgitmodules()) 119 120 def test_bad_type_allowed_googlesource_hosts(self) -> None: 121 with self.assertRaises(AssertionError): 122 cfg: gitmodules.Config = gitmodules.Config( 123 allowed_googlesource_hosts=('pigweed') 124 ) 125 self._run(cfg, dotgitmodules()) 126 127 def test_allowed_googlesource_hosts_ok(self) -> None: 128 cfg: gitmodules.Config = gitmodules.Config( 129 allowed_googlesource_hosts=( 130 'pigweed', 131 'pigweed-internal', 132 ) 133 ) 134 self._run(cfg, dotgitmodules(host='pigweed-internal')) 135 self.ctx.fail.assert_not_called() 136 137 def test_allowed_googlesource_hosts_fail(self) -> None: 138 cfg: gitmodules.Config = gitmodules.Config( 139 allowed_googlesource_hosts=('pigweed-internal',) 140 ) 141 self._run(cfg, dotgitmodules(host='pigweed')) 142 self.ctx.fail.assert_called() 143 144 def test_require_relative_urls_ok(self) -> None: 145 cfg: gitmodules.Config = gitmodules.Config(require_relative_urls=False) 146 self._run(cfg, dotgitmodules(host='foo')) 147 self.ctx.fail.assert_not_called() 148 149 def test_require_relative_urls_fail(self) -> None: 150 cfg: gitmodules.Config = gitmodules.Config(require_relative_urls=True) 151 self._run(cfg, dotgitmodules(host='foo')) 152 self.ctx.fail.assert_called() 153 154 def test_allow_sso_ok(self) -> None: 155 cfg: gitmodules.Config = gitmodules.Config(allow_sso=True) 156 self._run(cfg, dotgitmodules(url='sso://host/foo')) 157 self.ctx.fail.assert_not_called() 158 159 def test_allow_sso_fail(self) -> None: 160 cfg: gitmodules.Config = gitmodules.Config(allow_sso=False) 161 self._run(cfg, dotgitmodules(url='sso://host/foo')) 162 self.ctx.fail.assert_called() 163 164 def test_allow_git_corp_google_com_ok(self) -> None: 165 cfg: gitmodules.Config = gitmodules.Config( 166 allow_git_corp_google_com=True 167 ) 168 self._run(cfg, dotgitmodules(url='https://foo.git.corp.google.com/bar')) 169 self.ctx.fail.assert_not_called() 170 171 def test_allow_git_corp_google_com_fail(self) -> None: 172 cfg: gitmodules.Config = gitmodules.Config( 173 allow_git_corp_google_com=False 174 ) 175 self._run(cfg, dotgitmodules(url='https://foo.git.corp.google.com/bar')) 176 self.ctx.fail.assert_called() 177 178 def test_require_branch_ok(self) -> None: 179 cfg: gitmodules.Config = gitmodules.Config(require_branch=False) 180 self._run(cfg, dotgitmodules(branch=None)) 181 self.ctx.fail.assert_not_called() 182 183 def test_require_branch_fail(self) -> None: 184 cfg: gitmodules.Config = gitmodules.Config(require_branch=True) 185 self._run(cfg, dotgitmodules(branch=None)) 186 self.ctx.fail.assert_called() 187 188 189if __name__ == '__main__': 190 unittest.main() 191