Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1105)

Side by Side Diff: tools/telemetry/third_party/coverage/tests/test_parser.py

Issue 1366913004: Add coverage Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3
4 """Tests for coverage.py's code parsing."""
5
6 import textwrap
7
8 from tests.coveragetest import CoverageTest
9
10 from coverage import env
11 from coverage.misc import NotPython
12 from coverage.parser import PythonParser
13
14
15 class PythonParserTest(CoverageTest):
16 """Tests for coverage.py's Python code parsing."""
17
18 run_in_temp_dir = False
19
20 def parse_source(self, text):
21 """Parse `text` as source, and return the `PythonParser` used."""
22 if env.PY2:
23 text = text.decode("ascii")
24 text = textwrap.dedent(text)
25 parser = PythonParser(text=text, exclude="nocover")
26 parser.parse_source()
27 return parser
28
29 def test_exit_counts(self):
30 parser = self.parse_source("""\
31 # check some basic branch counting
32 class Foo:
33 def foo(self, a):
34 if a:
35 return 5
36 else:
37 return 7
38
39 class Bar:
40 pass
41 """)
42 self.assertEqual(parser.exit_counts(), {
43 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1
44 })
45
46 def test_generator_exit_counts(self):
47 # https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses- branch-coverage
48 parser = self.parse_source("""\
49 def gen(input):
50 for n in inp:
51 yield (i * 2 for i in range(n))
52
53 list(gen([1,2,3]))
54 """)
55 self.assertEqual(parser.exit_counts(), {
56 1:1, # def -> list
57 2:2, # for -> yield; for -> exit
58 3:2, # yield -> for; genexp exit
59 5:1, # list -> exit
60 })
61
62 def test_try_except(self):
63 parser = self.parse_source("""\
64 try:
65 a = 2
66 except ValueError:
67 a = 4
68 except ZeroDivideError:
69 a = 6
70 except:
71 a = 8
72 b = 9
73 """)
74 self.assertEqual(parser.exit_counts(), {
75 1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1
76 })
77
78 def test_excluded_classes(self):
79 parser = self.parse_source("""\
80 class Foo:
81 def __init__(self):
82 pass
83
84 if 0: # nocover
85 class Bar:
86 pass
87 """)
88 self.assertEqual(parser.exit_counts(), {
89 1:0, 2:1, 3:1
90 })
91
92 def test_missing_branch_to_excluded_code(self):
93 parser = self.parse_source("""\
94 if fooey:
95 a = 2
96 else: # nocover
97 a = 4
98 b = 5
99 """)
100 self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 5:1 })
101 parser = self.parse_source("""\
102 def foo():
103 if fooey:
104 a = 3
105 else:
106 a = 5
107 b = 6
108 """)
109 self.assertEqual(parser.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 })
110 parser = self.parse_source("""\
111 def foo():
112 if fooey:
113 a = 3
114 else: # nocover
115 a = 5
116 b = 6
117 """)
118 self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 3:1, 6:1 })
119
120 def test_indentation_error(self):
121 msg = (
122 "Couldn't parse '<code>' as Python source: "
123 "'unindent does not match any outer indentation level' at line 3"
124 )
125 with self.assertRaisesRegex(NotPython, msg):
126 _ = self.parse_source("""\
127 0 spaces
128 2
129 1
130 """)
131
132 def test_token_error(self):
133 msg = "Couldn't parse '<code>' as Python source: 'EOF in multi-line stri ng' at line 1"
134 with self.assertRaisesRegex(NotPython, msg):
135 _ = self.parse_source("""\
136 '''
137 """)
138
139
140 class ParserFileTest(CoverageTest):
141 """Tests for coverage.py's code parsing from files."""
142
143 def parse_file(self, filename):
144 """Parse `text` as source, and return the `PythonParser` used."""
145 # pylint: disable=attribute-defined-outside-init
146 parser = PythonParser(filename=filename, exclude="nocover")
147 self.statements, self.excluded = parser.parse_source()
148 return parser
149
150 def test_line_endings(self):
151 text = """\
152 # check some basic branch counting
153 class Foo:
154 def foo(self, a):
155 if a:
156 return 5
157 else:
158 return 7
159
160 class Bar:
161 pass
162 """
163 counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 }
164 name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r"))
165 for fname, newline in name_endings:
166 fname = fname + ".py"
167 self.make_file(fname, text, newline=newline)
168 parser = self.parse_file(fname)
169 self.assertEqual(
170 parser.exit_counts(),
171 counts,
172 "Wrong for %r" % fname
173 )
174
175 def test_encoding(self):
176 self.make_file("encoded.py", """\
177 coverage = "\xe7\xf6v\xear\xe3g\xe9"
178 """)
179 parser = self.parse_file("encoded.py")
180 self.assertEqual(parser.exit_counts(), {1: 1})
181
182 def test_missing_line_ending(self):
183 # Test that the set of statements is the same even if a final
184 # multi-line statement has no final newline.
185 # https://bitbucket.org/ned/coveragepy/issue/293
186
187 self.make_file("normal.py", """\
188 out, err = subprocess.Popen(
189 [sys.executable, '-c', 'pass'],
190 stdout=subprocess.PIPE,
191 stderr=subprocess.PIPE).communicate()
192 """)
193
194 self.parse_file("normal.py")
195 self.assertEqual(self.statements, set([1]))
196
197 self.make_file("abrupt.py", """\
198 out, err = subprocess.Popen(
199 [sys.executable, '-c', 'pass'],
200 stdout=subprocess.PIPE,
201 stderr=subprocess.PIPE).communicate()""") # no final newline.
202
203 # Double-check that some test helper wasn't being helpful.
204 with open("abrupt.py") as f:
205 self.assertEqual(f.read()[-1], ")")
206
207 self.parse_file("abrupt.py")
208 self.assertEqual(self.statements, set([1]))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698