1# Copyright 2024 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 the clang-format formatter.""" 15 16import importlib.resources 17from pathlib import Path 18from tempfile import TemporaryDirectory 19from typing import Final, Sequence 20import unittest 21 22from format_testing_utils import CapturingToolRunner 23from pw_presubmit.format.cpp import ClangFormatFormatter 24 25_TEST_DATA_FILES = importlib.resources.files('pw_presubmit.format.test_data') 26 27_TEST_SRC_FILE = _TEST_DATA_FILES / 'cpp_test_data.cc' 28_TEST_GOLDEN = _TEST_DATA_FILES / 'cpp_test_data_golden.cc' 29 30_CLANG_FORMAT_CONFIG_PATH = _TEST_DATA_FILES / 'clang_format_config' 31_CLANG_FORMAT_ARGS: Final[Sequence[str]] = ( 32 f'--style=file:{_CLANG_FORMAT_CONFIG_PATH}', 33) 34 35 36class TestClangFormatFormatter(unittest.TestCase): 37 """Tests for the ClangFormatFormatter.""" 38 39 def test_check_file(self): 40 tool_runner = CapturingToolRunner() 41 formatter = ClangFormatFormatter(_CLANG_FORMAT_ARGS) 42 formatter.run_tool = tool_runner 43 44 result = formatter.format_file_in_memory( 45 _TEST_SRC_FILE, _TEST_SRC_FILE.read_bytes() 46 ) 47 self.assertTrue(result.ok) 48 self.assertEqual(result.error_message, None) 49 50 self.assertEqual( 51 tool_runner.command_history.pop(0), 52 ' '.join( 53 ( 54 'clang-format', 55 f'--style=file:{_CLANG_FORMAT_CONFIG_PATH}', 56 str(_TEST_SRC_FILE), 57 ) 58 ), 59 ) 60 61 self.assertMultiLineEqual( 62 result.formatted_file_contents.decode(), _TEST_GOLDEN.read_text() 63 ) 64 65 def test_fix_file(self): 66 tool_runner = CapturingToolRunner() 67 formatter = ClangFormatFormatter(_CLANG_FORMAT_ARGS) 68 formatter.run_tool = tool_runner 69 70 with TemporaryDirectory() as temp_dir: 71 file_to_fix = Path(temp_dir) / _TEST_SRC_FILE.name 72 file_to_fix.write_bytes(_TEST_SRC_FILE.read_bytes()) 73 74 errors = formatter.format_files([file_to_fix]) 75 76 # Error dictionary should be empty. 77 self.assertFalse(list(errors)) 78 79 self.assertEqual( 80 tool_runner.command_history.pop(0), 81 ' '.join( 82 ( 83 'clang-format', 84 '-i', 85 f'--style=file:{_CLANG_FORMAT_CONFIG_PATH}', 86 str(file_to_fix), 87 ) 88 ), 89 ) 90 91 self.assertMultiLineEqual( 92 file_to_fix.read_text(), _TEST_GOLDEN.read_text() 93 ) 94 95 96if __name__ == '__main__': 97 unittest.main() 98