# Copyright 2019 Google LLC # # 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 # # https://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. """Tests for front_end.format_emb.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function import pkgutil import re import sys import unittest from compiler.front_end import format_emb from compiler.front_end import module_ir from compiler.front_end import parser from compiler.front_end import tokenizer class SanityCheckerTest(unittest.TestCase): def test_text_does_not_tokenize(self): self.assertTrue(format_emb.sanity_check_format_result("-- doc", "~ bad")) def test_original_text_does_not_tokenize(self): self.assertTrue(format_emb.sanity_check_format_result("~ bad", "-- doc")) def test_text_matches(self): self.assertFalse(format_emb.sanity_check_format_result("-- doc", "-- doc")) def test_text_has_extra_eols(self): self.assertFalse( format_emb.sanity_check_format_result("-- doc\n\n-- doc", "-- doc\n\n\n-- doc")) def test_text_has_fewer_eols(self): self.assertFalse(format_emb.sanity_check_format_result("-- doc\n\n-- doc", "-- doc\n-- doc")) def test_original_text_has_leading_eols(self): self.assertFalse(format_emb.sanity_check_format_result("\n\n-- doc\n", "-- doc\n")) def test_original_text_has_extra_doc_whitespace(self): self.assertFalse(format_emb.sanity_check_format_result("-- doc \n", "-- doc\n")) def test_comments_differ(self): self.assertTrue(format_emb.sanity_check_format_result("#c\n-- doc\n", "#d\n-- doc\n")) def test_comment_missing(self): self.assertTrue(format_emb.sanity_check_format_result("#c\n-- doc\n", "\n-- doc\n")) def test_comment_added(self): self.assertTrue(format_emb.sanity_check_format_result("\n-- doc\n", "#d\n-- doc\n")) def test_token_text_differs(self): self.assertTrue(format_emb.sanity_check_format_result("-- doc\n", "-- bad doc\n")) def test_token_type_differs(self): self.assertTrue(format_emb.sanity_check_format_result("-- doc\n", "abc\n")) def test_eol_missing(self): self.assertTrue(format_emb.sanity_check_format_result("abc\n-- doc\n", "abc -- doc\n")) class FormatEmbTest(unittest.TestCase): pass def _make_golden_file_tests(): """Generates test cases from the golden files in the resource bundle.""" package = "testdata.format" path_prefix = "" def make_test_case(name, unformatted_text, expected_text, indent_width): def test_case(self): self.maxDiff = 100000 unformatted_tokens, errors = tokenizer.tokenize(unformatted_text, name) self.assertFalse(errors) parsed_unformatted = parser.parse_module(unformatted_tokens) self.assertFalse(parsed_unformatted.error) formatted_text = format_emb.format_emboss_parse_tree( parsed_unformatted.parse_tree, format_emb.Config(indent_width=indent_width)) self.assertEqual(expected_text, formatted_text) annotated_text = format_emb.format_emboss_parse_tree( parsed_unformatted.parse_tree, format_emb.Config(indent_width=indent_width, show_line_types=True)) self.assertEqual(expected_text, re.sub(r"^.*?\|", "", annotated_text, flags=re.MULTILINE)) self.assertFalse(re.search("^[^|]+$", annotated_text, flags=re.MULTILINE)) return test_case all_unformatted_texts = [] for filename in ( "abbreviations", "anonymous_bits_formatting", "arithmetic_expressions", "array_length", "attributes", "choice_expression", "comparison_expressions", "conditional_field_formatting", "conditional_inline_bits_formatting", "dotted_names", "empty", "enum_value_attributes", "enum_value_bodies", "enum_values_aligned", "equality_expressions", "external", "extra_newlines", "fields_aligned", "functions", "header_and_type", "indent", "inline_attributes_get_a_column", "inline_bits", "inline_documentation_gets_a_column", "inline_enum", "inline_struct", "lines_not_spaced_out_with_excess_trailing_noise_lines", "lines_not_spaced_out_with_not_enough_noise_lines", "lines_spaced_out_with_noise_lines", "logical_expressions", "multiline_ifs", "multiple_header_sections", "nested_types_are_columnized_independently", "one_type", "parameterized_struct", "sanity_check", "spacing_between_types", "trailing_spaces", "virtual_fields"): for suffix, width in ((".emb.formatted", 2), (".emb.formatted_indent_4", 4)): unformatted_name = path_prefix + filename + ".emb" expected_name = path_prefix + filename + suffix unformatted_text = pkgutil.get_data(package, unformatted_name).decode("utf-8") expected_text = pkgutil.get_data(package, expected_name).decode("utf-8") setattr(FormatEmbTest, "test {} indent {}".format(filename, width), make_test_case(filename, unformatted_text, expected_text, width)) all_unformatted_texts.append(unformatted_text) def test_all_productions_used(self): used_productions = set() for unformatted_text in all_unformatted_texts: unformatted_tokens, errors = tokenizer.tokenize(unformatted_text, "") self.assertFalse(errors) parsed_unformatted = parser.parse_module(unformatted_tokens) self.assertFalse(parsed_unformatted.error) format_emb.format_emboss_parse_tree(parsed_unformatted.parse_tree, format_emb.Config(), used_productions) unused_productions = set(module_ir.PRODUCTIONS) - used_productions if unused_productions: print("Used production total:", len(used_productions), file=sys.stderr) for production in unused_productions: print("Unused production:", str(production), file=sys.stderr) print("Total:", len(unused_productions), file=sys.stderr) self.assertEqual(set(module_ir.PRODUCTIONS), used_productions) FormatEmbTest.testAllProductionsUsed = test_all_productions_used _make_golden_file_tests() if __name__ == "__main__": unittest.main()