From c9d1a4247fec58815a3ea0f73aa333c051d0ea2b Mon Sep 17 00:00:00 2001
From: "Gordon P. Hemsley"
Date: Tue, 30 Aug 2016 18:43:08 -0400
Subject: [PATCH] Improve test coverage for tools.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Replace generic Exception with TemplateParserException.
* Add tests to cover many of the uncovered lines in
tools/lib/template_parser.py.
* Add an exclusion line to the naïve pattern for checking for missing
tuples in format strings, to keep the linter happy.
---
tools/lib/template_parser.py | 14 +++--
tools/lint-all | 3 +
tools/tests/test_template_parser.py | 91 +++++++++++++++++++++++++++--
3 files changed, 99 insertions(+), 9 deletions(-)
diff --git a/tools/lib/template_parser.py b/tools/lib/template_parser.py
index 59870b31b0..f323f4947f 100644
--- a/tools/lib/template_parser.py
+++ b/tools/lib/template_parser.py
@@ -4,6 +4,10 @@ from typing import Callable, Optional
from six.moves import range
import re
+class TemplateParserException(Exception):
+ # TODO: Have callers pass in line numbers.
+ pass
+
class TokenizerState(object):
def __init__(self):
# type: () -> None
@@ -128,7 +132,7 @@ def validate(fn=None, text=None, check_indent=True):
def no_start_tag(token):
# type: (Token) -> None
- raise Exception('''
+ raise TemplateParserException('''
No start tag
fn: %s
end tag:
@@ -167,7 +171,7 @@ def validate(fn=None, text=None, check_indent=True):
if end_col != start_col:
problem = 'Bad indentation.'
if problem:
- raise Exception('''
+ raise TemplateParserException('''
fn: %s
%s
start:
@@ -238,7 +242,7 @@ def get_handlebars_tag(text, i):
while end < len(text) -1 and text[end] != '}':
end += 1
if text[end] != '}' or text[end+1] != '}':
- raise Exception('Tag missing }}')
+ raise TemplateParserException('Tag missing }}')
s = text[i:end+2]
return s
@@ -248,7 +252,7 @@ def get_django_tag(text, i):
while end < len(text) -1 and text[end] != '%':
end += 1
if text[end] != '%' or text[end+1] != '}':
- raise Exception('Tag missing %}')
+ raise TemplateParserException('Tag missing %}')
s = text[i:end+2]
return s
@@ -261,7 +265,7 @@ def get_html_tag(text, i):
quote_count += 1
end += 1
if end == len(text) or text[end] != '>':
- raise Exception('Tag missing >')
+ raise TemplateParserException('Tag missing >')
s = text[i:end+1]
return s
diff --git a/tools/lint-all b/tools/lint-all
index 83500cb9d1..e1ab512c85 100755
--- a/tools/lint-all
+++ b/tools/lint-all
@@ -248,6 +248,9 @@ def build_custom_checkers(by_lang):
# rare; if we find any, they can be added to the exclude list for
# this rule.
{'pattern': '% [a-zA-Z0-9_.]*\)?$',
+ 'exclude_line': set([
+ ('tools/tests/test_template_parser.py', '{% foo'),
+ ]),
'description': 'Used % comprehension without a tuple'},
# To avoid json_error(_variable) and json_error(_(variable))
{'pattern': '\Wjson_error\(_\(?\w+\)',
diff --git a/tools/tests/test_template_parser.py b/tools/tests/test_template_parser.py
index 392c92c675..d63b8caf1e 100644
--- a/tools/tests/test_template_parser.py
+++ b/tools/tests/test_template_parser.py
@@ -6,6 +6,8 @@ import unittest
try:
from tools.lib.template_parser import (
+ TemplateParserException,
+ get_tag_info,
html_tag_tree,
is_django_block_tag,
tokenize,
@@ -16,6 +18,12 @@ except ImportError:
sys.exit(1)
class ParserTest(unittest.TestCase):
+ def _assert_validate_error(self, error, fn=None, text=None, check_indent=True):
+ # See https://github.com/python/typeshed/issues/372
+ # for why we have to ingore types here.
+ with self.assertRaisesRegexp(TemplateParserException, error): # type: ignore
+ validate(fn=fn, text=text, check_indent=check_indent)
+
def test_is_django_block_tag(self):
# type: () -> None
self.assertTrue(is_django_block_tag('block'))
@@ -54,6 +62,71 @@ class ParserTest(unittest.TestCase):
'''
validate(text=my_html)
+ def test_validate_no_start_tag(self):
+ # type: () -> None
+ my_html = '''
+ foo
+ '''
+ self._assert_validate_error('No start tag', text=my_html)
+
+ def test_validate_mismatched_tag(self):
+ # type: () -> None
+ my_html = '''
+ foo
+ '''
+ self._assert_validate_error('Mismatched tag.', text=my_html)
+
+ def test_validate_bad_indentation(self):
+ # type: () -> None
+ my_html = '''
+
+ foo
+
+ '''
+ self._assert_validate_error('Bad indentation.', text=my_html, check_indent=True)
+
+ def test_validate_incomplete_handlebars_tag_1(self):
+ # type: () -> None
+ my_html = '''
+ {{# foo
+ '''
+ self._assert_validate_error('Tag missing }}', text=my_html)
+
+ def test_validate_incomplete_handlebars_tag_2(self):
+ # type: () -> None
+ my_html = '''
+ {{# foo }
+ '''
+ self._assert_validate_error('Tag missing }}', text=my_html)
+
+ def test_validate_incomplete_django_tag_1(self):
+ # type: () -> None
+ my_html = '''
+ {% foo
+ '''
+ self._assert_validate_error('Tag missing %}', text=my_html)
+
+ def test_validate_incomplete_django_tag_2(self):
+ # type: () -> None
+ my_html = '''
+ {% foo %
+ '''
+ self._assert_validate_error('Tag missing %}', text=my_html)
+
+ def test_validate_incomplete_html_tag_1(self):
+ # type: () -> None
+ my_html = '''
+ ', text=my_html)
+
+ def test_validate_incomplete_html_tag_2(self):
+ # type: () -> None
+ my_html = '''
+ foo
+ '''
+
+ start_tag, end_tag = tokenize(html)
+
+ start_tag_info = get_tag_info(start_tag)
+ end_tag_info = get_tag_info(end_tag)
+
+ self.assertEqual(start_tag_info.text(), 'p.test1.test2#test')
+ self.assertEqual(end_tag_info.text(), 'p')
+
def test_html_tag_tree(self):
# type: () -> None
html = '''