xref: /aosp_15_r20/external/pigweed/pw_presubmit/py/gn_format_test.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 GN's built-in formatter."""
15
16import importlib.resources
17from pathlib import Path
18from tempfile import TemporaryDirectory
19import unittest
20
21from format_testing_utils import CapturingToolRunner
22from pw_presubmit.format.gn import GnFormatter
23
24
25_TEST_DATA_FILES = importlib.resources.files('pw_presubmit.format.test_data')
26_TEST_SRC_FILE = _TEST_DATA_FILES / 'gn_test_data.gn'
27_TEST_GOLDEN = _TEST_DATA_FILES / 'gn_test_data_golden.gn'
28_TEST_MALFORMED = _TEST_DATA_FILES / 'malformed_file.txt'
29
30
31class TestGnFormatter(unittest.TestCase):
32    """Tests for the GnFormatter."""
33
34    def test_check_file(self):
35        tool_runner = CapturingToolRunner()
36        formatter = GnFormatter()
37        formatter.run_tool = tool_runner
38
39        result = formatter.format_file_in_memory(
40            _TEST_SRC_FILE, _TEST_SRC_FILE.read_bytes()
41        )
42        self.assertTrue(result.ok)
43        self.assertEqual(result.error_message, None)
44        self.assertMultiLineEqual(
45            result.formatted_file_contents.decode(), _TEST_GOLDEN.read_text()
46        )
47
48        self.assertEqual(
49            tool_runner.command_history.pop(0),
50            ' '.join(
51                (
52                    'gn',
53                    'format',
54                    '--stdin',
55                )
56            ),
57        )
58
59    def test_check_file_error(self):
60        tool_runner = CapturingToolRunner()
61        formatter = GnFormatter()
62        formatter.run_tool = tool_runner
63
64        result = formatter.format_file_in_memory(
65            _TEST_MALFORMED, _TEST_MALFORMED.read_bytes()
66        )
67        self.assertFalse(result.ok)
68        self.assertTrue(result.error_message.startswith('ERROR at'))
69        self.assertTrue('Invalid token' in result.error_message)
70        self.assertEqual(result.formatted_file_contents, b'')
71
72        self.assertEqual(
73            tool_runner.command_history.pop(0),
74            ' '.join(
75                (
76                    'gn',
77                    'format',
78                    '--stdin',
79                )
80            ),
81        )
82
83    def test_fix_file(self):
84        """Tests that formatting is properly applied to files."""
85
86        tool_runner = CapturingToolRunner()
87        formatter = GnFormatter()
88        formatter.run_tool = tool_runner
89
90        with TemporaryDirectory() as temp_dir:
91            file_to_fix = Path(temp_dir) / _TEST_SRC_FILE.name
92            file_to_fix.write_bytes(_TEST_SRC_FILE.read_bytes())
93
94            malformed_file = Path(temp_dir) / _TEST_MALFORMED.name
95            malformed_file.write_bytes(_TEST_MALFORMED.read_bytes())
96
97            errors = list(formatter.format_files([file_to_fix, malformed_file]))
98
99            # Should see three separate commands, one where we try to format
100            # both files together, and then the fallback logic that formats
101            # them individually to isolate errors.
102            self.assertEqual(
103                tool_runner.command_history.pop(0),
104                ' '.join(
105                    (
106                        'gn',
107                        'format',
108                        str(file_to_fix),
109                        str(malformed_file),
110                    )
111                ),
112            )
113
114            self.assertEqual(
115                tool_runner.command_history.pop(0),
116                ' '.join(
117                    (
118                        'gn',
119                        'format',
120                        str(file_to_fix),
121                    )
122                ),
123            )
124
125            self.assertEqual(
126                tool_runner.command_history.pop(0),
127                ' '.join(
128                    (
129                        'gn',
130                        'format',
131                        str(malformed_file),
132                    )
133                ),
134            )
135
136            # Check good build file.
137            self.assertMultiLineEqual(
138                file_to_fix.read_text(), _TEST_GOLDEN.read_text()
139            )
140
141            # Check malformed file.
142            self.assertEqual(len(errors), 1)
143            malformed_files = [malformed_file]
144            for file_path, error in errors:
145                self.assertIn(file_path, malformed_files)
146                self.assertFalse(error.ok)
147                self.assertTrue(error.error_message.startswith('ERROR at'))
148
149
150if __name__ == '__main__':
151    unittest.main()
152