| #!/usr/bin/env python3 |
| # Copyright 2022 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Unittests for clang-format.""" |
| |
| import contextlib |
| from pathlib import Path |
| import sys |
| import tempfile |
| import unittest |
| |
| |
| DIR = Path(__file__).resolve().parent |
| sys.path.insert(0, str(DIR.parent)) |
| |
| # We have to import our local modules after the sys.path tweak. We can't use |
| # relative imports because this is an executable program, not a module. |
| # pylint: disable=wrong-import-position,import-error |
| import rh.utils |
| |
| |
| CLANG_FORMAT = DIR / 'clang-format.py' |
| |
| |
| @contextlib.contextmanager |
| def git_clang_format(data: str): |
| """Create a fake git-clang-format script.""" |
| with tempfile.TemporaryDirectory(prefix='repohooks-tests') as tempdir: |
| tempdir = Path(tempdir) |
| script = tempdir / 'git-clang-format-fake.sh' |
| script.write_text(f'#!/bin/sh\n{data}', encoding='utf-8') |
| script.chmod(0o755) |
| yield script |
| |
| |
| def run_clang_format(script, args, **kwargs): |
| """Helper to run clang-format.py with fake git-clang-format script.""" |
| kwargs.setdefault('capture_output', True) |
| return rh.utils.run( |
| [CLANG_FORMAT, '--git-clang-format', script] + args, **kwargs) |
| |
| |
| class GitClangFormatExit(unittest.TestCase): |
| """Test git-clang-format parsing.""" |
| |
| def test_diff_exit_0_no_output(self): |
| """Test exit 0 w/no output.""" |
| with git_clang_format('exit 0') as script: |
| result = run_clang_format(script, ['--working-tree']) |
| self.assertEqual(result.stdout, '') |
| |
| def test_diff_exit_0_stderr(self): |
| """Test exit 0 w/stderr output.""" |
| with git_clang_format('echo bad >&2; exit 0') as script: |
| with self.assertRaises(rh.utils.CalledProcessError) as e: |
| run_clang_format(script, ['--working-tree']) |
| self.assertIn('clang-format failed', e.exception.stderr) |
| |
| def test_diff_exit_1_no_output(self): |
| """Test exit 1 w/no output.""" |
| with git_clang_format('exit 1') as script: |
| result = run_clang_format(script, ['--working-tree']) |
| self.assertEqual(result.stdout, '') |
| |
| def test_diff_exit_1_output(self): |
| """Test exit 1 with output.""" |
| with git_clang_format('echo bad; exit 1') as script: |
| with self.assertRaises(rh.utils.CalledProcessError) as e: |
| run_clang_format(script, ['--working-tree']) |
| self.assertIn('clang-format failed', e.exception.stderr) |
| |
| def test_diff_exit_1_stderr(self): |
| """Test exit 1 w/stderr.""" |
| with git_clang_format('echo bad >&2; exit 1') as script: |
| with self.assertRaises(rh.utils.CalledProcessError) as e: |
| run_clang_format(script, ['--working-tree']) |
| self.assertIn('clang-format failed', e.exception.stderr) |
| |
| def test_diff_exit_2(self): |
| """Test exit 2.""" |
| with git_clang_format('exit 2') as script: |
| with self.assertRaises(rh.utils.CalledProcessError) as e: |
| run_clang_format(script, ['--working-tree']) |
| self.assertIn('clang-format failed', e.exception.stderr) |
| |
| def test_fix_exit_1_output(self): |
| """Test fix with incorrect patch syntax.""" |
| with git_clang_format('echo bad patch; exit 1') as script: |
| with self.assertRaises(rh.utils.CalledProcessError) as e: |
| run_clang_format(script, ['--working-tree', '--fix']) |
| self.assertIn('Error: Unable to automatically fix things', |
| e.exception.stderr) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |