class Shell(object): def __init__(self): self.subject = Subject() def add_run_observer(self, observer): self.subject.add_observer(observer) def remove_run_observer(self, observer): self.subject.remove_observer(self, observer) def check_open(self, args, input_string=None): self.subject.notify(' '.join(args)) return check_open(args, input_string)
class Future(object): def __init__(self, fn, *args, **kwargs): self.queue = Queue() self.fn = fn self.args = args self.kwargs = kwargs self.start_subject = Subject() self.stop_subject = Subject() def add_start_observer(self, observer): self.start_subject.add_observer(observer) def add_stop_observer(self, observer): self.stop_subject.add_observer(observer) def deliver_exception(self, exception): self.queue.put((False, exception)) def fn_main(self): try: self.queue.put((True, self.fn(*self.args, **self.kwargs))) except Exception as e: self.queue.put((False, e)) def run(self): fn_thread = Thread(target=self.fn_main) self.start_subject.notify(self) fn_thread.start() result = self.queue.get() self.stop_subject.notify(self) if result[0]: return result[1] else: # TODO(peter): kill self.fn_thread? Killing it using some posix # interface can make python buggy. Not killing it might make screw # with future tests. raise result[1]
class GDBStubClient(object): def __init__(self, command_queue, response_queue, event_queue, server_pid): self.logger = logging.getLogger('GDBStubClient') self.command_queue = command_queue self.response_queue = response_queue self.event_queue = event_queue self.server_pid = server_pid self.quitting = False self.event_subject = Subject() self.event_thread = Thread(target=self.event_thread_main) self.event_thread.start() def event_thread_main(self): # After RETURN_TO_INTERPRETER has been processed, we are # disconnected from GDB's event generators, so the size of the event # queue is monotonically decreasing. The last event is a fake one # that we queue so queue.get returns. while True: event = self.event_queue.get() if self.quitting and self.event_queue.empty(): break print event self.event_subject.notify(event) def add_event_observer(self, observer): self.event_subject.add_observer(observer) def execute(self, command): self.logger.debug('execute ' + command) self.command_queue.put(Command(command)) def execute_sync(self, command): self.logger.debug('execute_sync ' + command) self.command_queue.put(Command(command, queue_output=True)) self.command_queue.join() return self.response_queue.get() def pause(self): self.logger.debug('pause') self.command_queue.put(Command(Command.INTERRUPT, is_meta=True)) os.kill(self.server_pid, signal.SIGINT) self.logger.debug('pause waiting for command queue to empty') self.command_queue.join() self.logger.debug('pause command queue empty') def abort(self): self.command_queue.put( Command(Command.RETURN_TO_INTERPRETER, is_meta=True)) def return_to_interpreter(self): self.logger.debug('returning to GDB command interpreter') self.command_queue.put( Command(Command.RETURN_TO_INTERPRETER, is_meta=True)) self.command_queue.join() self.quitting = True self.event_queue.put(None) self.event_thread.join()
class SubjectTestCase(unittest.TestCase): def setUp(self): self.count1 = 0 self.count2 = 0 self.count3 = 0 self.subject = Subject() def event1(self): self.count1 += 1 def event2(self): self.count2 += 1 def remove_during_event(self): self.count3 += 1 self.subject.remove_observer(self.remove_during_event) def test_simple(self): self.subject.add_observer(self.event1) self.subject.notify() self.assertEqual(1, self.count1) self.subject.remove_observer(self.event1) self.subject.notify() self.assertEqual(1, self.count1) self.subject.add_observer(self.event1) self.subject.add_observer(self.event2) self.subject.notify() self.assertEqual(2, self.count1) self.assertEqual(1, self.count2) def test_multiple(self): self.subject.add_observer(self.event1) self.subject.add_observer(self.event1) self.subject.notify() self.assertEqual(2, self.count1) def test_remove_during_event(self): self.subject.add_observer(self.event1) self.subject.add_observer(self.remove_during_event) self.subject.add_observer(self.event2) self.subject.notify() self.assertEqual(1, self.count1) self.assertEqual(1, self.count2) self.assertEqual(1, self.count3) self.subject.notify() self.assertEqual(2, self.count1) self.assertEqual(2, self.count2) self.assertEqual(1, self.count3)