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