blob: 7d2577f07d378e556f20ccddc7ce917f0d3fae5a [file] [log] [blame] [edit]
# 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 util.error."""
import unittest
from compiler.util import error
from compiler.util import parser_types
class MessageTest(unittest.TestCase):
"""Tests for _Message, as returned by error, warn, and note."""
def test_error(self):
error_message = error.error("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "Bad thing")
self.assertEqual("foo.emb", error_message.source_file)
self.assertEqual(error.ERROR, error_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (3, 6)),
error_message.location)
self.assertEqual("Bad thing", error_message.message)
sourceless_format = error_message.format({})
sourced_format = error_message.format({"foo.emb": "\n\nabcdefghijklm"})
self.assertEqual("foo.emb:3:4: error: Bad thing",
"".join([x[1] for x in sourceless_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing"), # Message
], sourceless_format)
self.assertEqual("foo.emb:3:4: error: Bad thing\n"
"abcdefghijklm\n"
" ^^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing\n"), # Message
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^^"), # Error column indicator
], sourced_format)
def test_synthetic_error(self):
error_message = error.error("foo.emb", parser_types.make_location(
(3, 4), (3, 6), True), "Bad thing")
sourceless_format = error_message.format({})
sourced_format = error_message.format({"foo.emb": "\n\nabcdefghijklm"})
self.assertEqual("foo.emb:[compiler bug]: error: Bad thing",
"".join([x[1] for x in sourceless_format]))
self.assertEqual([
(error.BOLD, "foo.emb:[compiler bug]: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing"), # Message
], sourceless_format)
self.assertEqual("foo.emb:[compiler bug]: error: Bad thing",
"".join([x[1] for x in sourced_format]))
self.assertEqual([
(error.BOLD, "foo.emb:[compiler bug]: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing"), # Message
], sourced_format)
def test_prelude_as_file_name(self):
error_message = error.error("", parser_types.make_location(
(3, 4), (3, 6)), "Bad thing")
self.assertEqual("", error_message.source_file)
self.assertEqual(error.ERROR, error_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (3, 6)),
error_message.location)
self.assertEqual("Bad thing", error_message.message)
sourceless_format = error_message.format({})
sourced_format = error_message.format({"": "\n\nabcdefghijklm"})
self.assertEqual("[prelude]:3:4: error: Bad thing",
"".join([x[1] for x in sourceless_format]))
self.assertEqual([(error.BOLD, "[prelude]:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing"), # Message
], sourceless_format)
self.assertEqual("[prelude]:3:4: error: Bad thing\n"
"abcdefghijklm\n"
" ^^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "[prelude]:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing\n"), # Message
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^^"), # Error column indicator
], sourced_format)
def test_multiline_error_source(self):
error_message = error.error("foo.emb", parser_types.make_location(
(3, 4), (4, 6)), "Bad thing")
self.assertEqual("foo.emb", error_message.source_file)
self.assertEqual(error.ERROR, error_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (4, 6)),
error_message.location)
self.assertEqual("Bad thing", error_message.message)
sourceless_format = error_message.format({})
sourced_format = error_message.format(
{"foo.emb": "\n\nabcdefghijklm\nnopqrstuv"})
self.assertEqual("foo.emb:3:4: error: Bad thing",
"".join([x[1] for x in sourceless_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing"), # Message
], sourceless_format)
self.assertEqual("foo.emb:3:4: error: Bad thing\n"
"abcdefghijklm\n"
" ^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing\n"), # Message
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^"), # Error column indicator
], sourced_format)
def test_multiline_error(self):
error_message = error.error("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "Bad thing\nSome explanation\nMore explanation")
self.assertEqual("foo.emb", error_message.source_file)
self.assertEqual(error.ERROR, error_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (3, 6)),
error_message.location)
self.assertEqual("Bad thing\nSome explanation\nMore explanation",
error_message.message)
sourceless_format = error_message.format({})
sourced_format = error_message.format(
{"foo.emb": "\n\nabcdefghijklm\nnopqrstuv"})
self.assertEqual("foo.emb:3:4: error: Bad thing\n"
"foo.emb:3:4: note: Some explanation\n"
"foo.emb:3:4: note: More explanation",
"".join([x[1] for x in sourceless_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing\n"), # Message
(error.BOLD, "foo.emb:3:4: "), # Location, line 2
(error.BRIGHT_BLACK, "note: "), # "Note" severity, line 2
(error.WHITE, "Some explanation\n"), # Message, line 2
(error.BOLD, "foo.emb:3:4: "), # Location, line 3
(error.BRIGHT_BLACK, "note: "), # "Note" severity, line 3
(error.WHITE, "More explanation"), # Message, line 3
], sourceless_format)
self.assertEqual("foo.emb:3:4: error: Bad thing\n"
"foo.emb:3:4: note: Some explanation\n"
"foo.emb:3:4: note: More explanation\n"
"abcdefghijklm\n"
" ^^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_RED, "error: "), # Severity
(error.BOLD, "Bad thing\n"), # Message
(error.BOLD, "foo.emb:3:4: "), # Location, line 2
(error.BRIGHT_BLACK, "note: "), # "Note" severity, line 2
(error.WHITE, "Some explanation\n"), # Message, line 2
(error.BOLD, "foo.emb:3:4: "), # Location, line 3
(error.BRIGHT_BLACK, "note: "), # "Note" severity, line 3
(error.WHITE, "More explanation\n"), # Message, line 3
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^^"), # Column indicator
], sourced_format)
def test_warn(self):
warning_message = error.warn("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "Not good thing")
self.assertEqual("foo.emb", warning_message.source_file)
self.assertEqual(error.WARNING, warning_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (3, 6)),
warning_message.location)
self.assertEqual("Not good thing", warning_message.message)
sourced_format = warning_message.format({"foo.emb": "\n\nabcdefghijklm"})
self.assertEqual("foo.emb:3:4: warning: Not good thing\n"
"abcdefghijklm\n"
" ^^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_MAGENTA, "warning: "), # Severity
(error.BOLD, "Not good thing\n"), # Message
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^^"), # Column indicator
], sourced_format)
def test_note(self):
note_message = error.note("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "OK thing")
self.assertEqual("foo.emb", note_message.source_file)
self.assertEqual(error.NOTE, note_message.severity)
self.assertEqual(parser_types.make_location((3, 4), (3, 6)),
note_message.location)
self.assertEqual("OK thing", note_message.message)
sourced_format = note_message.format({"foo.emb": "\n\nabcdefghijklm"})
self.assertEqual("foo.emb:3:4: note: OK thing\n"
"abcdefghijklm\n"
" ^^", "".join([x[1] for x in sourced_format]))
self.assertEqual([(error.BOLD, "foo.emb:3:4: "), # Location
(error.BRIGHT_BLACK, "note: "), # Severity
(error.WHITE, "OK thing\n"), # Message
(error.WHITE, "abcdefghijklm\n"), # Source snippet
(error.BRIGHT_GREEN, " ^^"), # Column indicator
], sourced_format)
def test_equality(self):
note_message = error.note("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "thing")
self.assertEqual(note_message,
error.note("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "thing"))
self.assertNotEqual(note_message,
error.warn("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "thing"))
self.assertNotEqual(note_message,
error.note("foo2.emb", parser_types.make_location(
(3, 4), (3, 6)), "thing"))
self.assertNotEqual(note_message,
error.note("foo.emb", parser_types.make_location(
(2, 4), (3, 6)), "thing"))
self.assertNotEqual(note_message,
error.note("foo.emb", parser_types.make_location(
(3, 4), (3, 6)), "thing2"))
class StringTest(unittest.TestCase):
"""Tests for strings."""
# These strings are a fixed part of the API.
def test_color_strings(self):
self.assertEqual("\033[0;30m", error.BLACK)
self.assertEqual("\033[0;31m", error.RED)
self.assertEqual("\033[0;32m", error.GREEN)
self.assertEqual("\033[0;33m", error.YELLOW)
self.assertEqual("\033[0;34m", error.BLUE)
self.assertEqual("\033[0;35m", error.MAGENTA)
self.assertEqual("\033[0;36m", error.CYAN)
self.assertEqual("\033[0;37m", error.WHITE)
self.assertEqual("\033[0;1;30m", error.BRIGHT_BLACK)
self.assertEqual("\033[0;1;31m", error.BRIGHT_RED)
self.assertEqual("\033[0;1;32m", error.BRIGHT_GREEN)
self.assertEqual("\033[0;1;33m", error.BRIGHT_YELLOW)
self.assertEqual("\033[0;1;34m", error.BRIGHT_BLUE)
self.assertEqual("\033[0;1;35m", error.BRIGHT_MAGENTA)
self.assertEqual("\033[0;1;36m", error.BRIGHT_CYAN)
self.assertEqual("\033[0;1;37m", error.BRIGHT_WHITE)
self.assertEqual("\033[0;1m", error.BOLD)
self.assertEqual("\033[0m", error.RESET)
def test_error_strings(self):
self.assertEqual("error", error.ERROR)
self.assertEqual("warning", error.WARNING)
self.assertEqual("note", error.NOTE)
class SplitErrorsTest(unittest.TestCase):
def test_split_errors(self):
user_error = [
error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((3, 4), (5, 6)),
"Note: bad thing referrent")
]
user_error_2 = [
error.error("foo.emb", parser_types.make_location((8, 9), (10, 11)),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((10, 11), (12, 13)),
"Note: bad thing referrent")
]
synthetic_error = [
error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((3, 4), (5, 6), True),
"Note: bad thing referrent")
]
synthetic_error_2 = [
error.error("foo.emb",
parser_types.make_location((8, 9), (10, 11), True),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((10, 11), (12, 13)),
"Note: bad thing referrent")
]
user_errors, synthetic_errors = error.split_errors(
[user_error, synthetic_error])
self.assertEqual([user_error], user_errors)
self.assertEqual([synthetic_error], synthetic_errors)
user_errors, synthetic_errors = error.split_errors(
[synthetic_error, user_error])
self.assertEqual([user_error], user_errors)
self.assertEqual([synthetic_error], synthetic_errors)
user_errors, synthetic_errors = error.split_errors(
[synthetic_error, user_error, synthetic_error_2, user_error_2])
self.assertEqual([user_error, user_error_2], user_errors)
self.assertEqual([synthetic_error, synthetic_error_2], synthetic_errors)
def test_filter_errors(self):
user_error = [
error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((3, 4), (5, 6)),
"Note: bad thing referrent")
]
synthetic_error = [
error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((3, 4), (5, 6), True),
"Note: bad thing referrent")
]
synthetic_error_2 = [
error.error("foo.emb",
parser_types.make_location((8, 9), (10, 11), True),
"Bad thing"),
error.note("foo.emb", parser_types.make_location((10, 11), (12, 13)),
"Note: bad thing referrent")
]
self.assertEqual(
[user_error],
error.filter_errors([synthetic_error, user_error, synthetic_error_2]))
class FormatErrorsTest(unittest.TestCase):
def test_format_errors(self):
errors = [[error.note("foo.emb", parser_types.make_location((3, 4), (3, 6)),
"note")]]
sources = {"foo.emb": "x\ny\nz bcd\nq\n"}
self.assertEqual("foo.emb:3:4: note: note\n"
"z bcd\n"
" ^^", error.format_errors(errors, sources))
bold = error.BOLD
reset = error.RESET
white = error.WHITE
bright_black = error.BRIGHT_BLACK
bright_green = error.BRIGHT_GREEN
self.assertEqual(bold + "foo.emb:3:4: " + reset + bright_black + "note: " +
reset + white + "note\n" +
reset + white + "z bcd\n" +
reset + bright_green + " ^^" + reset,
error.format_errors(errors, sources, use_color=True))
if __name__ == "__main__":
unittest.main()