• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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