OLD | NEW |
---|---|
1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
2 # | 2 # |
3 # Copyright 2009, Google Inc. | 3 # Copyright 2009, Google Inc. |
4 # All rights reserved. | 4 # All rights reserved. |
5 # | 5 # |
6 # Redistribution and use in source and binary forms, with or without | 6 # Redistribution and use in source and binary forms, with or without |
7 # modification, are permitted provided that the following conditions are | 7 # modification, are permitted provided that the following conditions are |
8 # met: | 8 # met: |
9 # | 9 # |
10 # * Redistributions of source code must retain the above copyright | 10 # * Redistributions of source code must retain the above copyright |
(...skipping 14 matching lines...) Expand all Loading... | |
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | 31 |
32 """Unit tests for Crocodile.""" | 32 """Unit tests for Crocodile.""" |
33 | 33 |
34 import os | 34 import os |
35 import re | |
36 import sys | |
37 import StringIO | 35 import StringIO |
38 import unittest | 36 import unittest |
39 import croc | 37 import croc |
40 | 38 |
41 #------------------------------------------------------------------------------ | 39 #------------------------------------------------------------------------------ |
42 | 40 |
41 | |
43 class TestCoverageStats(unittest.TestCase): | 42 class TestCoverageStats(unittest.TestCase): |
44 """Tests for croc.CoverageStats.""" | 43 """Tests for croc.CoverageStats.""" |
45 | 44 |
46 def testAdd(self): | 45 def testAdd(self): |
47 """Test Add().""" | 46 """Test Add().""" |
48 c = croc.CoverageStats() | 47 c = croc.CoverageStats() |
49 | 48 |
50 # Initially empty | 49 # Initially empty |
51 self.assertEqual(c, {}) | 50 self.assertEqual(c, {}) |
52 | 51 |
53 # Add items | 52 # Add items |
54 c['a'] = 1 | 53 c['a'] = 1 |
55 c['b'] = 0 | 54 c['b'] = 0 |
56 self.assertEqual(c, {'a':1, 'b':0}) | 55 self.assertEqual(c, {'a': 1, 'b': 0}) |
57 | 56 |
58 # Add dict with non-overlapping items | 57 # Add dict with non-overlapping items |
59 c.Add({'c':5}) | 58 c.Add({'c': 5}) |
60 self.assertEqual(c, {'a':1, 'b':0, 'c':5}) | 59 self.assertEqual(c, {'a': 1, 'b': 0, 'c': 5}) |
61 | 60 |
62 # Add dict with overlapping items | 61 # Add dict with overlapping items |
63 c.Add({'a':4, 'd':3}) | 62 c.Add({'a': 4, 'd': 3}) |
64 self.assertEqual(c, {'a':5, 'b':0, 'c':5, 'd':3}) | 63 self.assertEqual(c, {'a': 5, 'b': 0, 'c': 5, 'd': 3}) |
65 | 64 |
66 #------------------------------------------------------------------------------ | 65 #------------------------------------------------------------------------------ |
67 | 66 |
67 | |
68 class TestCoveredFile(unittest.TestCase): | 68 class TestCoveredFile(unittest.TestCase): |
69 """Tests for croc.CoveredFile.""" | 69 """Tests for croc.CoveredFile.""" |
70 | 70 |
71 def setUp(self): | 71 def setUp(self): |
72 self.cov_file = croc.CoveredFile('bob.cc', 'source', 'C++') | 72 self.cov_file = croc.CoveredFile('bob.cc', group='source', language='C++') |
73 | 73 |
74 def testInit(self): | 74 def testInit(self): |
75 """Test init.""" | 75 """Test init.""" |
76 f = self.cov_file | 76 f = self.cov_file |
77 | 77 |
78 # Check initial values | 78 # Check initial values |
79 self.assertEqual(f.filename, 'bob.cc') | 79 self.assertEqual(f.filename, 'bob.cc') |
80 self.assertEqual(f.group, 'source') | 80 self.assertEqual(f.attrs, {'group': 'source', 'language': 'C++'}) |
81 self.assertEqual(f.language, 'C++') | |
82 self.assertEqual(f.lines, {}) | 81 self.assertEqual(f.lines, {}) |
83 self.assertEqual(f.stats, {}) | 82 self.assertEqual(f.stats, {}) |
83 self.assertEqual(f.local_path, None) | |
84 self.assertEqual(f.in_lcov, False) | |
84 | 85 |
85 def testUpdateCoverageEmpty(self): | 86 def testUpdateCoverageEmpty(self): |
86 """Test updating coverage when empty.""" | 87 """Test updating coverage when empty.""" |
87 f = self.cov_file | 88 f = self.cov_file |
88 f.UpdateCoverage() | 89 f.UpdateCoverage() |
89 self.assertEqual(f.stats, { | 90 self.assertEqual(f.stats, { |
90 'lines_executable':0, | 91 'lines_executable': 0, |
91 'lines_instrumented':0, | 92 'lines_instrumented': 0, |
92 'lines_covered':0, | 93 'lines_covered': 0, |
93 'files_executable':1, | 94 'files_executable': 1, |
94 }) | 95 }) |
95 | 96 |
96 def testUpdateCoverageExeOnly(self): | 97 def testUpdateCoverageExeOnly(self): |
97 """Test updating coverage when no lines are instrumented.""" | 98 """Test updating coverage when no lines are instrumented.""" |
98 f = self.cov_file | 99 f = self.cov_file |
99 f.lines = {1:None, 2:None, 4:None} | 100 f.lines = {1: None, 2: None, 4: None} |
100 f.UpdateCoverage() | 101 f.UpdateCoverage() |
101 self.assertEqual(f.stats, { | 102 self.assertEqual(f.stats, { |
102 'lines_executable':3, | 103 'lines_executable': 3, |
103 'lines_instrumented':0, | 104 'lines_instrumented': 0, |
104 'lines_covered':0, | 105 'lines_covered': 0, |
105 'files_executable':1, | 106 'files_executable': 1, |
107 }) | |
108 | |
109 # Now mark the file instrumented via in_lcov | |
110 f.in_lcov = True | |
111 f.UpdateCoverage() | |
112 self.assertEqual(f.stats, { | |
113 'lines_executable': 3, | |
114 'lines_instrumented': 0, | |
115 'lines_covered': 0, | |
116 'files_executable': 1, | |
117 'files_instrumented': 1, | |
106 }) | 118 }) |
107 | 119 |
108 def testUpdateCoverageExeAndInstr(self): | 120 def testUpdateCoverageExeAndInstr(self): |
109 """Test updating coverage when no lines are covered.""" | 121 """Test updating coverage when no lines are covered.""" |
110 f = self.cov_file | 122 f = self.cov_file |
111 f.lines = {1:None, 2:None, 4:0, 5:0, 7:None} | 123 f.lines = {1: None, 2: None, 4: 0, 5: 0, 7: None} |
112 f.UpdateCoverage() | 124 f.UpdateCoverage() |
113 self.assertEqual(f.stats, { | 125 self.assertEqual(f.stats, { |
114 'lines_executable':5, | 126 'lines_executable': 5, |
115 'lines_instrumented':2, | 127 'lines_instrumented': 2, |
116 'lines_covered':0, | 128 'lines_covered': 0, |
117 'files_executable':1, | 129 'files_executable': 1, |
118 'files_instrumented':1, | 130 'files_instrumented': 1, |
119 }) | 131 }) |
120 | 132 |
121 def testUpdateCoverageWhenCovered(self): | 133 def testUpdateCoverageWhenCovered(self): |
122 """Test updating coverage when lines are covered.""" | 134 """Test updating coverage when lines are covered.""" |
123 f = self.cov_file | 135 f = self.cov_file |
124 f.lines = {1:None, 2:None, 3:1, 4:0, 5:0, 6:1, 7:None} | 136 f.lines = {1: None, 2: None, 3: 1, 4: 0, 5: 0, 6: 1, 7: None} |
125 f.UpdateCoverage() | 137 f.UpdateCoverage() |
126 self.assertEqual(f.stats, { | 138 self.assertEqual(f.stats, { |
127 'lines_executable':7, | 139 'lines_executable': 7, |
128 'lines_instrumented':4, | 140 'lines_instrumented': 4, |
129 'lines_covered':2, | 141 'lines_covered': 2, |
130 'files_executable':1, | 142 'files_executable': 1, |
131 'files_instrumented':1, | 143 'files_instrumented': 1, |
132 'files_covered':1, | 144 'files_covered': 1, |
133 }) | 145 }) |
134 | 146 |
135 #------------------------------------------------------------------------------ | 147 #------------------------------------------------------------------------------ |
136 | 148 |
149 | |
137 class TestCoveredDir(unittest.TestCase): | 150 class TestCoveredDir(unittest.TestCase): |
138 """Tests for croc.CoveredDir.""" | 151 """Tests for croc.CoveredDir.""" |
139 | 152 |
140 def setUp(self): | 153 def setUp(self): |
141 self.cov_dir = croc.CoveredDir('/a/b/c') | 154 self.cov_dir = croc.CoveredDir('/a/b/c') |
142 | 155 |
143 def testInit(self): | 156 def testInit(self): |
144 """Test init.""" | 157 """Test init.""" |
145 d = self.cov_dir | 158 d = self.cov_dir |
146 | 159 |
147 # Check initial values | 160 # Check initial values |
148 self.assertEqual(d.dirpath, '/a/b/c') | 161 self.assertEqual(d.dirpath, '/a/b/c') |
149 self.assertEqual(d.files, {}) | 162 self.assertEqual(d.files, {}) |
150 self.assertEqual(d.subdirs, {}) | 163 self.assertEqual(d.subdirs, {}) |
151 self.assertEqual(d.stats_by_group, {'all':{}}) | 164 self.assertEqual(d.stats_by_group, {'all': {}}) |
152 | 165 |
153 def testGetTreeEmpty(self): | 166 def testGetTreeEmpty(self): |
154 """Test getting empty tree.""" | 167 """Test getting empty tree.""" |
155 d = self.cov_dir | 168 d = self.cov_dir |
156 self.assertEqual(d.GetTree(), '/a/b/c/') | 169 self.assertEqual(d.GetTree(), 'c/') |
157 | 170 |
158 def testGetTreeStats(self): | 171 def testGetTreeStats(self): |
159 """Test getting tree with stats.""" | 172 """Test getting tree with stats.""" |
160 d = self.cov_dir | 173 d = self.cov_dir |
161 d.stats_by_group['all'] = croc.CoverageStats( | 174 d.stats_by_group['all'] = croc.CoverageStats( |
162 lines_executable=50, lines_instrumented=30, lines_covered=20) | 175 lines_executable=50, lines_instrumented=30, lines_covered=20) |
163 d.stats_by_group['bar'] = croc.CoverageStats( | 176 d.stats_by_group['bar'] = croc.CoverageStats( |
164 lines_executable=0, lines_instrumented=0, lines_covered=0) | 177 lines_executable=0, lines_instrumented=0, lines_covered=0) |
165 d.stats_by_group['foo'] = croc.CoverageStats( | 178 d.stats_by_group['foo'] = croc.CoverageStats( |
166 lines_executable=33, lines_instrumented=22, lines_covered=11) | 179 lines_executable=33, lines_instrumented=22, lines_covered=11) |
167 # 'bar' group is skipped because it has no executable lines | 180 # 'bar' group is skipped because it has no executable lines |
168 self.assertEqual(d.GetTree(), | 181 self.assertEqual( |
169 '/a/b/c/ all:20/30/50 foo:11/22/33') | 182 d.GetTree(), |
183 'c/ all:20/30/50 foo:11/22/33') | |
170 | 184 |
171 def testGetTreeSubdir(self): | 185 def testGetTreeSubdir(self): |
172 """Test getting tree with subdirs.""" | 186 """Test getting tree with subdirs.""" |
173 d1 = self.cov_dir = croc.CoveredDir('/a') | 187 d1 = self.cov_dir = croc.CoveredDir('/a') |
174 d2 = self.cov_dir = croc.CoveredDir('/a/b') | 188 d2 = self.cov_dir = croc.CoveredDir('/a/b') |
175 d3 = self.cov_dir = croc.CoveredDir('/a/c') | 189 d3 = self.cov_dir = croc.CoveredDir('/a/c') |
176 d4 = self.cov_dir = croc.CoveredDir('/a/b/d') | 190 d4 = self.cov_dir = croc.CoveredDir('/a/b/d') |
177 d5 = self.cov_dir = croc.CoveredDir('/a/b/e') | 191 d5 = self.cov_dir = croc.CoveredDir('/a/b/e') |
178 d1.subdirs = {'/a/b':d2, '/a/c':d3} | 192 d1.subdirs = {'/a/b': d2, '/a/c': d3} |
179 d2.subdirs = {'/a/b/d':d4, '/a/b/e':d5} | 193 d2.subdirs = {'/a/b/d': d4, '/a/b/e': d5} |
180 self.assertEqual(d1.GetTree(), | 194 self.assertEqual(d1.GetTree(), 'a/\n b/\n d/\n e/\n c/') |
181 '/a/\n /a/b/\n /a/b/d/\n /a/b/e/\n /a/c/') | |
182 | 195 |
183 #------------------------------------------------------------------------------ | 196 #------------------------------------------------------------------------------ |
184 | 197 |
198 | |
185 class TestCoverage(unittest.TestCase): | 199 class TestCoverage(unittest.TestCase): |
186 """Tests for croc.Coverage.""" | 200 """Tests for croc.Coverage.""" |
187 | 201 |
188 def MockWalk(self, src_dir): | 202 def MockWalk(self, src_dir): |
189 """Mock for os.walk(). | 203 """Mock for os.walk(). |
190 | 204 |
191 Args: | 205 Args: |
192 src_dir: Source directory to walk. | 206 src_dir: Source directory to walk. |
193 | 207 |
194 Returns: | 208 Returns: |
195 A list of (dirpath, dirnames, filenames) tuples. | 209 A list of (dirpath, dirnames, filenames) tuples. |
196 """ | 210 """ |
197 self.mock_walk_calls.append(src_dir) | 211 self.mock_walk_calls.append(src_dir) |
198 return self.mock_walk_return | 212 return self.mock_walk_return |
199 | 213 |
214 def MockScanFile(self, filename, language): | |
215 """Mock for croc_scan.ScanFile(). | |
216 | |
217 Args: | |
218 filename: Path to file to scan. | |
219 language: Language for file. | |
220 | |
221 Returns: | |
222 A list of executable lines. | |
223 """ | |
224 self.mock_scan_calls.append([filename, language]) | |
225 if filename in self.mock_scan_return: | |
226 return self.mock_scan_return[filename] | |
227 else: | |
228 return self.mock_scan_return['default'] | |
229 | |
200 def setUp(self): | 230 def setUp(self): |
201 """Per-test setup""" | 231 """Per-test setup.""" |
202 | 232 |
203 # Empty coverage object | 233 # Empty coverage object |
204 self.cov = croc.Coverage() | 234 self.cov = croc.Coverage() |
205 | 235 |
206 # Coverage object with minimal setup | 236 # Coverage object with minimal setup |
207 self.cov_minimal = croc.Coverage() | 237 self.cov_minimal = croc.Coverage() |
208 self.cov_minimal.AddRoot('/src') | 238 self.cov_minimal.AddRoot('/src') |
209 self.cov_minimal.AddRoot('c:\\source') | 239 self.cov_minimal.AddRoot('c:\\source') |
210 self.cov_minimal.AddRule('^#/', include=1, group='my') | 240 self.cov_minimal.AddRule('^_/', include=1, group='my') |
211 self.cov_minimal.AddRule('.*\\.c$', language='C') | 241 self.cov_minimal.AddRule('.*\\.c$', language='C') |
212 self.cov_minimal.AddRule('.*\\.c##$', language='C##') # sharper than thou | 242 self.cov_minimal.AddRule('.*\\.c##$', language='C##') # sharper than thou |
213 | 243 |
214 # Data for MockWalk() | 244 # Data for MockWalk() |
215 self.mock_walk_calls = [] | 245 self.mock_walk_calls = [] |
216 self.mock_walk_return = [] | 246 self.mock_walk_return = [] |
217 | 247 |
248 # Data for MockScanFile() | |
249 self.mock_scan_calls = [] | |
250 self.mock_scan_return = {'default': [1]} | |
251 | |
218 def testInit(self): | 252 def testInit(self): |
219 """Test init.""" | 253 """Test init.""" |
220 c = self.cov | 254 c = self.cov |
221 self.assertEqual(c.files, {}) | 255 self.assertEqual(c.files, {}) |
222 self.assertEqual(c.root_dirs, []) | 256 self.assertEqual(c.root_dirs, []) |
223 self.assertEqual(c.print_stats, []) | 257 self.assertEqual(c.print_stats, []) |
224 | 258 self.assertEqual(c.rules, []) |
225 # Check for the initial subdir rule | |
226 self.assertEqual(len(c.rules), 1) | |
227 r0 = c.rules[0] | |
228 self.assertEqual(r0[0].pattern, '.*/$') | |
229 self.assertEqual(r0[1:], [None, None, 'subdir']) | |
230 | 259 |
231 def testAddRoot(self): | 260 def testAddRoot(self): |
232 """Test AddRoot() and CleanupFilename().""" | 261 """Test AddRoot() and CleanupFilename().""" |
233 c = self.cov | 262 c = self.cov |
234 | 263 |
235 # Check for identity on already-clean filenames | 264 # Check for identity on already-clean filenames |
236 self.assertEqual(c.CleanupFilename(''), '') | 265 self.assertEqual(c.CleanupFilename(''), '') |
237 self.assertEqual(c.CleanupFilename('a'), 'a') | 266 self.assertEqual(c.CleanupFilename('a'), 'a') |
238 self.assertEqual(c.CleanupFilename('.a'), '.a') | 267 self.assertEqual(c.CleanupFilename('.a'), '.a') |
239 self.assertEqual(c.CleanupFilename('..a'), '..a') | 268 self.assertEqual(c.CleanupFilename('..a'), '..a') |
240 self.assertEqual(c.CleanupFilename('a.b'), 'a.b') | 269 self.assertEqual(c.CleanupFilename('a.b'), 'a.b') |
241 self.assertEqual(c.CleanupFilename('a/b/c'), 'a/b/c') | 270 self.assertEqual(c.CleanupFilename('a/b/c'), 'a/b/c') |
242 self.assertEqual(c.CleanupFilename('a/b/c/'), 'a/b/c/') | 271 self.assertEqual(c.CleanupFilename('a/b/c/'), 'a/b/c/') |
243 | 272 |
244 # Backslash to forward slash | 273 # Backslash to forward slash |
245 self.assertEqual(c.CleanupFilename('a\\b\\c'), 'a/b/c') | 274 self.assertEqual(c.CleanupFilename('a\\b\\c'), 'a/b/c') |
246 | 275 |
247 # Handle relative paths | 276 # Handle relative paths |
248 self.assertEqual(c.CleanupFilename('.'), | 277 self.assertEqual(c.CleanupFilename('.'), |
249 c.CleanupFilename(os.path.abspath('.'))) | 278 c.CleanupFilename(os.path.abspath('.'))) |
250 self.assertEqual(c.CleanupFilename('..'), | 279 self.assertEqual(c.CleanupFilename('..'), |
251 c.CleanupFilename(os.path.abspath('..'))) | 280 c.CleanupFilename(os.path.abspath('..'))) |
252 self.assertEqual(c.CleanupFilename('./foo/bar'), | 281 self.assertEqual(c.CleanupFilename('./foo/bar'), |
253 c.CleanupFilename(os.path.abspath('./foo/bar'))) | 282 c.CleanupFilename(os.path.abspath('./foo/bar'))) |
254 self.assertEqual(c.CleanupFilename('../../a/b/c'), | 283 self.assertEqual(c.CleanupFilename('../../a/b/c'), |
255 c.CleanupFilename(os.path.abspath('../../a/b/c'))) | 284 c.CleanupFilename(os.path.abspath('../../a/b/c'))) |
256 | 285 |
257 # Replace alt roots | 286 # Replace alt roots |
258 c.AddRoot('foo', '#') | 287 c.AddRoot('foo') |
259 self.assertEqual(c.CleanupFilename('foo'), '#') | 288 self.assertEqual(c.CleanupFilename('foo'), '_') |
260 self.assertEqual(c.CleanupFilename('foo/bar/baz'), '#/bar/baz') | 289 self.assertEqual(c.CleanupFilename('foo/bar/baz'), '_/bar/baz') |
261 self.assertEqual(c.CleanupFilename('aaa/foo'), 'aaa/foo') | 290 self.assertEqual(c.CleanupFilename('aaa/foo'), 'aaa/foo') |
262 | 291 |
263 # Alt root replacement is applied for all roots | 292 # Alt root replacement is applied for all roots |
264 c.AddRoot('foo/bar', '#B') | 293 c.AddRoot('foo/bar', '_B') |
265 self.assertEqual(c.CleanupFilename('foo/bar/baz'), '#B/baz') | 294 self.assertEqual(c.CleanupFilename('foo/bar/baz'), '_B/baz') |
266 | 295 |
267 # Can use previously defined roots in cleanup | 296 # Can use previously defined roots in cleanup |
268 c.AddRoot('#/nom/nom/nom', '#CANHAS') | 297 c.AddRoot('_/nom/nom/nom', '_CANHAS') |
269 self.assertEqual(c.CleanupFilename('foo/nom/nom/nom/cheezburger'), | 298 self.assertEqual(c.CleanupFilename('foo/nom/nom/nom/cheezburger'), |
270 '#CANHAS/cheezburger') | 299 '_CANHAS/cheezburger') |
271 | 300 |
272 # Verify roots starting with UNC paths or drive letters work, and that | 301 # Verify roots starting with UNC paths or drive letters work, and that |
273 # more than one root can point to the same alt_name | 302 # more than one root can point to the same alt_name |
274 c.AddRoot('/usr/local/foo', '#FOO') | 303 c.AddRoot('/usr/local/foo', '_FOO') |
275 c.AddRoot('D:\\my\\foo', '#FOO') | 304 c.AddRoot('D:\\my\\foo', '_FOO') |
276 self.assertEqual(c.CleanupFilename('/usr/local/foo/a/b'), '#FOO/a/b') | 305 self.assertEqual(c.CleanupFilename('/usr/local/foo/a/b'), '_FOO/a/b') |
277 self.assertEqual(c.CleanupFilename('D:\\my\\foo\\c\\d'), '#FOO/c/d') | 306 self.assertEqual(c.CleanupFilename('D:\\my\\foo\\c\\d'), '_FOO/c/d') |
307 | |
308 # Cannot specify a blank alt_name | |
309 self.assertRaises(ValueError, c.AddRoot, 'some_dir', '') | |
278 | 310 |
279 def testAddRule(self): | 311 def testAddRule(self): |
280 """Test AddRule() and ClassifyFile().""" | 312 """Test AddRule() and ClassifyFile().""" |
281 c = self.cov | 313 c = self.cov |
282 | 314 |
283 # With only the default rule, nothing gets kept | 315 # With only the default rule, nothing gets kept |
284 self.assertEqual(c.ClassifyFile('#/src/'), (None, None)) | 316 self.assertEqual(c.ClassifyFile('_/src/'), {}) |
285 self.assertEqual(c.ClassifyFile('#/src/a.c'), (None, None)) | 317 self.assertEqual(c.ClassifyFile('_/src/a.c'), {}) |
286 | 318 |
287 # Add rules to include a tree and set a default group | 319 # Add rules to include a tree and set a default group |
288 c.AddRule('^#/src/', include=1, group='source') | 320 c.AddRule('^_/src/', include=1, group='source') |
289 # Now the subdir matches, but source doesn't, since no languages are | 321 self.assertEqual(c.ClassifyFile('_/src/'), |
290 # defined yet | 322 {'include': 1, 'group': 'source'}) |
291 self.assertEqual(c.ClassifyFile('#/src/'), ('source', 'subdir')) | 323 self.assertEqual(c.ClassifyFile('_/notsrc/'), {}) |
292 self.assertEqual(c.ClassifyFile('#/notsrc/'), (None, None)) | 324 self.assertEqual(c.ClassifyFile('_/src/a.c'), |
293 self.assertEqual(c.ClassifyFile('#/src/a.c'), (None, None)) | 325 {'include': 1, 'group': 'source'}) |
294 | 326 |
295 # Define some languages and groups | 327 # Define some languages and groups |
296 c.AddRule('.*\\.(c|h)$', language='C') | 328 c.AddRule('.*\\.(c|h)$', language='C') |
297 c.AddRule('.*\\.py$', language='Python') | 329 c.AddRule('.*\\.py$', language='Python') |
298 c.AddRule('.*_test\\.', group='test') | 330 c.AddRule('.*_test\\.', group='test') |
299 self.assertEqual(c.ClassifyFile('#/src/a.c'), ('source', 'C')) | 331 self.assertEqual(c.ClassifyFile('_/src/a.c'), |
300 self.assertEqual(c.ClassifyFile('#/src/a.h'), ('source', 'C')) | 332 {'include': 1, 'group': 'source', 'language': 'C'}) |
301 self.assertEqual(c.ClassifyFile('#/src/a.cpp'), (None, None)) | 333 self.assertEqual(c.ClassifyFile('_/src/a.h'), |
302 self.assertEqual(c.ClassifyFile('#/src/a_test.c'), ('test', 'C')) | 334 {'include': 1, 'group': 'source', 'language': 'C'}) |
303 self.assertEqual(c.ClassifyFile('#/src/test_a.c'), ('source', 'C')) | 335 self.assertEqual(c.ClassifyFile('_/src/a.cpp'), |
304 self.assertEqual(c.ClassifyFile('#/src/foo/bar.py'), ('source', 'Python')) | 336 {'include': 1, 'group': 'source'}) |
305 self.assertEqual(c.ClassifyFile('#/src/test.py'), ('source', 'Python')) | 337 self.assertEqual(c.ClassifyFile('_/src/a_test.c'), |
338 {'include': 1, 'group': 'test', 'language': 'C'}) | |
339 self.assertEqual(c.ClassifyFile('_/src/test_a.c'), | |
340 {'include': 1, 'group': 'source', 'language': 'C'}) | |
341 self.assertEqual(c.ClassifyFile('_/src/foo/bar.py'), | |
342 {'include': 1, 'group': 'source', 'language': 'Python'}) | |
343 self.assertEqual(c.ClassifyFile('_/src/test.py'), | |
344 {'include': 1, 'group': 'source', 'language': 'Python'}) | |
306 | 345 |
307 # Exclude a path (for example, anything in a build output dir) | 346 # Exclude a path (for example, anything in a build output dir) |
308 c.AddRule('.*/build/', include=0) | 347 c.AddRule('.*/build/', include=0) |
309 # But add back in a dir which matched the above rule but isn't a build | 348 # But add back in a dir which matched the above rule but isn't a build |
310 # output dir | 349 # output dir |
311 c.AddRule('#/src/tools/build/', include=1) | 350 c.AddRule('_/src/tools/build/', include=1) |
312 self.assertEqual(c.ClassifyFile('#/src/build.c'), ('source', 'C')) | 351 self.assertEqual(c.ClassifyFile('_/src/build.c').get('include'), 1) |
313 self.assertEqual(c.ClassifyFile('#/src/build/'), (None, None)) | 352 self.assertEqual(c.ClassifyFile('_/src/build/').get('include'), 0) |
314 self.assertEqual(c.ClassifyFile('#/src/build/a.c'), (None, None)) | 353 self.assertEqual(c.ClassifyFile('_/src/build/a.c').get('include'), 0) |
315 self.assertEqual(c.ClassifyFile('#/src/tools/build/'), ('source', 'subdir')) | 354 self.assertEqual(c.ClassifyFile('_/src/tools/build/').get('include'), 1) |
316 self.assertEqual(c.ClassifyFile('#/src/tools/build/t.c'), ('source', 'C')) | 355 self.assertEqual(c.ClassifyFile('_/src/tools/build/t.c').get('include'), 1) |
317 | 356 |
318 def testGetCoveredFile(self): | 357 def testGetCoveredFile(self): |
319 """Test GetCoveredFile().""" | 358 """Test GetCoveredFile().""" |
320 c = self.cov_minimal | 359 c = self.cov_minimal |
321 | 360 |
322 # Not currently any covered files | 361 # Not currently any covered files |
323 self.assertEqual(c.GetCoveredFile('#/a.c'), None) | 362 self.assertEqual(c.GetCoveredFile('_/a.c'), None) |
324 | 363 |
325 # Add some files | 364 # Add some files |
326 a_c = c.GetCoveredFile('#/a.c', add=True) | 365 a_c = c.GetCoveredFile('_/a.c', add=True) |
327 b_c = c.GetCoveredFile('#/b.c##', add=True) | 366 b_c = c.GetCoveredFile('_/b.c##', add=True) |
328 self.assertEqual(a_c.filename, '#/a.c') | 367 self.assertEqual(a_c.filename, '_/a.c') |
329 self.assertEqual(a_c.group, 'my') | 368 self.assertEqual(a_c.attrs, {'include': 1, 'group': 'my', 'language': 'C'}) |
330 self.assertEqual(a_c.language, 'C') | 369 self.assertEqual(b_c.filename, '_/b.c##') |
331 self.assertEqual(b_c.filename, '#/b.c##') | 370 self.assertEqual(b_c.attrs, |
332 self.assertEqual(b_c.group, 'my') | 371 {'include': 1, 'group': 'my', 'language': 'C##'}) |
333 self.assertEqual(b_c.language, 'C##') | |
334 | 372 |
335 # Specifying the same filename should return the existing object | 373 # Specifying the same filename should return the existing object |
336 self.assertEqual(c.GetCoveredFile('#/a.c'), a_c) | 374 self.assertEqual(c.GetCoveredFile('_/a.c'), a_c) |
337 self.assertEqual(c.GetCoveredFile('#/a.c', add=True), a_c) | 375 self.assertEqual(c.GetCoveredFile('_/a.c', add=True), a_c) |
338 | 376 |
339 # Filenames get cleaned on the way in, as do root paths | 377 # Filenames get cleaned on the way in, as do root paths |
340 self.assertEqual(c.GetCoveredFile('/src/a.c'), a_c) | 378 self.assertEqual(c.GetCoveredFile('/src/a.c'), a_c) |
341 self.assertEqual(c.GetCoveredFile('c:\\source\\a.c'), a_c) | 379 self.assertEqual(c.GetCoveredFile('c:\\source\\a.c'), a_c) |
342 | 380 |
381 # TODO: Make sure that covered files require language, group, and include | |
382 # (since that checking is now done in GetCoveredFile() rather than | |
383 # ClassifyFile()) | |
384 | |
385 def testRemoveCoveredFile(self): | |
386 """Test RemoveCoveredFile().""" | |
387 # TODO: TEST ME! | |
388 | |
343 def testParseLcov(self): | 389 def testParseLcov(self): |
344 """Test ParseLcovData().""" | 390 """Test ParseLcovData().""" |
345 c = self.cov_minimal | 391 c = self.cov_minimal |
346 | 392 |
347 c.ParseLcovData([ | 393 c.ParseLcovData([ |
348 '# Ignore unknown lines', | 394 '# Ignore unknown lines', |
349 # File we should include' | 395 # File we should include' |
350 'SF:/src/a.c', | 396 'SF:/src/a.c', |
351 'DA:10,1', | 397 'DA:10,1', |
352 'DA:11,0', | 398 'DA:11,0', |
353 'DA:12,1 \n', # Trailing whitespace should get stripped | 399 'DA:12,1 \n', # Trailing whitespace should get stripped |
354 'end_of_record', | 400 'end_of_record', |
355 # File we should ignore | 401 # File we should ignore |
356 'SF:/not_src/a.c', | 402 'SF:/not_src/a.c', |
357 'DA:20,1', | 403 'DA:20,1', |
358 'end_of_record', | 404 'end_of_record', |
359 # Same as first source file, but alternate root | 405 # Same as first source file, but alternate root |
360 'SF:c:\\source\\a.c', | 406 'SF:c:\\source\\a.c', |
361 'DA:30,1', | 407 'DA:30,1', |
362 'end_of_record', | 408 'end_of_record', |
363 # Ignore extra end of record | 409 # Ignore extra end of record |
364 'end_of_record', | 410 'end_of_record', |
365 # Ignore data points after end of record | 411 # Ignore data points after end of record |
366 'DA:40,1', | 412 'DA:40,1', |
367 # Instrumented but uncovered file | 413 # Instrumented but uncovered file |
368 'SF:/src/b.c', | 414 'SF:/src/b.c', |
369 'DA:50,0', | 415 'DA:50,0', |
370 'end_of_record', | 416 'end_of_record', |
417 # Empty file (instrumented but no executable lines) | |
418 'SF:c:\\source\\c.c', | |
bradn
2009/05/28 23:57:36
Does this test work on non-windows?
Randall Spangler
2009/05/29 00:02:57
Yep.
| |
419 'end_of_record', | |
371 ]) | 420 ]) |
372 | 421 |
373 # We should know about two files | 422 # We should know about three files |
374 self.assertEqual(sorted(c.files), ['#/a.c', '#/b.c']) | 423 self.assertEqual(sorted(c.files), ['_/a.c', '_/b.c', '_/c.c']) |
375 | 424 |
376 # Check expected contents | 425 # Check expected contents |
377 a_c = c.GetCoveredFile('#/a.c') | 426 a_c = c.GetCoveredFile('_/a.c') |
378 self.assertEqual(a_c.lines, {10: 1, 11: 0, 12: 1, 30: 1}) | 427 self.assertEqual(a_c.lines, {10: 1, 11: 0, 12: 1, 30: 1}) |
379 self.assertEqual(a_c.stats, { | 428 self.assertEqual(a_c.stats, { |
380 'files_executable': 1, | 429 'files_executable': 1, |
381 'files_instrumented': 1, | 430 'files_instrumented': 1, |
382 'files_covered': 1, | 431 'files_covered': 1, |
383 'lines_instrumented': 4, | 432 'lines_instrumented': 4, |
384 'lines_executable': 4, | 433 'lines_executable': 4, |
385 'lines_covered': 3, | 434 'lines_covered': 3, |
386 }) | 435 }) |
387 b_c = c.GetCoveredFile('#/b.c') | 436 self.assertEqual(a_c.in_lcov, True) |
437 | |
438 b_c = c.GetCoveredFile('_/b.c') | |
388 self.assertEqual(b_c.lines, {50: 0}) | 439 self.assertEqual(b_c.lines, {50: 0}) |
389 self.assertEqual(b_c.stats, { | 440 self.assertEqual(b_c.stats, { |
390 'files_executable': 1, | 441 'files_executable': 1, |
391 'files_instrumented': 1, | 442 'files_instrumented': 1, |
392 'lines_instrumented': 1, | 443 'lines_instrumented': 1, |
393 'lines_executable': 1, | 444 'lines_executable': 1, |
394 'lines_covered': 0, | 445 'lines_covered': 0, |
395 }) | 446 }) |
447 self.assertEqual(b_c.in_lcov, True) | |
448 | |
449 c_c = c.GetCoveredFile('_/c.c') | |
450 self.assertEqual(c_c.lines, {}) | |
451 self.assertEqual(c_c.stats, { | |
452 'files_executable': 1, | |
453 'files_instrumented': 1, | |
454 'lines_instrumented': 0, | |
455 'lines_executable': 0, | |
456 'lines_covered': 0, | |
457 }) | |
458 self.assertEqual(c_c.in_lcov, True) | |
459 | |
460 # TODO: Test that files are marked as instrumented if they come from lcov, | |
461 # even if they don't have any instrumented lines. (and that in_lcov is set | |
462 # for those files - probably should set that via some method rather than | |
463 # directly...) | |
396 | 464 |
397 def testGetStat(self): | 465 def testGetStat(self): |
398 """Test GetStat() and PrintStat().""" | 466 """Test GetStat() and PrintStat().""" |
399 c = self.cov | 467 c = self.cov |
400 | 468 |
401 # Add some stats, so there's something to report | 469 # Add some stats, so there's something to report |
402 c.tree.stats_by_group = { | 470 c.tree.stats_by_group = { |
403 'all': { | 471 'all': { |
404 'count_a': 10, | 472 'count_a': 10, |
405 'count_b': 4, | 473 'count_b': 4, |
406 'foo': 'bar', | 474 'foo': 'bar', |
407 }, | 475 }, |
408 'tests': { | 476 'tests': { |
409 'count_a': 2, | 477 'count_a': 2, |
410 'count_b': 5, | 478 'count_b': 5, |
411 'baz': 'bob', | 479 'baz': 'bob', |
412 }, | 480 }, |
413 } | 481 } |
414 | 482 |
415 # Test missing stats and groups | 483 # Test missing stats and groups |
416 self.assertRaises(croc.CoverageStatError, c.GetStat, 'nosuch') | 484 self.assertRaises(croc.CrocStatError, c.GetStat, 'nosuch') |
417 self.assertRaises(croc.CoverageStatError, c.GetStat, 'baz') | 485 self.assertRaises(croc.CrocStatError, c.GetStat, 'baz') |
418 self.assertRaises(croc.CoverageStatError, c.GetStat, 'foo', group='tests') | 486 self.assertRaises(croc.CrocStatError, c.GetStat, 'foo', group='tests') |
419 self.assertRaises(croc.CoverageStatError, c.GetStat, 'foo', group='nosuch') | 487 self.assertRaises(croc.CrocStatError, c.GetStat, 'foo', group='nosuch') |
420 | 488 |
421 # Test returning defaults | 489 # Test returning defaults |
422 self.assertEqual(c.GetStat('nosuch', default=13), 13) | 490 self.assertEqual(c.GetStat('nosuch', default=13), 13) |
423 self.assertEqual(c.GetStat('baz', default='aaa'), 'aaa') | 491 self.assertEqual(c.GetStat('baz', default='aaa'), 'aaa') |
424 self.assertEqual(c.GetStat('foo', group='tests', default=0), 0) | 492 self.assertEqual(c.GetStat('foo', group='tests', default=0), 0) |
425 self.assertEqual(c.GetStat('foo', group='nosuch', default=''), '') | 493 self.assertEqual(c.GetStat('foo', group='nosuch', default=''), '') |
426 | 494 |
427 # Test getting stats | 495 # Test getting stats |
428 self.assertEqual(c.GetStat('count_a'), 10) | 496 self.assertEqual(c.GetStat('count_a'), 10) |
429 self.assertEqual(c.GetStat('count_a', group='tests'), 2) | 497 self.assertEqual(c.GetStat('count_a', group='tests'), 2) |
430 self.assertEqual(c.GetStat('foo', default='baz'), 'bar') | 498 self.assertEqual(c.GetStat('foo', default='baz'), 'bar') |
431 | 499 |
432 # Test stat math (eval) | 500 # Test stat math (eval) |
433 self.assertEqual(c.GetStat('count_a - count_b'), 6) | 501 self.assertEqual(c.GetStat('count_a - count_b'), 6) |
434 self.assertEqual(c.GetStat('100.0 * count_a / count_b', group='tests'), | 502 self.assertEqual(c.GetStat('100.0 * count_a / count_b', group='tests'), |
435 40.0) | 503 40.0) |
436 # Should catch eval errors | 504 # Should catch eval errors |
437 self.assertRaises(croc.CoverageStatError, c.GetStat, '100 / 0') | 505 self.assertRaises(croc.CrocStatError, c.GetStat, '100 / 0') |
438 self.assertRaises(croc.CoverageStatError, c.GetStat, 'count_a -') | 506 self.assertRaises(croc.CrocStatError, c.GetStat, 'count_a -') |
439 | 507 |
440 # Test nested stats via S() | 508 # Test nested stats via S() |
441 self.assertEqual(c.GetStat('count_a - S("count_a", group="tests")'), 8) | 509 self.assertEqual(c.GetStat('count_a - S("count_a", group="tests")'), 8) |
442 self.assertRaises(croc.CoverageStatError, c.GetStat, 'S()') | 510 self.assertRaises(croc.CrocStatError, c.GetStat, 'S()') |
443 self.assertRaises(croc.CoverageStatError, c.GetStat, 'S("nosuch")') | 511 self.assertRaises(croc.CrocStatError, c.GetStat, 'S("nosuch")') |
444 | 512 |
445 # Test PrintStat() | 513 # Test PrintStat() |
446 # We won't see the first print, but at least verify it doesn't assert | 514 # We won't see the first print, but at least verify it doesn't assert |
447 c.PrintStat('count_a', format='(test to stdout: %s)') | 515 c.PrintStat('count_a', format='(test to stdout: %s)') |
448 # Send subsequent prints to a file | 516 # Send subsequent prints to a file |
449 f = StringIO.StringIO() | 517 f = StringIO.StringIO() |
450 c.PrintStat('count_b', outfile=f) | 518 c.PrintStat('count_b', outfile=f) |
451 # Test specifying output format | 519 # Test specifying output format |
452 c.PrintStat('count_a', format='Count A = %05d', outfile=f) | 520 c.PrintStat('count_a', format='Count A = %05d', outfile=f) |
453 # Test specifing additional keyword args | 521 # Test specifing additional keyword args |
(...skipping 15 matching lines...) Expand all Loading... | |
469 | 537 |
470 def testAddConfig(self): | 538 def testAddConfig(self): |
471 """Test AddConfig().""" | 539 """Test AddConfig().""" |
472 c = self.cov | 540 c = self.cov |
473 lcov_queue = [] | 541 lcov_queue = [] |
474 addfiles_queue = [] | 542 addfiles_queue = [] |
475 | 543 |
476 c.AddConfig("""{ | 544 c.AddConfig("""{ |
477 'roots' : [ | 545 'roots' : [ |
478 {'root' : '/foo'}, | 546 {'root' : '/foo'}, |
479 {'root' : '/bar', 'altname' : '#BAR'}, | 547 {'root' : '/bar', 'altname' : 'BAR'}, |
480 ], | 548 ], |
481 'rules' : [ | 549 'rules' : [ |
482 {'regexp' : '^#', 'group' : 'apple'}, | 550 {'regexp' : '^_/', 'group' : 'apple'}, |
483 {'regexp' : 're2', 'include' : 1, 'language' : 'elvish'}, | 551 {'regexp' : 're2', 'include' : 1, 'language' : 'elvish'}, |
484 ], | 552 ], |
485 'lcov_files' : ['a.lcov', 'b.lcov'], | 553 'lcov_files' : ['a.lcov', 'b.lcov'], |
486 'add_files' : ['/src', '#BAR/doo'], | 554 'add_files' : ['/src', 'BAR/doo'], |
487 'print_stats' : [ | 555 'print_stats' : [ |
488 {'stat' : 'count_a'}, | 556 {'stat' : 'count_a'}, |
489 {'stat' : 'count_b', 'group' : 'tests'}, | 557 {'stat' : 'count_b', 'group' : 'tests'}, |
490 ], | 558 ], |
491 'extra_key' : 'is ignored', | 559 'extra_key' : 'is ignored', |
492 }""", lcov_queue=lcov_queue, addfiles_queue=addfiles_queue) | 560 }""", lcov_queue=lcov_queue, addfiles_queue=addfiles_queue) |
493 | 561 |
494 self.assertEqual(lcov_queue, ['a.lcov', 'b.lcov']) | 562 self.assertEqual(lcov_queue, ['a.lcov', 'b.lcov']) |
495 self.assertEqual(addfiles_queue, ['/src', '#BAR/doo']) | 563 self.assertEqual(addfiles_queue, ['/src', 'BAR/doo']) |
496 self.assertEqual(c.root_dirs, [['/foo', '#'], ['/bar', '#BAR']]) | 564 self.assertEqual(c.root_dirs, [['/foo', '_'], ['/bar', 'BAR']]) |
497 self.assertEqual(c.print_stats, [ | 565 self.assertEqual(c.print_stats, [ |
498 {'stat': 'count_a'}, | 566 {'stat': 'count_a'}, |
499 {'stat': 'count_b', 'group': 'tests'}, | 567 {'stat': 'count_b', 'group': 'tests'}, |
500 ]) | 568 ]) |
501 # Convert compiled re's back to patterns for comparison | 569 # Convert compiled re's back to patterns for comparison |
502 rules = [[r[0].pattern] + r[1:] for r in c.rules] | 570 rules = [[r[0].pattern] + r[1:] for r in c.rules] |
503 self.assertEqual(rules, [ | 571 self.assertEqual(rules, [ |
504 ['.*/$', None, None, 'subdir'], | 572 ['^_/', {'group': 'apple'}], |
505 ['^#', None, 'apple', None], | 573 ['re2', {'include': 1, 'language': 'elvish'}], |
506 ['re2', 1, None, 'elvish'], | |
507 ]) | 574 ]) |
508 | 575 |
509 def testAddFilesSimple(self): | 576 def testAddFilesSimple(self): |
510 """Test AddFiles() simple call.""" | 577 """Test AddFiles() simple call.""" |
511 c = self.cov_minimal | 578 c = self.cov_minimal |
512 c.add_files_walk = self.MockWalk | 579 c.add_files_walk = self.MockWalk |
580 c.scan_file = self.MockScanFile | |
581 | |
513 c.AddFiles('/a/b/c') | 582 c.AddFiles('/a/b/c') |
514 self.assertEqual(self.mock_walk_calls, ['/a/b/c']) | 583 self.assertEqual(self.mock_walk_calls, ['/a/b/c']) |
584 self.assertEqual(self.mock_scan_calls, []) | |
515 self.assertEqual(c.files, {}) | 585 self.assertEqual(c.files, {}) |
516 | 586 |
517 def testAddFilesRootMap(self): | 587 def testAddFilesRootMap(self): |
518 """Test AddFiles() with root mappings.""" | 588 """Test AddFiles() with root mappings.""" |
519 c = self.cov_minimal | 589 c = self.cov_minimal |
520 c.add_files_walk = self.MockWalk | 590 c.add_files_walk = self.MockWalk |
521 c.AddRoot('#/subdir', '#SUBDIR') | 591 c.scan_file = self.MockScanFile |
522 | 592 |
523 # AddFiles() should replace the '#SUBDIR' alt_name, then match both | 593 c.AddRoot('_/subdir', 'SUBDIR') |
524 # possible roots for the '#' alt_name. | 594 |
525 c.AddFiles('#SUBDIR/foo') | 595 # AddFiles() should replace the 'SUBDIR' alt_name, then match both |
596 # possible roots for the '_' alt_name. | |
597 c.AddFiles('SUBDIR/foo') | |
526 self.assertEqual(self.mock_walk_calls, | 598 self.assertEqual(self.mock_walk_calls, |
527 ['/src/subdir/foo', 'c:/source/subdir/foo']) | 599 ['/src/subdir/foo', 'c:/source/subdir/foo']) |
600 self.assertEqual(self.mock_scan_calls, []) | |
528 self.assertEqual(c.files, {}) | 601 self.assertEqual(c.files, {}) |
529 | 602 |
530 def testAddFilesNonEmpty(self): | 603 def testAddFilesNonEmpty(self): |
531 """Test AddFiles() where files are returned.""" | 604 """Test AddFiles() where files are returned.""" |
532 | 605 |
533 c = self.cov_minimal | 606 c = self.cov_minimal |
534 c.add_files_walk = self.MockWalk | 607 c.add_files_walk = self.MockWalk |
608 c.scan_file = self.MockScanFile | |
535 | 609 |
536 # Add a rule to exclude a subdir | 610 # Add a rule to exclude a subdir |
537 c.AddRule('^#/proj1/excluded/', include=0) | 611 c.AddRule('^_/proj1/excluded/', include=0) |
538 | 612 |
539 # Set data for mock walk | 613 # Add a rule to exclude adding some fiels |
614 c.AddRule('.*noscan.c$', add_if_missing=0) | |
615 | |
616 # Set data for mock walk and scan | |
540 self.mock_walk_return = [ | 617 self.mock_walk_return = [ |
541 [ | 618 [ |
542 '/src/proj1', | 619 '/src/proj1', |
543 ['excluded', 'subdir'], | 620 ['excluded', 'subdir'], |
544 ['a.c', 'no.f', 'yes.c'], | 621 ['a.c', 'no.f', 'yes.c', 'noexe.c', 'bob_noscan.c'], |
545 ], | 622 ], |
546 [ | 623 [ |
547 '/src/proj1/subdir', | 624 '/src/proj1/subdir', |
548 [], | 625 [], |
549 ['cherry.c'], | 626 ['cherry.c'], |
550 ], | 627 ], |
551 ] | 628 ] |
552 | 629 |
630 # Add a file with no executable lines; it should be scanned but not added | |
631 self.mock_scan_return['/src/proj1/noexe.c'] = [] | |
632 | |
553 c.AddFiles('/src/proj1') | 633 c.AddFiles('/src/proj1') |
554 | 634 |
555 self.assertEqual(self.mock_walk_calls, ['/src/proj1']) | 635 self.assertEqual(self.mock_walk_calls, ['/src/proj1']) |
636 self.assertEqual(self.mock_scan_calls, [ | |
637 ['/src/proj1/a.c', 'C'], | |
638 ['/src/proj1/yes.c', 'C'], | |
639 ['/src/proj1/noexe.c', 'C'], | |
640 ['/src/proj1/subdir/cherry.c', 'C'], | |
641 ]) | |
556 | 642 |
557 # Include files from the main dir and subdir | 643 # Include files from the main dir and subdir |
558 self.assertEqual(sorted(c.files), [ | 644 self.assertEqual(sorted(c.files), [ |
559 '#/proj1/a.c', | 645 '_/proj1/a.c', |
560 '#/proj1/subdir/cherry.c', | 646 '_/proj1/subdir/cherry.c', |
561 '#/proj1/yes.c']) | 647 '_/proj1/yes.c']) |
562 | 648 |
563 # Excluded dir should have been pruned from the mock walk data dirnames. | 649 # Excluded dir should have been pruned from the mock walk data dirnames. |
564 # In the real os.walk() call this prunes the walk. | 650 # In the real os.walk() call this prunes the walk. |
565 self.assertEqual(self.mock_walk_return[0][1], ['subdir']) | 651 self.assertEqual(self.mock_walk_return[0][1], ['subdir']) |
566 | 652 |
567 def testUpdateTreeStats(self): | 653 def testUpdateTreeStats(self): |
568 """Test UpdateTreeStats().""" | 654 """Test UpdateTreeStats().""" |
569 | 655 |
570 c = self.cov_minimal | 656 c = self.cov_minimal |
571 | |
572 | |
573 | |
574 c.AddRule('.*_test', group='test') | 657 c.AddRule('.*_test', group='test') |
575 | 658 |
576 # Fill the files list | 659 # Fill the files list |
577 c.ParseLcovData([ | 660 c.ParseLcovData([ |
578 'SF:/src/a.c', | 661 'SF:/src/a.c', |
579 'DA:10,1', 'DA:11,1', 'DA:20,0', | 662 'DA:10,1', 'DA:11,1', 'DA:20,0', |
580 'end_of_record', | 663 'end_of_record', |
581 'SF:/src/a_test.c', | 664 'SF:/src/a_test.c', |
582 'DA:10,1', 'DA:11,1', 'DA:12,1', | 665 'DA:10,1', 'DA:11,1', 'DA:12,1', |
583 'end_of_record', | 666 'end_of_record', |
584 'SF:/src/foo/b.c', | 667 'SF:/src/foo/b.c', |
585 'DA:10,1', 'DA:11,1', 'DA:20,0', 'DA:21,0', 'DA:30,0', | 668 'DA:10,1', 'DA:11,1', 'DA:20,0', 'DA:21,0', 'DA:30,0', |
586 'end_of_record', | 669 'end_of_record', |
587 'SF:/src/foo/b_test.c', | 670 'SF:/src/foo/b_test.c', |
588 'DA:20,0', 'DA:21,0', 'DA:22,0', | 671 'DA:20,0', 'DA:21,0', 'DA:22,0', |
589 'end_of_record', | 672 'end_of_record', |
590 ]) | 673 ]) |
591 c.UpdateTreeStats() | 674 c.UpdateTreeStats() |
592 | 675 |
593 t = c.tree | 676 t = c.tree |
594 self.assertEqual(t.dirpath, '') | 677 self.assertEqual(t.dirpath, '') |
595 self.assertEqual(sorted(t.files), []) | 678 self.assertEqual(sorted(t.files), []) |
596 self.assertEqual(sorted(t.subdirs), ['#']) | 679 self.assertEqual(sorted(t.subdirs), ['_']) |
597 self.assertEqual(t.stats_by_group, { | 680 self.assertEqual(t.stats_by_group, { |
598 'all': { | 681 'all': { |
599 'files_covered': 3, | 682 'files_covered': 3, |
600 'files_executable': 4, | 683 'files_executable': 4, |
601 'lines_executable': 14, | 684 'lines_executable': 14, |
602 'lines_covered': 7, | 685 'lines_covered': 7, |
603 'lines_instrumented': 14, | 686 'lines_instrumented': 14, |
604 'files_instrumented': 4, | 687 'files_instrumented': 4, |
605 }, | 688 }, |
606 'my': { | 689 'my': { |
607 'files_covered': 2, | 690 'files_covered': 2, |
608 'files_executable': 2, | 691 'files_executable': 2, |
609 'lines_executable': 8, | 692 'lines_executable': 8, |
610 'lines_covered': 4, | 693 'lines_covered': 4, |
611 'lines_instrumented': 8, | 694 'lines_instrumented': 8, |
612 'files_instrumented': 2, | 695 'files_instrumented': 2, |
613 }, | 696 }, |
614 'test': { | 697 'test': { |
615 'files_covered': 1, | 698 'files_covered': 1, |
616 'files_executable': 2, | 699 'files_executable': 2, |
617 'lines_executable': 6, | 700 'lines_executable': 6, |
618 'lines_covered': 3, | 701 'lines_covered': 3, |
619 'lines_instrumented': 6, | 702 'lines_instrumented': 6, |
620 'files_instrumented': 2, | 703 'files_instrumented': 2, |
621 }, | 704 }, |
622 }) | 705 }) |
623 | 706 |
624 t = t.subdirs['#'] | 707 t = t.subdirs['_'] |
625 self.assertEqual(t.dirpath, '#') | 708 self.assertEqual(t.dirpath, '_') |
626 self.assertEqual(sorted(t.files), ['a.c', 'a_test.c']) | 709 self.assertEqual(sorted(t.files), ['a.c', 'a_test.c']) |
627 self.assertEqual(sorted(t.subdirs), ['foo']) | 710 self.assertEqual(sorted(t.subdirs), ['foo']) |
628 self.assertEqual(t.stats_by_group, { | 711 self.assertEqual(t.stats_by_group, { |
629 'all': { | 712 'all': { |
630 'files_covered': 3, | 713 'files_covered': 3, |
631 'files_executable': 4, | 714 'files_executable': 4, |
632 'lines_executable': 14, | 715 'lines_executable': 14, |
633 'lines_covered': 7, | 716 'lines_covered': 7, |
634 'lines_instrumented': 14, | 717 'lines_instrumented': 14, |
635 'files_instrumented': 4, | 718 'files_instrumented': 4, |
(...skipping 10 matching lines...) Expand all Loading... | |
646 'files_covered': 1, | 729 'files_covered': 1, |
647 'files_executable': 2, | 730 'files_executable': 2, |
648 'lines_executable': 6, | 731 'lines_executable': 6, |
649 'lines_covered': 3, | 732 'lines_covered': 3, |
650 'lines_instrumented': 6, | 733 'lines_instrumented': 6, |
651 'files_instrumented': 2, | 734 'files_instrumented': 2, |
652 }, | 735 }, |
653 }) | 736 }) |
654 | 737 |
655 t = t.subdirs['foo'] | 738 t = t.subdirs['foo'] |
656 self.assertEqual(t.dirpath, 'foo') | 739 self.assertEqual(t.dirpath, '_/foo') |
657 self.assertEqual(sorted(t.files), ['b.c', 'b_test.c']) | 740 self.assertEqual(sorted(t.files), ['b.c', 'b_test.c']) |
658 self.assertEqual(sorted(t.subdirs), []) | 741 self.assertEqual(sorted(t.subdirs), []) |
659 self.assertEqual(t.stats_by_group, { | 742 self.assertEqual(t.stats_by_group, { |
660 'test': { | 743 'test': { |
661 'files_executable': 1, | 744 'files_executable': 1, |
662 'files_instrumented': 1, | 745 'files_instrumented': 1, |
663 'lines_executable': 3, | 746 'lines_executable': 3, |
664 'lines_instrumented': 3, | 747 'lines_instrumented': 3, |
665 'lines_covered': 0, | 748 'lines_covered': 0, |
666 }, | 749 }, |
(...skipping 18 matching lines...) Expand all Loading... | |
685 # TODO: test: less important, since these are thin wrappers around other | 768 # TODO: test: less important, since these are thin wrappers around other |
686 # tested methods. | 769 # tested methods. |
687 # ParseConfig() | 770 # ParseConfig() |
688 # ParseLcovFile() | 771 # ParseLcovFile() |
689 # PrintTree() | 772 # PrintTree() |
690 | 773 |
691 #------------------------------------------------------------------------------ | 774 #------------------------------------------------------------------------------ |
692 | 775 |
693 if __name__ == '__main__': | 776 if __name__ == '__main__': |
694 unittest.main() | 777 unittest.main() |
OLD | NEW |