blob: 867decc4af1aa0754a466dffb7ffebcc3bef4993 [file] [log] [blame]
import re
import unittest
from tools.linter.translate_annotations import parse_annotation, parse_diff, translate
flake8_regex \
= r'^(?P<filename>.*?):(?P<lineNumber>\d+):(?P<columnNumber>\d+): (?P<errorCode>\w+\d+) (?P<errorDesc>.*)'
clang_tidy_regex \
= r'^(?P<filename>.*?):(?P<lineNumber>\d+):(?P<columnNumber>\d+): (?P<errorDesc>.*?) \[(?P<errorCode>.*)\]'
# in the below example patch, note that the filenames differ, so the
# translation should reflect that as well as the line numbers
# $ git clone -b 1.0.2 https://github.com/cscorley/whatthepatch.git
# $ cd whatthepatch/tests/casefiles
# $ git diff --no-index --unified=0 lao tzu
lao_tzu_diff = '''
diff --git a/lao b/tzu
index 635ef2c..5af88a8 100644
--- a/lao
+++ b/tzu
@@ -1,2 +0,0 @@
-The Way that can be told of is not the eternal Way;
-The name that can be named is not the eternal name.
@@ -4 +2,2 @@ The Nameless is the origin of Heaven and Earth;
-The Named is the mother of all things.
+The named is the mother of all things.
+
@@ -11,0 +11,3 @@ But after they are produced,
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
'''.lstrip()
sparser_diff = '''
diff --git a/foo.txt b/bar.txt
index 27a6dad..6fae323 100644
--- a/foo.txt
+++ b/bar.txt
@@ -4,3 +4,2 @@ lines
-lines
-lines
-lines
+A change!!
+Wow
@@ -10,2 +8,0 @@ more lines
-even more
-even more
'''.lstrip()
new_file_diff = '''
diff --git a/torch/csrc/jit/tensorexpr/operators/conv2d.h b/torch/csrc/jit/tensorexpr/operators/conv2d.h
new file mode 100644
index 0000000000..a81eeae346
--- /dev/null
+++ b/torch/csrc/jit/tensorexpr/operators/conv2d.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <torch/csrc/jit/tensorexpr/tensor.h>
+
+namespace torch {
+namespace jit {
+namespace tensorexpr {
+
+TORCH_API Tensor* conv2d_depthwise(
+ BufHandle input,
+ BufHandle weight,
+ BufHandle bias,
+ int stride,
+ int pad,
+ int groups);
+
+} // namespace tensorexpr
+} // namespace jit
+} // namespace torch
'''.lstrip()
# fun fact, this example fools VS Code's diff syntax highlighter
haskell_diff = '''
diff --git a/hello.hs b/hello.hs
index ffb8d4ad14..0872ac9db6 100644
--- a/hello.hs
+++ b/hello.hs
@@ -1 +1 @@
--- a/hello/world/example
+main = putStrLn "Hello, world!"
'''.lstrip()
class TestTranslateAnnotations(unittest.TestCase):
maxDiff = None
def test_parse_diff_lao_tzu(self) -> None:
self.assertEqual(
parse_diff(lao_tzu_diff),
{
'old_filename': 'lao',
'hunks': [
{
'old_start': 1,
'old_count': 2,
'new_start': 0,
'new_count': 0,
},
{
'old_start': 4,
'old_count': 1,
'new_start': 2,
'new_count': 2,
},
{
'old_start': 11,
'old_count': 0,
'new_start': 11,
'new_count': 3,
},
],
},
)
def test_parse_diff_new_file(self) -> None:
self.assertEqual(
parse_diff(new_file_diff),
{
'old_filename': None,
'hunks': [
{
'old_start': 0,
'old_count': 0,
'new_start': 1,
'new_count': 19,
},
],
},
)
def test_parse_diff_haskell(self) -> None:
self.assertEqual(
parse_diff(haskell_diff),
{
'old_filename': 'hello.hs',
'hunks': [
{
'old_start': 1,
'old_count': 1,
'new_start': 1,
'new_count': 1,
},
],
},
)
def test_translate_lao_tzu(self) -> None:
# we'll pretend that this diff represents the file lao being
# renamed to tzu and also modified
diff = parse_diff(lao_tzu_diff)
# line numbers less than 1 are invalid so they map to None
self.assertEqual(translate(diff, -1), None)
self.assertEqual(translate(diff, 0), None)
# the first two lines of the file were removed, so the first
# line of the new version corresponds to the third line of the
# original
self.assertEqual(translate(diff, 1), 3)
# the second and third lines of the new file were not present in
# the original version, so they map to None
self.assertEqual(translate(diff, 2), None)
self.assertEqual(translate(diff, 3), None)
# at this point, we have a stretch of lines that are identical
# in both versions of the file, but the original version of the
# file had 4 lines before this section whereas the new version
# has only 3 lines before this section
self.assertEqual(translate(diff, 4), 5)
self.assertEqual(translate(diff, 5), 6)
self.assertEqual(translate(diff, 6), 7)
self.assertEqual(translate(diff, 7), 8)
self.assertEqual(translate(diff, 8), 9)
self.assertEqual(translate(diff, 9), 10)
self.assertEqual(translate(diff, 10), 11)
# these three lines were added in the new version of the file,
# so they map to None
self.assertEqual(translate(diff, 11), None)
self.assertEqual(translate(diff, 12), None)
self.assertEqual(translate(diff, 13), None)
# the diff doesn't say how long the file is, so we keep mapping
# line numbers back; since we can look back at the original
# files, though, we can see that the original is two lines
# shorter than the new version, which explains why we are
# subtracting 2 here
self.assertEqual(translate(diff, 14), 12)
self.assertEqual(translate(diff, 15), 13)
def test_translate_empty(self) -> None:
diff = parse_diff('--- a/foo')
# again, we start numbering at 1
self.assertEqual(translate(diff, -1), None)
self.assertEqual(translate(diff, 0), None)
# this diff says there are no changes, so all line numbers
# greater than zero map to themselves
self.assertEqual(translate(diff, 1), 1)
self.assertEqual(translate(diff, 2), 2)
self.assertEqual(translate(diff, 3), 3)
self.assertEqual(translate(diff, 4), 4)
self.assertEqual(translate(diff, 5), 5)
def test_translate_sparser(self) -> None:
diff = parse_diff(sparser_diff)
# again, we start numbering at 1
self.assertEqual(translate(diff, -1), None)
self.assertEqual(translate(diff, 0), None)
# the first three lines are unchanged
self.assertEqual(translate(diff, 1), 1)
self.assertEqual(translate(diff, 2), 2)
self.assertEqual(translate(diff, 3), 3)
# we removed three lines here and added two, so the two lines we
# added don't map back to anything in the original file
self.assertEqual(translate(diff, 4), None)
self.assertEqual(translate(diff, 5), None)
# we have some unchanged lines here, but in the preceding hunk
# we removed 3 and added only 2, so we have an offset of 1
self.assertEqual(translate(diff, 6), 7)
self.assertEqual(translate(diff, 7), 8)
# since the unified diff format essentially subtracts 1 from the
# starting line number when the count is 0, and since we use
# bisect.bisect_right to decide which hunk to look at, an
# earlier version of translate had a bug that caused it to get
# confused because it would look at the second hunk (which lists
# 8 as its start line number) rather than the first hunk
self.assertEqual(translate(diff, 8), 9)
# after the two lines that we removed in the second hunk, we've
# reduced the total length of the file by 3 lines, so once we
# reach the end of the diff, we just add 3 to every line number
self.assertEqual(translate(diff, 9), 12)
self.assertEqual(translate(diff, 10), 13)
self.assertEqual(translate(diff, 11), 14)
self.assertEqual(translate(diff, 12), 15)
def test_parse_annotation_flake8(self) -> None:
regex = re.compile(flake8_regex)
self.assertEqual(
parse_annotation(regex, 'README.md:1:3: R100 make a better title'),
{
'filename': 'README.md',
'lineNumber': 1,
'columnNumber': 3,
'errorCode': 'R100',
'errorDesc': 'make a better title',
},
)
def test_parse_annotation_clang_tidy(self) -> None:
regex = re.compile(clang_tidy_regex)
self.assertEqual(
parse_annotation(regex, 'README.md:2:1: improve description [R200]'),
{
'filename': 'README.md',
'lineNumber': 2,
'columnNumber': 1,
'errorCode': 'R200',
'errorDesc': 'improve description',
},
)
if __name__ == '__main__':
unittest.main()