Skip to content

Commit cbdf698

Browse files
Merge branch 'master' of github.com:squaresLab/BugZoo
2 parents b161560 + 570c907 commit cbdf698

File tree

17 files changed

+586
-192
lines changed

17 files changed

+586
-192
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Pipfile
2+
Pipfile.lock
3+
bugzood.log
4+
docs-html
5+
16
.mypy_cache
27
*.pyc
38

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
## 2.1.7 (2018-05-20)
2+
3+
### Features
4+
5+
* `bugzood` now allows users to log to a given file.
6+
* Added `**kwargs` to all HTTP methods in low-level API client; allows more
7+
information to be forwarded onto `requests`.
8+
* Added `build` method as an alias of `compile` in both client- and
9+
server-side container managers.
10+
* Added more detailed logging to client file manager.
11+
* Added `__repr__` to `Spectra`.
12+
* Added check to `BugZoo` to ensure that the Docker server is responsive.
13+
* Added slightly better error handling to `mktemp` in server-side container
14+
manager.
15+
* Added better logging and error reporting to `command` in server-side
16+
container manager.
17+
* Added `POST /containers/<uid>/build` endpoint to server.
18+
19+
### Bug Fixes
20+
21+
* Fixed a bug in logging that prevented `DEBUG` level calls from being written
22+
to file or passed to the stdout.
23+
* Fixed a bug in URL generation method in client module that prevented certain
24+
URLs from being reached.
25+
* Fixed HTTP method used by `coverage` method in `client.container`.
26+
* Fixed bug in `CompilationOutcome.from_dict` that prevented serialised
27+
compilation outcomes from being parsed.
28+
29+
130
## 2.1.6 (2018-05-15)
231

332
### Features

README.md

Lines changed: 130 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,128 @@
11
# BugZoo
22

3-
[![Join the chat at https://gitter.im/BugZoo/Lobby](https://badges.gitter.im/BugZoo/Lobby.svg)](https://gitter.im/BugZoo/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4-
[![Build Status](https://travis-ci.org/squaresLab/BugZoo.svg?branch=master)](https://travis-ci.org/squaresLab/BugZoo)
5-
6-
BugZoo is an ongoing effort to provide a series of controlled environments
7-
for performing experiments on automated program repair of C programs. BugZoo
8-
provides a number of bug scenarios, adapted from existing publicly-available
9-
datasets, including [ManyBugs](http://repairbenchmarks.cs.umass.edu/),
10-
[GenProg's earlier benchmarks](http://dijkstra.cs.virginia.edu/genprog/), and
11-
several datasets from the
12-
[Software Infrastructure Repository](http://sir.unl.edu/).
13-
14-
As well as providing the files necessary to study each bug,
15-
BugZoo also provides a minimal, isolated environment for execution, in the
16-
form of an accompanying Docker container. By providing a container for
17-
each bug, rather than a single, monolithic virtual machine for a group of bugs,
18-
BugZoo incurs fewer overheads (resulting in a much higher performance, crucial
19-
for rigorous experimental trials), makes dependencies easier to manage, and
20-
results in a smaller disk footprint.
21-
22-
For more information on [Docker](https://www.docker.com/), the interested user is
23-
referred to
24-
[https://docs.docker.com/learn/](https://docs.docker.com/learn/).
3+
[![Build Status](https://travis-ci.org/squaresLab/BugZoo.svg?branch=master)](https://travis-ci.org/squaresLab/BugZoo)
4+
[![PyPI version](https://badge.fury.io/py/bugzoo.svg)](https://badge.fury.io/py/bugzoo)
5+
6+
BugZoo is a decentralised platform for distributing,
7+
reproducing, and interacting with historical software bugs. BugZoo is designed
8+
to support both software engineering researchers as well as developers of tools
9+
for program testing, analysis and repair.
10+
11+
Under the hood, BugZoo uses [Docker](https://www.docker.com/) containers to
12+
provide a controlled, sterile environment for safely interacting with
13+
historical software bugs. BugZoo provides several advantages over
14+
the use of monolithic virtual machines
15+
(e.g., [ManyBugs VM](http://repairbenchmarks.cs.umass.edu/)):
16+
17+
* By using containerisation instead of virtualisation, BugZoo can ensure
18+
reproducibility with minimal sacrifice to performance, allowing you to run
19+
bigger experiments faster.
20+
* Since containers can be spawned in under a second, a safe, idempotent
21+
execution environment can be realistically provided for every test suite
22+
evaluation.
23+
* Each historical bug is provided as its own minimal Docker container image.
24+
There are no assumptions that bug containers should be capable of running
25+
other software, such as a testing or repair tool that is being evaluated as
26+
part of an experiment. BugZoo avoids the inevitable "DLL hell" that arises
27+
from attempting to mix bugs and tools by transforming tools into portable
28+
binaries and mounting them in the execution environment at run-time.
29+
* Thanks to their minimal nature and Docker's layer-based image caching,
30+
prebuilt datasets of historical bugs can be downloaded quickly and
31+
easily.
32+
33+
34+
## Features
35+
36+
* A simple but powerful command-line interface for building, downloading and
37+
interacting with historical bugs.
38+
* A Python interface for complex, structured interactions with historical
39+
bugs: execute specific tests, compute line coverage, apply patches, compile
40+
with certain flags, and more.
41+
* A powerful underlying RESTful API that can be used to add BugZoo bindings to your
42+
own favourite language.
43+
* A decentralised architecture that lets you share your tools and datasets of
44+
historical bugs on the BugZoo platform without giving up ownership or control.
45+
Adding BugZoo support to your dataset of tool is as simple as adding a
46+
`.bugzoo.yml` file to your project.
2547

2648
## Installation
2749

28-
To install the latest stable version of BugZoo:
50+
We recommend using [pipenv](http://pipenv.org/) to install BugZoo, although you
51+
may simply use `pip3` instead:
52+
53+
```
54+
$ pipenv install bugzoo
55+
```
56+
57+
BugZoo supports Python >= 3.5.
58+
59+
## Getting Started
60+
61+
Since BugZoo is a decentralised platform for sharing and interacting with
62+
historical bugs (*and not itself a dataset of bugs*), you'll need to add
63+
several bugs and tools to your installation. Bugs and tools are usually
64+
provided to BugZoo by remote, public Git repositories. Adding a *source* of
65+
bugs or tools to your installation can be done via the `bugzoo source add
66+
[name] [url]` command:
67+
68+
```
69+
$ bugzoo source add manybugs https://github.com/squaresLab/ManyBugs
70+
```
71+
72+
Note that sources do not necessarily have to be remote, public Git
73+
repositories: they can also be provided by local directories.
74+
75+
```
76+
$ git clone https://github.com/squaresLab/ManyBugs path/to/manybugs
77+
$ bugzoo source add another-manybugs path/to/manybugs
78+
```
79+
80+
The `bugzoo source list` command can be used to provide a list of registered
81+
sources:
82+
83+
```
84+
$ bugzoo source list
85+
86+
Source Type URL Location Version
87+
-------- ------ ------------------------------------------ -------------------------------------------------------------- ---------
88+
robust Local - /home/chris/bugs/robust -
89+
genprog Remote https://github.com/squaresLab/genprog-code /home/chris/.bugzoo/sources/github_com_squaresLab_genprog-code b4de21d7
90+
manybugs Remote https://github.com/squaresLab/ManyBugs /home/chris/.bugzoo/sources/github_com_squaresLab_ManyBugs ad83bd9a
91+
```
92+
93+
And `bugzoo bug list` and `bugzoo tool list` can be used to produce a list of
94+
all bugs and tools that are provided by your registered sources:
2995

3096
```
31-
$ pip3 install bugzoo
97+
$ bugzoo bug list
98+
99+
Bug Program Dataset Source Installed?
100+
---------------------------------------------- ---------- --------- -------- ------------
101+
manybugs:gmp:13420-13421 gmp manybugs manybugs No
102+
manybugs:gmp:14166-14167 gmp manybugs manybugs No
103+
manybugs:gzip:2009-08-16-3fe0caeada-39a362ae9d gzip manybugs manybugs No
104+
manybugs:gzip:2009-09-26-a1d3d4019d-f17cbd13a1 gzip manybugs manybugs No
105+
manybugs:gzip:2009-10-09-1a085b1446-118a107f2d gzip manybugs manybugs No
106+
manybugs:gzip:2010-01-30-fc00329e3d-1204630c96 gzip manybugs manybugs No
107+
manybugs:gzip:2010-02-19-3eb6091d69-884ef6d16c gzip manybugs manybugs No
108+
manybugs:libtiff:2005-12-14-6746b87-0d3d51d libtiff manybugs manybugs No
109+
manybugs:libtiff:2005-12-21-3b848a7-3edb9cd libtiff manybugs manybugs No
110+
manybugs:libtiff:2005-12-27-6f76e76-5dac30f libtiff manybugs manybugs No
111+
manybugs:libtiff:2006-02-23-b2ce5d8-207c78a libtiff manybugs manybugs No
112+
manybugs:libtiff:2006-02-27-6074705-e6d0c32 libtiff manybugs manybugs No
113+
manybugs:libtiff:2006-03-03-a72cf60-0a36d7f libtiff manybugs manybugs No
114+
...
32115
```
33116

34-
To install the latest development version of BugZoo, first produce a shallow
35-
clone of this repository before executing `pip3` as shown below.
117+
To interact with a particular bug or tool, you'll need to install it on your
118+
machine. There are two ways to do this: (1) you can build the Docker image for
119+
the bug or tool locally (via `bugzoo bug build` and `bugzoo tool build`), or
120+
alternatively, you can download a prebuilt image (via `bugzoo bug download`
121+
or `bugzoo tool download`).
36122

37123
```
38-
$ git clone git://github.com/squaresLab/BugZoo --depth 1 bugzoo
39-
$ cd bugzoo
40-
$ pip3 install . --upgrade
124+
$ bugzoo bug build manybugs:libtiff:2005-12-14-6746b87-0d3d51d
125+
...
41126
```
42127

43128
## Known Sources
@@ -54,3 +139,19 @@ To add one of these sources, simply execute the following from the command line:
54139
$ bugzoo source add manybugs https://github.com/squaresLab/ManyBugs
55140
$ bugzoo source add genprog https://github.com/squaresLab/genprog-code
56141
```
142+
143+
## Citation
144+
145+
If you use BugZoo in your research work, we would highly appreciate it if you
146+
cited the [following paper](http://www.cs.cmu.edu/~clegoues/docs/timperley-icse18-poster.pdf):
147+
148+
```
149+
@inproceedings{bugzoo,
150+
author = {Timperley, Christopher and Stepney, Susan and {Le Goues}, Claire}
151+
title = {{Poster: BugZoo – A Platform for Studying Software Bugs}},
152+
booktitle = {{International Conference on Software Engineering}},
153+
series = {{ICSE '18}},
154+
year = {2018}
155+
note = {{To appear}}
156+
}
157+
```

bugzoo/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77

88
import logging
99
logging.getLogger(__name__).addHandler(logging.NullHandler())
10+
logging.getLogger(__name__).setLevel(logging.INFO)

bugzoo/cli/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import List, Optional, Dict
22
import sys
3+
import os
34
import argparse
45
import logging
56
from operator import itemgetter
@@ -528,10 +529,11 @@ def build_parser():
528529
def main():
529530
try:
530531
log_formatter = logging.Formatter('%(levelname)s:%(name)s:%(asctime)s: %(message)s') # noqa: pycodestyle
531-
log_to_stdout = logging.StreamHandler()
532-
log_to_stdout.setFormatter(log_formatter)
533-
logging.getLogger('bugzoo').setLevel(logging.INFO)
534-
logging.getLogger('bugzoo').addHandler(log_to_stdout)
532+
log_filename = os.path.join(os.getcwd(), "bugzood.log")
533+
log_to_file = logging.handlers.WatchedFileHandler(log_filename)
534+
log_to_file.setFormatter(log_formatter)
535+
logging.getLogger('bugzoo').setLevel(logging.DEBUG)
536+
logging.getLogger('bugzoo').addHandler(log_to_file)
535537

536538
parser = build_parser()
537539
args = parser.parse_args()

bugzoo/client/api.py

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ def __init__(self,
4343
self.__base_url = base_url
4444

4545
# attempt to establish a connection
46-
logging.info("Attempting to establish connection to %s within %d seconds", # noqa: pycodestyle
47-
base_url,
48-
timeout_connection)
46+
logger.info("Attempting to establish connection to %s within %d seconds", # noqa: pycodestyle
47+
base_url, timeout_connection)
4948
url = self._url("status")
5049
time_started = timer()
5150
connected = False
@@ -66,13 +65,15 @@ def __init__(self,
6665
base_url)
6766
raise ConnectionFailure
6867
time.sleep(0.05)
69-
logging.info("Established connection to server: %s", base_url)
68+
logger.info("Established connection to server: %s", base_url)
7069

7170
def _url(self, path: str) -> str:
7271
"""
7372
Computes the URL for a resource located at a given path on the server.
7473
"""
75-
return urllib.parse.urljoin(self.__base_url, path)
74+
url = "{}/{}".format(self.__base_url, path)
75+
logger.debug("transformed path [%s] into url: %s", path, url)
76+
return url
7677

7778
def handle_erroneous_response(self,
7879
response: requests.Response
@@ -86,49 +87,34 @@ def handle_erroneous_response(self,
8687
UnexpectedResponse: if the response cannot be decoded to an
8788
exception.
8889
"""
90+
logger.debug("handling erroneous response: %s", response)
8991
try:
9092
err = BugZooException.from_dict(response.json())
9193
except Exception:
9294
err = UnexpectedResponse(response)
9395
raise err
9496

95-
def get(self,
96-
path: str,
97-
*,
98-
json: Optional[Any] = None
99-
) -> requests.Response:
97+
def get(self, path: str, **kwargs) -> requests.Response:
10098
url = self._url(path)
101-
logger.info('GET: %s', url)
102-
return requests.get(url, json=json)
103-
104-
def post(self,
105-
path: str,
106-
*,
107-
json: Optional[Any] = None
108-
) -> requests.Response:
99+
logger.debug('GET: %s', url)
100+
return requests.get(url, **kwargs)
101+
102+
def post(self, path: str, **kwargs) -> requests.Response:
109103
url = self._url(path)
110-
logger.info('POST: %s', url)
111-
return requests.post(url, json=json)
104+
logger.debug('POST: %s', url)
105+
return requests.post(url, **kwargs)
112106

113107
def put(self, path: str, **kwargs) -> requests.Response:
114108
url = self._url(path)
115-
logger.info('PUT: %s', url)
109+
logger.debug('PUT: %s', url)
116110
return requests.put(url, **kwargs)
117111

118-
def patch(self,
119-
path: str,
120-
data,
121-
**kwargs
122-
) -> requests.Response:
112+
def patch(self, path: str, data, **kwargs ) -> requests.Response:
123113
url = self._url(path)
124-
logger.info('PATCH: %s', url)
114+
logger.debug('PATCH: %s', url)
125115
return requests.patch(url, data=data, **kwargs)
126116

127-
def delete(self,
128-
path: str,
129-
*,
130-
json: Optional[Any] = None
131-
) -> requests.Response:
117+
def delete(self, path: str, **kwargs) -> requests.Response:
132118
url = self._url(path)
133-
logger.info('DELETE: %s', url)
134-
return requests.delete(url, json=json)
119+
logger.debug('DELETE: %s', url)
120+
return requests.delete(url, **kwargs)

bugzoo/client/container.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from ..core.coverage import TestSuiteCoverage
1010
from ..testing import TestCase, TestOutcome
1111
from ..cmd import ExecResponse
12+
from ..exceptions import BugZooException
1213

1314
logger = logging.getLogger(__name__) # type: logging.Logger
1415

@@ -144,17 +145,16 @@ def compile(self,
144145
Raises:
145146
KeyError: if the container no longer exists.
146147
"""
147-
path = "containers/{}/compile".format(container.uid)
148-
r = self.__api.post(path)
149-
148+
path = "containers/{}/build".format(container.uid)
149+
params = {}
150+
if verbose:
151+
params['verbose'] = 'yes'
152+
r = self.__api.post(path, params=params)
150153
if r.status_code == 200:
151154
return CompilationOutcome.from_dict(r.json())
152-
153-
if r.status_code == 404:
154-
raise KeyError("container or test case not found")
155-
156155
self.__api.handle_erroneous_response(r)
157156

157+
build = compile
158158

159159
def test(self,
160160
container: Container,
@@ -187,16 +187,21 @@ def coverage(self,
187187
uid = container.uid
188188
logger.info("Fetching coverage information for container: %s",
189189
uid)
190-
r = self.__api.get('containers/{}/coverage'.format(uid))
190+
r = self.__api.post('containers/{}/coverage'.format(uid))
191191
if r.status_code == 200:
192192
jsn = r.json()
193193
coverage = TestSuiteCoverage.from_dict(jsn) # type: ignore
194194
logger.info("Fetched coverage information for container: %s",
195195
uid)
196196
return coverage
197-
logger.error("Failed to fetch coverage information for container: %s",
198-
uid)
199-
self.__api.handle_erroneous_response(r)
197+
try:
198+
self.__api.handle_erroneous_response(r)
199+
except BugZooException as err:
200+
logger.exception("Failed to fetch coverage information for container %s: %s", uid, err.message) # noqa: pycodestyle
201+
raise
202+
except Exception as err:
203+
logger.exception("Failed to fetch coverage information for container %s due to unexpected failure: %s", uid, err) # noqa: pycodestyle
204+
raise
200205

201206
def exec(self,
202207
container: Container,

0 commit comments

Comments
 (0)