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 def setUp(self): 30 # Create a temporary directory for the test. 31 self.test_dir = tempfile.mkdtemp() 32 33 def tearDown(self): 34 # Remove it after the test. 35 shutil.rmtree(self.test_dir) 36 37 def create_file(self, path, contents=''): 38 """Create a file and any directories assuming '/' path separator""" 39 full_file_path = pathlib.Path(self.test_dir, path) 40 if full_file_path.exists(): 41 raise Exception(f'File exists already: {path}') 42 43 # Make parent directories if they don't exsit. 44 full_file_path.parent.mkdir(parents=True, exist_ok=True) 45 46 with open(full_file_path, 'w') as fd: 47 fd.write(contents) 48 49 return full_file_path 50 51 def assert_no_issues(self, checker, directory=None): 52 if directory is not None: 53 directory = str(pathlib.Path(self.test_dir, directory)) 54 else: 55 directory = self.test_dir 56 return self.assertFalse(list(checker(directory))) 57 58 def assert_issue(self, checker, match, directory=None): 59 if directory is not None: 60 directory = str(pathlib.Path(self.test_dir, directory)) 61 else: 62 directory = self.test_dir 63 issues = list(checker(directory)) 64 self.assertTrue(any((match in issue.message) for issue in issues)) 65 66 # Have Python code --> have setup.py. 67 def test_pwck001_have_setup_py(self): 68 # Python files; no setup --> error. 69 self.create_file('pw_foo/py/pw_foo/__init__.py') 70 self.create_file('pw_foo/py/pw_foo/bar.py') 71 self.assert_issue(pw_module.check.check_python_proper_module, 72 'setup.py') 73 74 # Python files; have setup.py --> ok. 75 self.create_file('pw_foo/py/setup.py') 76 self.assert_no_issues(pw_module.check.check_python_proper_module) 77 78 # Have C++ code --> have C++ tests. 79 def test_pwck002_have_python_tests(self): 80 self.create_file('pw_foo/public/foo.h') 81 self.create_file('pw_foo/foo.cc') 82 self.assert_issue(pw_module.check.check_have_cc_tests, 'tests') 83 84 self.create_file('pw_foo/foo_test.cc') 85 self.assert_no_issues(pw_module.check.check_have_cc_tests) 86 87 # Have Python code --> have Python tests. 88 def test_pwck003_have_python_tests(self): 89 self.create_file('pw_foo/py/pw_foo/__init__.py') 90 self.create_file('pw_foo/py/setup.py') 91 self.assert_issue(pw_module.check.check_have_python_tests, 'tests') 92 93 self.create_file('pw_foo/py/foo_test.py') 94 self.assert_no_issues(pw_module.check.check_have_python_tests) 95 96 # Have README.md 97 def test_pwck004_have_readme(self): 98 self.assert_issue(pw_module.check.check_has_readme, 'README') 99 self.create_file('README.md') 100 self.assert_no_issues(pw_module.check.check_has_readme) 101 102 # Have ReST docs of some kind 103 def test_pwck005_have_rst_docs(self): 104 checker = pw_module.check.check_has_rst_docs 105 self.assert_issue(checker, 'ReST') 106 self.create_file('pw_foo/docs.rst') 107 self.assert_no_issues(checker) 108 109 # Have ReST docs of some kind 110 def test_pwck006_have_public_or_override_headers(self): 111 checker = pw_module.check.check_has_public_or_override_headers 112 module_name = 'pw_foo' 113 114 # Only have a doc? Great. 115 self.create_file('pw_foo/docs.rst') 116 self.assert_no_issues(checker, directory=module_name) 117 118 # CC files with no public header --> error. 119 self.create_file('pw_foo/implementation.cc') 120 self.create_file('pw_foo/implementation_test.cc') 121 self.assert_issue(checker, 'public/pw_foo', directory=module_name) 122 123 # CC files with public header in unmatched module folder --> error. 124 bad_header = self.create_file('pw_foo/public/wrong/foo.h') 125 self.assert_issue(checker, 'public/pw_foo', directory=module_name) 126 127 # Remove the "bad" header. 128 bad_header_parent = bad_header.parent 129 bad_header.unlink() 130 bad_header_parent.rmdir() 131 132 # Finally create the correct header. 133 self.create_file('pw_foo/public/pw_foo/baz.h') 134 self.assert_no_issues(checker, directory=module_name) 135 136 # Reject if there are multiple directories in public/... 137 self.create_file('pw_foo/public/fake/fake.h') 138 self.assert_issue(checker, 'multiple', directory=module_name) 139 140 141if __name__ == '__main__': 142 import sys 143 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) 144 unittest.main() 145