Skip to content

Commit

Permalink
Implemented ephemeral servers and fixed connection timeout bug (fixes #…
Browse files Browse the repository at this point in the history
…205) (#206)

* added ephemeral method to server module

* bug fix: connection timeout in server was shorter than expected

* updated client example to use ephemeral server

* bug fix: url -> _url

* bump to version 2.1.2

* bug fix: bad type definition for bugzoo.server.ephemeral
  • Loading branch information
ChrisTimperley authored Apr 30, 2018
1 parent 229393a commit 77d0bd1
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 45 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 2.1.2 (2018-04-30)

### Features

* Added method `bugzoo.server.ephemeral` to allow ephemeral servers to be
provisioned. Launches a server and returns a context-bound client that is
connected to that server. As soon as the context is closed, the server is
safely destroyed.

### Bug Fixes

* Fixed a bug in `bugzoo.client.Client` that caused the connection timeout to
abort the connection attempt prematurely.


## 2.1.1 (2018-04-27)

### Features
Expand Down
10 changes: 5 additions & 5 deletions bugzoo/client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ def __init__(self,

# attempt to establish a connection
url = self._url("status")
time_left = float(timeout_connection)
time_started = timer()
connected = False
while time_left > 0.0 and not connected:
while not connected:
time_running = timer() - time_started
time_left = timeout_connection - time_running
if time_left <= 0.0:
raise ConnectionFailure
try:
r = requests.get(url, timeout=time_left)
connected = r.status_code == 204
Expand All @@ -50,9 +53,6 @@ def __init__(self,
except requests.exceptions.Timeout:
raise ConnectionFailure
time.sleep(0.05)
time_left -= timer() - time_started
if not connected:
raise ConnectionFailure

def _url(self, path: str) -> str:
"""
Expand Down
38 changes: 37 additions & 1 deletion bugzoo/server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from typing import Dict, Any
from typing import Dict, Any, Iterator
from functools import wraps
from contextlib import contextmanager
import argparse
import os
import signal
import subprocess

import flask

from ..core.bug import Bug
from ..core.patch import Patch
from ..manager import BugZoo
from ..exceptions import *
from ..client import Client

daemon = None # type: BugZoo
app = flask.Flask(__name__)
Expand Down Expand Up @@ -39,6 +44,37 @@ def wrapper(*args, **kwargs):
return wrapper


@contextmanager
def ephemeral(*,
port: int = 6060,
verbose: bool = False
) -> Iterator[Client]:
"""
Launches an ephemeral server instance that will be immediately
close when no longer in context.
Parameters:
port: the port that the server should run on.
verbose: if set to True, the server will print its output to the
stdout, otherwise it will remain silent.
Returns:
a client for communicating with the server.
"""
url = "http://127.0.0.1:{}".format(port)
cmd = ["bugzood", "-p", str(port)]
try:
stdout = None if verbose else subprocess.DEVNULL
stderr = None if verbose else subprocess.DEVNULL
proc = subprocess.Popen(cmd,
preexec_fn=os.setsid,
stdout=stdout,
stderr=stderr)
yield Client(url)
finally:
os.killpg(proc.pid, signal.SIGTERM)


@app.route('/status', methods=['GET'])
def get_status():
"""
Expand Down
2 changes: 1 addition & 1 deletion bugzoo/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2.1.1'
__version__ = '2.1.2'
76 changes: 38 additions & 38 deletions examples/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import time

import bugzoo.client
import bugzoo.server
from bugzoo.core.bug import Bug
from bugzoo.core.patch import Patch

Expand All @@ -22,47 +22,47 @@
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
""".lstrip())

client = bugzoo.client.Client(timeout_connection = 90)
bug = client.bugs['manybugs:python:69223-69224']
test = bug.harness['p1']
container = client.containers.provision(bug)
try:
r = client.containers.exec(container, "echo 'hello world'")
outcome = client.containers.test(container, test)
print(outcome)
with bugzoo.server.ephemeral() as client:
bug = client.bugs['manybugs:python:69223-69224']
test = bug.harness['p1']
container = client.containers.provision(bug)
try:
r = client.containers.exec(container, "echo 'hello world'")
outcome = client.containers.test(container, test)
print(outcome)

# read a file
contents = client.files.read(container, "setup.py")
print(contents)
# read a file
contents = client.files.read(container, "setup.py")
print(contents)

# patch a file
outcome = client.containers.patch(container, patch)
outcome_text = "yes" if outcome else "no"
print("applied patch? {}".format(outcome_text))
# patch a file
outcome = client.containers.patch(container, patch)
outcome_text = "yes" if outcome else "no"
print("applied patch? {}".format(outcome_text))

# get the contents of the patched file
contents = client.files.read(container, "LICENSE")
print(contents)
# get the contents of the patched file
contents = client.files.read(container, "LICENSE")
print(contents)

# persist the container
client.containers.persist(container, "hulk/foobarblah")
# persist the container
client.containers.persist(container, "hulk/foobarblah")

# delete the newly persisted Docker image
client.docker.delete_image("hulk/foobarblah")
# delete the newly persisted Docker image
client.docker.delete_image("hulk/foobarblah")

# register a mutant
mutant = Bug("an-example-bug",
"hulk/foobarblah",
dataset=None,
source=None,
program=bug.program,
source_dir=bug.source_dir,
languages=bug.languages,
harness=bug.harness,
compiler=bug.compiler,
files_to_instrument=bug.files_to_instrument)
client.bugs.register(mutant)
print("registered mutant")
# register a mutant
mutant = Bug("an-example-bug",
"hulk/foobarblah",
dataset=None,
source=None,
program=bug.program,
source_dir=bug.source_dir,
languages=bug.languages,
harness=bug.harness,
compiler=bug.compiler,
files_to_instrument=bug.files_to_instrument)
client.bugs.register(mutant)
print("registered mutant")

finally:
del client.containers[container.uid]
finally:
del client.containers[container.uid]

0 comments on commit 77d0bd1

Please sign in to comment.