xref: /aosp_15_r20/external/emboss/compiler/front_end/format_emb_test.py (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of 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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Tests for front_end.format_emb."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21import pkgutil
22import re
23import sys
24
25import unittest
26from compiler.front_end import format_emb
27from compiler.front_end import module_ir
28from compiler.front_end import parser
29from compiler.front_end import tokenizer
30
31
32class SanityCheckerTest(unittest.TestCase):
33
34  def test_text_does_not_tokenize(self):
35    self.assertTrue(format_emb.sanity_check_format_result("-- doc", "~ bad"))
36
37  def test_original_text_does_not_tokenize(self):
38    self.assertTrue(format_emb.sanity_check_format_result("~ bad", "-- doc"))
39
40  def test_text_matches(self):
41    self.assertFalse(format_emb.sanity_check_format_result("-- doc", "-- doc"))
42
43  def test_text_has_extra_eols(self):
44    self.assertFalse(
45        format_emb.sanity_check_format_result("-- doc\n\n-- doc",
46                                              "-- doc\n\n\n-- doc"))
47
48  def test_text_has_fewer_eols(self):
49    self.assertFalse(format_emb.sanity_check_format_result("-- doc\n\n-- doc",
50                                                           "-- doc\n-- doc"))
51
52  def test_original_text_has_leading_eols(self):
53    self.assertFalse(format_emb.sanity_check_format_result("\n\n-- doc\n",
54                                                           "-- doc\n"))
55
56  def test_original_text_has_extra_doc_whitespace(self):
57    self.assertFalse(format_emb.sanity_check_format_result("-- doc     \n",
58                                                           "-- doc\n"))
59
60  def test_comments_differ(self):
61    self.assertTrue(format_emb.sanity_check_format_result("#c\n-- doc\n",
62                                                          "#d\n-- doc\n"))
63
64  def test_comment_missing(self):
65    self.assertTrue(format_emb.sanity_check_format_result("#c\n-- doc\n",
66                                                          "\n-- doc\n"))
67
68  def test_comment_added(self):
69    self.assertTrue(format_emb.sanity_check_format_result("\n-- doc\n",
70                                                          "#d\n-- doc\n"))
71
72  def test_token_text_differs(self):
73    self.assertTrue(format_emb.sanity_check_format_result("-- doc\n",
74                                                          "-- bad doc\n"))
75
76  def test_token_type_differs(self):
77    self.assertTrue(format_emb.sanity_check_format_result("-- doc\n",
78                                                          "abc\n"))
79
80  def test_eol_missing(self):
81    self.assertTrue(format_emb.sanity_check_format_result("abc\n-- doc\n",
82                                                          "abc -- doc\n"))
83
84
85class FormatEmbTest(unittest.TestCase):
86  pass
87
88
89def _make_golden_file_tests():
90  """Generates test cases from the golden files in the resource bundle."""
91
92  package = "testdata.format"
93  path_prefix = ""
94
95  def make_test_case(name, unformatted_text, expected_text, indent_width):
96
97    def test_case(self):
98      self.maxDiff = 100000
99      unformatted_tokens, errors = tokenizer.tokenize(unformatted_text, name)
100      self.assertFalse(errors)
101      parsed_unformatted = parser.parse_module(unformatted_tokens)
102      self.assertFalse(parsed_unformatted.error)
103      formatted_text = format_emb.format_emboss_parse_tree(
104          parsed_unformatted.parse_tree,
105          format_emb.Config(indent_width=indent_width))
106      self.assertEqual(expected_text, formatted_text)
107      annotated_text = format_emb.format_emboss_parse_tree(
108          parsed_unformatted.parse_tree,
109          format_emb.Config(indent_width=indent_width, show_line_types=True))
110      self.assertEqual(expected_text, re.sub(r"^.*?\|", "", annotated_text,
111                                             flags=re.MULTILINE))
112      self.assertFalse(re.search("^[^|]+$", annotated_text, flags=re.MULTILINE))
113
114    return test_case
115
116  all_unformatted_texts = []
117
118  for filename in (
119      "abbreviations",
120      "anonymous_bits_formatting",
121      "arithmetic_expressions",
122      "array_length",
123      "attributes",
124      "choice_expression",
125      "comparison_expressions",
126      "conditional_field_formatting",
127      "conditional_inline_bits_formatting",
128      "dotted_names",
129      "empty",
130      "enum_value_attributes",
131      "enum_value_bodies",
132      "enum_values_aligned",
133      "equality_expressions",
134      "external",
135      "extra_newlines",
136      "fields_aligned",
137      "functions",
138      "header_and_type",
139      "indent",
140      "inline_attributes_get_a_column",
141      "inline_bits",
142      "inline_documentation_gets_a_column",
143      "inline_enum",
144      "inline_struct",
145      "lines_not_spaced_out_with_excess_trailing_noise_lines",
146      "lines_not_spaced_out_with_not_enough_noise_lines",
147      "lines_spaced_out_with_noise_lines",
148      "logical_expressions",
149      "multiline_ifs",
150      "multiple_header_sections",
151      "nested_types_are_columnized_independently",
152      "one_type",
153      "parameterized_struct",
154      "sanity_check",
155      "spacing_between_types",
156      "trailing_spaces",
157      "virtual_fields"):
158    for suffix, width in ((".emb.formatted", 2),
159                          (".emb.formatted_indent_4", 4)):
160      unformatted_name = path_prefix + filename + ".emb"
161      expected_name = path_prefix + filename + suffix
162      unformatted_text = pkgutil.get_data(package,
163                                          unformatted_name).decode("utf-8")
164      expected_text = pkgutil.get_data(package, expected_name).decode("utf-8")
165      setattr(FormatEmbTest, "test {} indent {}".format(filename, width),
166              make_test_case(filename, unformatted_text, expected_text, width))
167
168      all_unformatted_texts.append(unformatted_text)
169
170  def test_all_productions_used(self):
171    used_productions = set()
172    for unformatted_text in all_unformatted_texts:
173      unformatted_tokens, errors = tokenizer.tokenize(unformatted_text, "")
174      self.assertFalse(errors)
175      parsed_unformatted = parser.parse_module(unformatted_tokens)
176      self.assertFalse(parsed_unformatted.error)
177      format_emb.format_emboss_parse_tree(parsed_unformatted.parse_tree,
178                                          format_emb.Config(), used_productions)
179    unused_productions = set(module_ir.PRODUCTIONS) - used_productions
180    if unused_productions:
181      print("Used production total:", len(used_productions), file=sys.stderr)
182      for production in unused_productions:
183        print("Unused production:", str(production), file=sys.stderr)
184      print("Total:", len(unused_productions), file=sys.stderr)
185    self.assertEqual(set(module_ir.PRODUCTIONS), used_productions)
186
187  FormatEmbTest.testAllProductionsUsed = test_all_productions_used
188
189
190_make_golden_file_tests()
191
192if __name__ == "__main__":
193  unittest.main()
194