xref: /aosp_15_r20/external/pigweed/pw_module/py/check_test.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2019 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Tests for pw_module.check."""
15
16import logging
17import pathlib
18import shutil
19import tempfile
20import unittest
21
22import pw_module.check
23
24_LOG = logging.getLogger(__name__)
25
26
27class TestWithTempDirectory(unittest.TestCase):
28    """Tests for pw_module.check."""
29
30    def setUp(self):
31        # Create a temporary directory for the test.
32        self.test_dir = tempfile.mkdtemp()
33
34    def tearDown(self):
35        # Remove it after the test.
36        shutil.rmtree(self.test_dir)
37
38    def create_file(self, path, contents=''):
39        """Create a file and any directories assuming '/' path separator"""
40        full_file_path = pathlib.Path(self.test_dir, path)
41        if full_file_path.exists():
42            raise Exception(f'File exists already: {path}')
43
44        # Make parent directories if they don't exsit.
45        full_file_path.parent.mkdir(parents=True, exist_ok=True)
46
47        with open(full_file_path, 'w') as fd:
48            fd.write(contents)
49
50        return full_file_path
51
52    def assert_no_issues(self, checker, directory=None):
53        if directory is not None:
54            directory = str(pathlib.Path(self.test_dir, directory))
55        else:
56            directory = self.test_dir
57        return self.assertFalse(list(checker(directory)))
58
59    def assert_issue(self, checker, match, directory=None):
60        if directory is not None:
61            directory = str(pathlib.Path(self.test_dir, directory))
62        else:
63            directory = self.test_dir
64        issues = list(checker(directory))
65        self.assertTrue(any((match in issue.message) for issue in issues))
66
67    # Have Python code --> have setup.py.
68    def test_pwck001_have_setup_py(self):
69        # Python files; no setup --> error.
70        self.create_file('pw_foo/py/pw_foo/__init__.py')
71        self.create_file('pw_foo/py/pw_foo/bar.py')
72        self.assert_issue(
73            pw_module.check.check_python_proper_module, 'setup.py'
74        )
75
76        # Python files; have setup.py --> ok.
77        self.create_file('pw_foo/py/setup.py')
78        self.assert_no_issues(pw_module.check.check_python_proper_module)
79
80    # Have C++ code --> have C++ tests.
81    def test_pwck002_have_python_tests(self):
82        self.create_file('pw_foo/public/foo.h')
83        self.create_file('pw_foo/foo.cc')
84        self.assert_issue(pw_module.check.check_have_cc_tests, 'tests')
85
86        self.create_file('pw_foo/foo_test.cc')
87        self.assert_no_issues(pw_module.check.check_have_cc_tests)
88
89    # Have Python code --> have Python tests.
90    def test_pwck003_have_python_tests(self):
91        self.create_file('pw_foo/py/pw_foo/__init__.py')
92        self.create_file('pw_foo/py/setup.py')
93        self.assert_issue(pw_module.check.check_have_python_tests, 'tests')
94
95        self.create_file('pw_foo/py/foo_test.py')
96        self.assert_no_issues(pw_module.check.check_have_python_tests)
97
98    # Have ReST docs of some kind
99    def test_pwck004_have_rst_docs(self):
100        checker = pw_module.check.check_has_rst_docs
101        self.assert_issue(checker, 'ReST')
102        self.create_file('pw_foo/docs.rst')
103        self.assert_no_issues(checker)
104
105    # Have ReST docs of some kind
106    def test_pwck005_have_public_or_override_headers(self):
107        checker = pw_module.check.check_has_public_or_override_headers
108        module_name = 'pw_foo'
109
110        # Only have a doc? Great.
111        self.create_file('pw_foo/docs.rst')
112        self.assert_no_issues(checker, directory=module_name)
113
114        # CC files with no public header --> error.
115        self.create_file('pw_foo/implementation.cc')
116        self.create_file('pw_foo/implementation_test.cc')
117        self.assert_issue(checker, 'public/pw_foo', directory=module_name)
118
119        # CC files with public header in unmatched module folder --> error.
120        bad_header = self.create_file('pw_foo/public/wrong/foo.h')
121        self.assert_issue(checker, 'public/pw_foo', directory=module_name)
122
123        # Remove the "bad" header.
124        bad_header_parent = bad_header.parent
125        bad_header.unlink()
126        bad_header_parent.rmdir()
127
128        # Finally create the correct header.
129        self.create_file('pw_foo/public/pw_foo/baz.h')
130        self.assert_no_issues(checker, directory=module_name)
131
132        # Reject if there are multiple directories in public/...
133        self.create_file('pw_foo/public/fake/fake.h')
134        self.assert_issue(checker, 'multiple', directory=module_name)
135
136
137if __name__ == '__main__':
138    import sys
139
140    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
141    unittest.main()
142