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