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