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 19import unittest 20from unittest.mock import MagicMock 21 22from pw_presubmit import gitmodules, PresubmitFailure 23 24 25def dotgitmodules( 26 name: str = 'foo', 27 url: str | None = None, 28 host: str | None = None, 29 branch: str | None = 'main', 30): 31 cfg = f'[submodule "{name}"]\n' 32 cfg += f'path = {name}\n' 33 if url is None and host is None: 34 host = 'host' 35 if host: 36 cfg += f'url = https://{host}.googlesource.com/{name}\n' 37 else: 38 assert url 39 cfg += f'url = {url}\n' 40 if branch: 41 cfg += f'branch = {branch}\n' 42 return cfg 43 44 45class TestGitmodules(unittest.TestCase): 46 """Test gitmodules check.""" 47 48 def setUp(self): 49 self.ctx: MagicMock = None 50 51 def _run(self, config: gitmodules.Config, contents: str) -> None: 52 self.ctx = MagicMock() 53 self.ctx.fail = MagicMock() 54 55 with tempfile.TemporaryDirectory() as tempdir: 56 path = Path(tempdir) / '.gitmodules' 57 with path.open('w') as outs: 58 outs.write(contents) 59 60 gitmodules.process_gitmodules(self.ctx, config, path) 61 62 def test_ok_no_submodules(self) -> None: 63 self._run(gitmodules.Config(), '') 64 self.ctx.fail.assert_not_called() 65 66 def test_no_submodules_allowed(self) -> None: 67 self._run( 68 gitmodules.Config(allow_submodules=False), 69 dotgitmodules(url='../foo'), 70 ) 71 self.ctx.fail.assert_called() 72 73 def test_ok_default(self) -> None: 74 self._run(gitmodules.Config(), dotgitmodules(url='../foo')) 75 self.ctx.fail.assert_not_called() 76 77 def test_ok_restrictive(self) -> None: 78 cfg: gitmodules.Config = gitmodules.Config( 79 allow_non_googlesource_hosts=False, 80 allowed_googlesource_hosts=('host',), 81 require_relative_urls=True, 82 allow_sso=False, 83 allow_git_corp_google_com=False, 84 require_branch=True, 85 ) 86 self._run(cfg, dotgitmodules(url='../foo')) 87 self.ctx.fail.assert_not_called() 88 89 def test_validate_ok(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='host')) 97 self.ctx.fail.assert_not_called() 98 99 def test_validate_fail(self) -> None: 100 def validator(ctx, path, name, props) -> None: 101 _ = name 102 if 'bad' in props['url']: 103 ctx.fail('bad', path) 104 105 cfg: gitmodules.Config = gitmodules.Config(validator=validator) 106 self._run(cfg, dotgitmodules(host='badhost')) 107 self.ctx.fail.assert_called() 108 109 def test_non_google_ok(self) -> None: 110 cfg: gitmodules.Config = gitmodules.Config( 111 allow_non_googlesource_hosts=True 112 ) 113 self._run(cfg, dotgitmodules(url='https://github.com/foo/bar')) 114 self.ctx.fail.assert_not_called() 115 116 def test_non_google_fail(self) -> None: 117 cfg: gitmodules.Config = gitmodules.Config( 118 allow_non_googlesource_hosts=False 119 ) 120 self._run(cfg, dotgitmodules(url='https://github.com/foo/bar')) 121 self.ctx.fail.assert_called() 122 123 def test_bad_allowed_googlesource_hosts(self) -> None: 124 with self.assertRaises(PresubmitFailure): 125 cfg: gitmodules.Config = gitmodules.Config( 126 allowed_googlesource_hosts=('pigweed-review',) 127 ) 128 self._run(cfg, dotgitmodules()) 129 130 def test_bad_type_allowed_googlesource_hosts(self) -> None: 131 with self.assertRaises(AssertionError): 132 cfg: gitmodules.Config = gitmodules.Config( 133 allowed_googlesource_hosts=('pigweed') 134 ) 135 self._run(cfg, dotgitmodules()) 136 137 def test_allowed_googlesource_hosts_ok(self) -> None: 138 cfg: gitmodules.Config = gitmodules.Config( 139 allowed_googlesource_hosts=( 140 'pigweed', 141 'pigweed-internal', 142 ) 143 ) 144 self._run(cfg, dotgitmodules(host='pigweed-internal')) 145 self.ctx.fail.assert_not_called() 146 147 def test_allowed_googlesource_hosts_fail(self) -> None: 148 cfg: gitmodules.Config = gitmodules.Config( 149 allowed_googlesource_hosts=('pigweed-internal',) 150 ) 151 self._run(cfg, dotgitmodules(host='pigweed')) 152 self.ctx.fail.assert_called() 153 154 def test_require_relative_urls_ok(self) -> None: 155 cfg: gitmodules.Config = gitmodules.Config(require_relative_urls=False) 156 self._run(cfg, dotgitmodules(host='foo')) 157 self.ctx.fail.assert_not_called() 158 159 def test_require_relative_urls_fail(self) -> None: 160 cfg: gitmodules.Config = gitmodules.Config(require_relative_urls=True) 161 self._run(cfg, dotgitmodules(host='foo')) 162 self.ctx.fail.assert_called() 163 164 def test_allow_sso_ok(self) -> None: 165 cfg: gitmodules.Config = gitmodules.Config(allow_sso=True) 166 self._run(cfg, dotgitmodules(url='sso://host/foo')) 167 self.ctx.fail.assert_not_called() 168 169 def test_allow_sso_fail(self) -> None: 170 cfg: gitmodules.Config = gitmodules.Config(allow_sso=False) 171 self._run(cfg, dotgitmodules(url='sso://host/foo')) 172 self.ctx.fail.assert_called() 173 174 def test_allow_git_corp_google_com_ok(self) -> None: 175 cfg: gitmodules.Config = gitmodules.Config( 176 allow_git_corp_google_com=True 177 ) 178 self._run(cfg, dotgitmodules(url='https://foo.git.corp.google.com/bar')) 179 self.ctx.fail.assert_not_called() 180 181 def test_allow_git_corp_google_com_fail(self) -> None: 182 cfg: gitmodules.Config = gitmodules.Config( 183 allow_git_corp_google_com=False 184 ) 185 self._run(cfg, dotgitmodules(url='https://foo.git.corp.google.com/bar')) 186 self.ctx.fail.assert_called() 187 188 def test_require_branch_ok(self) -> None: 189 cfg: gitmodules.Config = gitmodules.Config(require_branch=False) 190 self._run(cfg, dotgitmodules(branch=None)) 191 self.ctx.fail.assert_not_called() 192 193 def test_require_branch_fail(self) -> None: 194 cfg: gitmodules.Config = gitmodules.Config(require_branch=True) 195 self._run(cfg, dotgitmodules(branch=None)) 196 self.ctx.fail.assert_called() 197 198 199if __name__ == '__main__': 200 unittest.main() 201