summaryrefslogtreecommitdiff
path: root/distbuild
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2015-04-07 18:17:10 +0000
committerPedro Alvarez <pedro.alvarez@codethink.co.uk>2015-04-22 08:22:39 +0000
commit124e2f1b68a5176dcb3bf37543d4d9ff26a14b95 (patch)
treed00ad83aa71ea34876996823e0eb5523188f84f4 /distbuild
parent8103617c23fed8f07f23431d0b66ca6bcb6cba2d (diff)
downloadmorph-124e2f1b68a5176dcb3bf37543d4d9ff26a14b95.tar.gz
distbuild: Add test suite for distbuild-helper
This is mostly to check that the 'cancel entire subprocess tree' works as expected. Revert that patch and the test fails. There are also some tweaks included in this commit. Change-Id: If297522e6589ebb3a07dac66a39eb243789e53aa
Diffstat (limited to 'distbuild')
-rw-r--r--distbuild/helper_router.py4
-rw-r--r--distbuild/json_router.py2
-rw-r--r--distbuild/mainloop.py65
-rw-r--r--distbuild/sockserv.py4
4 files changed, 70 insertions, 5 deletions
diff --git a/distbuild/helper_router.py b/distbuild/helper_router.py
index 5578f750..22096b81 100644
--- a/distbuild/helper_router.py
+++ b/distbuild/helper_router.py
@@ -40,7 +40,7 @@ class HelperResult(object):
class HelperRouter(distbuild.StateMachine):
- '''Route JSON messages between helpers and other state machines.
+ '''Route JSON messages between controller and its helper.
This state machine relays and schedules access to one distbuild-helper
process. The helper process connects to a socket, which causes an
@@ -51,7 +51,7 @@ class HelperRouter(distbuild.StateMachine):
Other state machines in the same mainloop as HelperRouter can
request work from the helper process by emitting an event:
- * event source: the distbuild.HelperProcess class
+ * event source: the distbuild.HelperRouter class
* event: distbuild.HelperRequest instance
The HelperRequest event gets a message to be serialised as JSON.
diff --git a/distbuild/json_router.py b/distbuild/json_router.py
index d9c32a9c..0f41bfc6 100644
--- a/distbuild/json_router.py
+++ b/distbuild/json_router.py
@@ -22,7 +22,7 @@ import distbuild
class JsonRouter(distbuild.StateMachine):
- '''Route JSON messages between clients and helpers.
+ '''Route JSON messages between controller, worker and worker helper(s).
This state machine receives JSON messages from clients and helpers,
and routes messages between them.
diff --git a/distbuild/mainloop.py b/distbuild/mainloop.py
index e7c0cc3b..d48d60ec 100644
--- a/distbuild/mainloop.py
+++ b/distbuild/mainloop.py
@@ -132,3 +132,68 @@ class MainLoop(object):
event_source, event = self._events.pop(0)
yield event_source, event
+
+
+class TestableMainLoop(MainLoop):
+ '''Special mainloop class with extra hooks for tests to use.
+
+ When writing a test, you often need to wait until a certain event has
+ happened, then examine that event. The run_until_event() and
+ run_until_new_state_machine() functions allow this.
+
+ '''
+ def __init__(self):
+ super(TestableMainLoop, self).__init__()
+
+ self._machines_added_this_cycle = []
+ self._events_sent_this_cycle = []
+
+ def add_state_machine(self, machine):
+ # Overriding the base class to monitor new state machines.
+ super(TestableMainLoop, self).add_state_machine(machine)
+ self._machines_added_this_cycle.append(machine)
+
+ def queue_event(self, event_source, event):
+ # Overriding the base class to monitor new events.
+ super(TestableMainLoop, self).queue_event(event_source, event)
+ self._events_sent_this_cycle.append((event_source, event))
+
+ def run_until_event(self, target_event_source, target_event_type):
+ '''Run the main loop continuously until a given event happens.
+
+ All queued messages will be processed before the loop exits.
+
+ '''
+ logging.debug('Running main loop until a %s event from %s.',
+ target_event_type, target_event_source)
+ while self._machines:
+ self._events_sent_this_cycle = []
+
+ self._run_once()
+
+ for event_source, event in self._events_sent_this_cycle:
+ if target_event_source == event_source:
+ if isinstance(event, target_event_type):
+ logging.debug(
+ 'Received %s from %s, exiting loop.', event,
+ event_source)
+ return event
+
+ def run_until_new_state_machine(self, target_machine_type):
+ '''Run the main loop continuously until a new state machine appears.
+
+ All queued messages will be processed before the loop exits.
+
+ '''
+ logging.debug('Running main loop until a new %s appears.',
+ target_machine_type)
+ while self._machines:
+ self._machines_added_this_cycle = []
+
+ self._run_once()
+
+ for machine in self._machines_added_this_cycle:
+ if type(machine) == target_machine_type:
+ logging.debug(
+ 'Found new machine %s, exiting loop.', machine)
+ return machine
diff --git a/distbuild/sockserv.py b/distbuild/sockserv.py
index c9979328..998cfb11 100644
--- a/distbuild/sockserv.py
+++ b/distbuild/sockserv.py
@@ -35,10 +35,10 @@ class ListenServer(StateMachine):
def setup(self):
src = ListeningSocketEventSource(self._addr, self._port)
+ _, self._port = src.sock.getsockname()
if self._port_file:
- host, port = src.sock.getsockname()
with open(self._port_file, 'w') as f:
- f.write('%s\n' % port)
+ f.write('%s\n' % self._port)
self.mainloop.add_event_source(src)
spec = [