| Index: tools/telemetry/third_party/coverage/tests/test_parser.py
|
| diff --git a/tools/telemetry/third_party/coverage/tests/test_parser.py b/tools/telemetry/third_party/coverage/tests/test_parser.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..84b9a214607affa14d22e59d8428425433d5e144
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/coverage/tests/test_parser.py
|
| @@ -0,0 +1,208 @@
|
| +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
| +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
|
| +
|
| +"""Tests for coverage.py's code parsing."""
|
| +
|
| +import textwrap
|
| +
|
| +from tests.coveragetest import CoverageTest
|
| +
|
| +from coverage import env
|
| +from coverage.misc import NotPython
|
| +from coverage.parser import PythonParser
|
| +
|
| +
|
| +class PythonParserTest(CoverageTest):
|
| + """Tests for coverage.py's Python code parsing."""
|
| +
|
| + run_in_temp_dir = False
|
| +
|
| + def parse_source(self, text):
|
| + """Parse `text` as source, and return the `PythonParser` used."""
|
| + if env.PY2:
|
| + text = text.decode("ascii")
|
| + text = textwrap.dedent(text)
|
| + parser = PythonParser(text=text, exclude="nocover")
|
| + parser.parse_source()
|
| + return parser
|
| +
|
| + def test_exit_counts(self):
|
| + parser = self.parse_source("""\
|
| + # check some basic branch counting
|
| + class Foo:
|
| + def foo(self, a):
|
| + if a:
|
| + return 5
|
| + else:
|
| + return 7
|
| +
|
| + class Bar:
|
| + pass
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), {
|
| + 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1
|
| + })
|
| +
|
| + def test_generator_exit_counts(self):
|
| + # https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses-branch-coverage
|
| + parser = self.parse_source("""\
|
| + def gen(input):
|
| + for n in inp:
|
| + yield (i * 2 for i in range(n))
|
| +
|
| + list(gen([1,2,3]))
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), {
|
| + 1:1, # def -> list
|
| + 2:2, # for -> yield; for -> exit
|
| + 3:2, # yield -> for; genexp exit
|
| + 5:1, # list -> exit
|
| + })
|
| +
|
| + def test_try_except(self):
|
| + parser = self.parse_source("""\
|
| + try:
|
| + a = 2
|
| + except ValueError:
|
| + a = 4
|
| + except ZeroDivideError:
|
| + a = 6
|
| + except:
|
| + a = 8
|
| + b = 9
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), {
|
| + 1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1
|
| + })
|
| +
|
| + def test_excluded_classes(self):
|
| + parser = self.parse_source("""\
|
| + class Foo:
|
| + def __init__(self):
|
| + pass
|
| +
|
| + if 0: # nocover
|
| + class Bar:
|
| + pass
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), {
|
| + 1:0, 2:1, 3:1
|
| + })
|
| +
|
| + def test_missing_branch_to_excluded_code(self):
|
| + parser = self.parse_source("""\
|
| + if fooey:
|
| + a = 2
|
| + else: # nocover
|
| + a = 4
|
| + b = 5
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 5:1 })
|
| + parser = self.parse_source("""\
|
| + def foo():
|
| + if fooey:
|
| + a = 3
|
| + else:
|
| + a = 5
|
| + b = 6
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 })
|
| + parser = self.parse_source("""\
|
| + def foo():
|
| + if fooey:
|
| + a = 3
|
| + else: # nocover
|
| + a = 5
|
| + b = 6
|
| + """)
|
| + self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 3:1, 6:1 })
|
| +
|
| + def test_indentation_error(self):
|
| + msg = (
|
| + "Couldn't parse '<code>' as Python source: "
|
| + "'unindent does not match any outer indentation level' at line 3"
|
| + )
|
| + with self.assertRaisesRegex(NotPython, msg):
|
| + _ = self.parse_source("""\
|
| + 0 spaces
|
| + 2
|
| + 1
|
| + """)
|
| +
|
| + def test_token_error(self):
|
| + msg = "Couldn't parse '<code>' as Python source: 'EOF in multi-line string' at line 1"
|
| + with self.assertRaisesRegex(NotPython, msg):
|
| + _ = self.parse_source("""\
|
| + '''
|
| + """)
|
| +
|
| +
|
| +class ParserFileTest(CoverageTest):
|
| + """Tests for coverage.py's code parsing from files."""
|
| +
|
| + def parse_file(self, filename):
|
| + """Parse `text` as source, and return the `PythonParser` used."""
|
| + # pylint: disable=attribute-defined-outside-init
|
| + parser = PythonParser(filename=filename, exclude="nocover")
|
| + self.statements, self.excluded = parser.parse_source()
|
| + return parser
|
| +
|
| + def test_line_endings(self):
|
| + text = """\
|
| + # check some basic branch counting
|
| + class Foo:
|
| + def foo(self, a):
|
| + if a:
|
| + return 5
|
| + else:
|
| + return 7
|
| +
|
| + class Bar:
|
| + pass
|
| + """
|
| + counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 }
|
| + name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r"))
|
| + for fname, newline in name_endings:
|
| + fname = fname + ".py"
|
| + self.make_file(fname, text, newline=newline)
|
| + parser = self.parse_file(fname)
|
| + self.assertEqual(
|
| + parser.exit_counts(),
|
| + counts,
|
| + "Wrong for %r" % fname
|
| + )
|
| +
|
| + def test_encoding(self):
|
| + self.make_file("encoded.py", """\
|
| + coverage = "\xe7\xf6v\xear\xe3g\xe9"
|
| + """)
|
| + parser = self.parse_file("encoded.py")
|
| + self.assertEqual(parser.exit_counts(), {1: 1})
|
| +
|
| + def test_missing_line_ending(self):
|
| + # Test that the set of statements is the same even if a final
|
| + # multi-line statement has no final newline.
|
| + # https://bitbucket.org/ned/coveragepy/issue/293
|
| +
|
| + self.make_file("normal.py", """\
|
| + out, err = subprocess.Popen(
|
| + [sys.executable, '-c', 'pass'],
|
| + stdout=subprocess.PIPE,
|
| + stderr=subprocess.PIPE).communicate()
|
| + """)
|
| +
|
| + self.parse_file("normal.py")
|
| + self.assertEqual(self.statements, set([1]))
|
| +
|
| + self.make_file("abrupt.py", """\
|
| + out, err = subprocess.Popen(
|
| + [sys.executable, '-c', 'pass'],
|
| + stdout=subprocess.PIPE,
|
| + stderr=subprocess.PIPE).communicate()""") # no final newline.
|
| +
|
| + # Double-check that some test helper wasn't being helpful.
|
| + with open("abrupt.py") as f:
|
| + self.assertEqual(f.read()[-1], ")")
|
| +
|
| + self.parse_file("abrupt.py")
|
| + self.assertEqual(self.statements, set([1]))
|
|
|