• 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 todo_check."""
16
17from pathlib import Path
18import re
19import unittest
20from unittest.mock import MagicMock, mock_open, patch
21
22from pw_presubmit import todo_check
23
24# pylint: disable=attribute-defined-outside-init
25# todo-check: disable
26
27
28class TestTodoCheck(unittest.TestCase):
29    """Test TODO checker."""
30
31    def _run(self, regex: re.Pattern, contents: str) -> None:
32        self.ctx = MagicMock()
33        self.ctx.fail = MagicMock()
34        path = MagicMock(spec=Path('foo/bar'))
35
36        def mocked_open_read(*args, **kwargs):
37            return mock_open(read_data=contents)(*args, **kwargs)
38
39        with patch.object(path, 'open', mocked_open_read):
40            # pylint: disable=protected-access
41            todo_check._process_file(self.ctx, regex, path)
42
43            # pylint: enable=protected-access
44
45    def _run_bugs_users(self, contents: str) -> None:
46        self._run(todo_check.BUGS_OR_USERNAMES, contents)
47
48    def _run_bugs(self, contents: str) -> None:
49        self._run(todo_check.BUGS_ONLY, contents)
50
51    def test_one_bug(self) -> None:
52        contents = 'TODO(b/123): foo\n'
53        self._run_bugs_users(contents)
54        self.ctx.fail.assert_not_called()
55        self._run_bugs(contents)
56        self.ctx.fail.assert_not_called()
57
58    def test_two_bugs(self) -> None:
59        contents = 'TODO(b/123, b/456): foo\n'
60        self._run_bugs_users(contents)
61        self.ctx.fail.assert_not_called()
62        self._run_bugs(contents)
63        self.ctx.fail.assert_not_called()
64
65    def test_three_bugs(self) -> None:
66        contents = 'TODO(b/123,b/456,b/789): foo\n'
67        self._run_bugs_users(contents)
68        self.ctx.fail.assert_not_called()
69        self._run_bugs(contents)
70        self.ctx.fail.assert_not_called()
71
72    def test_one_username(self) -> None:
73        self._run_bugs_users('TODO(usera): foo\n')
74        self.ctx.fail.assert_not_called()
75
76    def test_two_usernames(self) -> None:
77        self._run_bugs_users('TODO(usera, userb): foo\n')
78        self.ctx.fail.assert_not_called()
79
80    def test_three_usernames(self) -> None:
81        self._run_bugs_users('TODO(usera,userb,userc): foo\n')
82        self.ctx.fail.assert_not_called()
83
84    def test_username_not_allowed(self) -> None:
85        self._run_bugs('TODO(usera): foo\n')
86        self.ctx.fail.assert_called()
87
88    def test_space_after_todo_bugsonly(self) -> None:
89        self._run_bugs('TODO (b/123): foo\n')
90        self.ctx.fail.assert_called()
91
92    def test_space_after_todo_bugsusers(self) -> None:
93        self._run_bugs_users('TODO (b/123): foo\n')
94        self.ctx.fail.assert_called()
95
96    def test_space_before_bug_bugsonly(self) -> None:
97        self._run_bugs('TODO( b/123): foo\n')
98        self.ctx.fail.assert_called()
99
100    def test_space_before_bug_bugsusers(self) -> None:
101        self._run_bugs_users('TODO( b/123): foo\n')
102        self.ctx.fail.assert_called()
103
104    def test_space_after_bug_bugsonly(self) -> None:
105        self._run_bugs('TODO(b/123 ): foo\n')
106        self.ctx.fail.assert_called()
107
108    def test_space_after_bug_bugsusers(self) -> None:
109        self._run_bugs_users('TODO(b/123 ): foo\n')
110        self.ctx.fail.assert_called()
111
112    def test_missing_explanation_bugsonly(self) -> None:
113        self._run_bugs('TODO(b/123)\n')
114        self.ctx.fail.assert_called()
115
116    def test_missing_explanation_bugsusers(self) -> None:
117        self._run_bugs_users('TODO(b/123)\n')
118        self.ctx.fail.assert_called()
119
120    def test_not_a_bug_bugsonly(self) -> None:
121        self._run_bugs('TODO(cl/123): foo\n')
122        self.ctx.fail.assert_called()
123
124    def test_not_a_bug_bugsusers(self) -> None:
125        self._run_bugs_users('TODO(cl/123): foo\n')
126        self.ctx.fail.assert_called()
127
128    def test_but_not_bug_bugsonly(self) -> None:
129        self._run_bugs('TODO(b/123, cl/123): foo\n')
130        self.ctx.fail.assert_called()
131
132    def test_bug_not_bug_bugsusers(self) -> None:
133        self._run_bugs_users('TODO(b/123, cl/123): foo\n')
134        self.ctx.fail.assert_called()
135
136    def test_empty_bugsonly(self) -> None:
137        self._run_bugs('TODO(): foo\n')
138        self.ctx.fail.assert_called()
139
140    def test_empty_bugsusers(self) -> None:
141        self._run_bugs_users('TODO(): foo\n')
142        self.ctx.fail.assert_called()
143
144    def test_bare_bugsonly(self) -> None:
145        self._run_bugs('TODO: foo\n')
146        self.ctx.fail.assert_called()
147
148    def test_bare_bugsusers(self) -> None:
149        self._run_bugs_users('TODO: foo\n')
150        self.ctx.fail.assert_called()
151
152
153if __name__ == '__main__':
154    unittest.main()
155
156# todo-check: enable
157