| # 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() |