Skip to content

Commit ed7f199

Browse files
Fixed gcovr report reading and added coverage method to bug manager (fixes #158) (#168)
* fixed API migration bugs * added files_to_instrument parameter to Bug.coverage method * added missing imports * added mktemp method to container manager * bug fix: tweaked gcovr to write to temporary file; avoids corrupted XML outputs * bumped version to 2.0.4
1 parent 3cf2fb4 commit ed7f199

File tree

5 files changed

+59
-19
lines changed

5 files changed

+59
-19
lines changed

bugzoo/core/coverage.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class TestSuiteCoverage(object):
9898
@staticmethod
9999
def from_dict(d: dict) -> 'TestSuiteCoverage':
100100
coverage_by_test = {}
101-
for test_coverage_dict in d:
101+
for test_coverage_dict in d.values():
102102
test_coverage = TestCoverage.from_dict(test_coverage_dict)
103103
coverage_by_test[test_coverage.test] = test_coverage
104-
return ProjectCoverageMap(coverage_by_test)
104+
return TestSuiteCoverage(coverage_by_test)
105105

106106
@staticmethod
107107
def from_file(fn: str) -> 'TestSuiteCoverage':

bugzoo/mgr/bug.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Iterator
1+
from typing import Iterator, Optional, List
2+
import os
23

34
import docker
45
import textwrap
@@ -185,10 +186,21 @@ def validate(self, bug: Bug, verbose: bool = True) -> bool:
185186

186187
return validated
187188

188-
def coverage(self, bug: Bug) -> TestSuiteCoverage:
189+
def coverage(self,
190+
bug: Bug,
191+
files_to_instrument: Optional[List[str]] = None
192+
) -> TestSuiteCoverage:
189193
"""
190194
Provides coverage information for each test within the test suite
191195
for the program associated with this bug.
196+
197+
Parameters:
198+
bug: the bug for which to compute coverage.
199+
files_to_instrument: an optional list of files that should be
200+
instrumented before generating the coverage report.
201+
202+
Returns:
203+
a test suite coverage report for the given bug.
192204
"""
193205
# determine the location of the coverage map on disk
194206
fn = os.path.join(self.__installation.coverage_path,
@@ -201,9 +213,12 @@ def coverage(self, bug: Bug) -> TestSuiteCoverage:
201213
# if we don't have coverage information, compute it
202214
try:
203215
mgr_ctr = self.__installation.containers
216+
mgr_cov = self.__installation.coverage
204217
container = None
205218
container = mgr_ctr.provision(bug)
206-
coverage = mgr_ctr.coverage(container)
219+
coverage = mgr_cov.coverage(container,
220+
bug.tests,
221+
files_to_instrument=files_to_instrument)
207222

208223
# save to disk
209224
with open(fn, 'w') as f:

bugzoo/mgr/container.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,20 @@ def provision(self,
153153
self.__containers[uid] = container
154154
return container
155155

156+
def mktemp(self,
157+
container: Container
158+
) -> str:
159+
"""
160+
Creates a named temporary file within a given container.
161+
162+
Returns:
163+
the absolute path to the created temporary file.
164+
"""
165+
response = self.command(container, "mktemp")
166+
assert response.code == 0, "failed to create temporary file"
167+
fn = response.output.strip()
168+
return fn
169+
156170
def ip_address(self,
157171
container: Container,
158172
raise_error: bool = False

bugzoo/mgr/coverage.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ def _from_gcovr_xml_string(self,
5656
dir_source = container.bug.source_dir # TODO port
5757
# getting a list of all files in source directory to later use for resolving path
5858
resp = mgr_ctr.command(container, "find {} -type f".format(dir_source))
59-
all_files = resp.output.split('\n')
60-
59+
all_files = [fn.strip() for fn in resp.output.split('\n')]
6160

6261
def has_file(fn_rel: str) -> bool:
6362
fn_abs = os.path.join(dir_source, fn_rel)
@@ -233,7 +232,7 @@ def extract(self,
233232
"""
234233
logger = self.__logger.getChild(container.id)
235234
mgr_ctr = self.__installation.containers
236-
logger.debug("Starting to extract coverage info")
235+
logger.debug("Extracting coverage information")
237236

238237
if not instrumented_files:
239238
instrumented_files = set()
@@ -243,17 +242,29 @@ def extract(self,
243242
dir_source = container.bug.source_dir # TODO port
244243
t_start = timer()
245244
logger.debug("Running gcovr.")
245+
fn_temp_ctr = mgr_ctr.mktemp(container)
246+
cmd = 'gcovr -o "{}" -x -d -r .'.format(fn_temp_ctr)
246247
response = mgr_ctr.command(container,
247-
'gcovr -x -d -r .',
248-
context=dir_source)
249-
logger.debug("gcovr returned. Seconds passed: %.2f", timer() - t_start)
250-
assert response.code == 0
251-
response = response.output
248+
cmd,
249+
context=dir_source,
250+
verbose=True)
251+
logger.debug("Finished running gcovr (took %.2f seconds).", timer() - t_start)
252+
assert response.code == 0, "failed to run gcovr"
253+
254+
# copy the contents of the temporary file to the host machine
255+
(_, fn_temp_host) = tempfile.mkstemp(suffix='.bugzoo')
256+
try:
257+
mgr_ctr.copy_from(container, fn_temp_ctr, fn_temp_host)
258+
with open(fn_temp_host, 'r') as fh:
259+
report = fh.read()
260+
finally:
261+
os.remove(fn_temp_host)
252262

253263
t_start = timer()
254-
logger.debug("Parsing gcovr xml.")
255-
res = self._from_gcovr_xml_string(response,
256-
instrumented_files,
257-
container)
258-
logger.debug("Finished parsing gcovr xml. Seconds passed: %.2f", timer() - t_start)
264+
logger.debug("Parsing gcovr XML report.")
265+
res = self._from_gcovr_xml_string(report,
266+
instrumented_files,
267+
container)
268+
logger.debug("Finished parsing gcovr XML report (took %.2f seconds).", timer() - t_start)
269+
logger.debug("Finished extracting coverage information")
259270
return res

bugzoo/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '2.0.3'
1+
__version__ = '2.0.4'

0 commit comments

Comments
 (0)