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