def test_set_step(self): """ Tests the functionality of set_step by asserting that it only executes the next line and no more. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) # Queue up a step command. cmd_manager.enqueue(lambda t: t.set_step()) stepped = False with Timeout(0.1, False): db.set_trace() stepped = True self.assertTrue(stepped) db.disable() cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) cmd_manager.enqueue(lambda t: t.set_step()) cmd_manager.user_wait(0.2) stepped = over_stepped = False with Timeout(0.1, False): db.set_trace() stepped = True over_stepped = True self.assertTrue(stepped) self.assertFalse(over_stepped)
def test_function_call_next_step(self): """ Tests the functionality of next and step when calling functions. This checks to make sure the function is stepped into and can be stepped over. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) # Queue up a next command to next over the function call. cmd_manager.enqueue(lambda t: t.set_next(t.curframe)) # Queue up a sleep so that we block after calling next. # This would cause us to NOT execute the f_called[0] = True line of f # had we only called set_step. This is asserted afterwards. cmd_manager.user_wait(0.2) # A mutable structure to check if f is called. f_called = NonLocal(False) def f(): f_called.value = True with Timeout(0.1, False): db.set_trace() f() # We hit that line in f, so it should now be True. self.assertTrue(f_called.value) # Assert that we are currently executing the line we think we should # be executing. Since we are just stepping, this should be setting # curframe each time. self.assertEqual( db.get_line(self.filename, db.curframe.f_lineno), ' db.get_line(self.filename, db.curframe.f_lineno),' ) db.disable() cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) f_called = NonLocal(False) # This time we will be only stepping, so we should not execute the # entire call to f. cmd_manager.enqueue(lambda t: t.set_step()) cmd_manager.user_wait(1.2) with Timeout(0.1, False): db.set_trace() f() # We should not have hit this line in f. self.assertFalse(f_called.value) # Since we only stepped once, this is the last time we set the frame. self.assertEqual( db.get_line(self.filename, db.curframe.f_lineno), ' f_called.value = True' )
def test_timeout_smart_constructor(self): """ Tests that the smart constructor returns the correct type. """ green = Timeout(1, green=True) self.assertTrue(isinstance(green, gevent.Timeout)) not_green = Timeout(1, green=False) self.assertTrue(isinstance(not_green, QdbTimeout))
def test_clear_break(self): """ Tests clearing a breakpoint. WARNING: This test relies on the relative line numbers inside the test. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) clear_break_offset = 14 set_break_offset = 8 cmd_manager.enqueue(lambda t: t.clear_break( self.filename, sys._getframe().f_lineno + clear_break_offset )) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.user_wait(0.2) db.set_break( self.filename, sys._getframe().f_lineno + set_break_offset ) db.set_trace(stop=False) continued = False with Timeout(0.1): db.set_trace(stop=False) for n in range(2): pass continued = True self.assertTrue(continued)
def test_set_continue_no_breaks(self): """ Asserts that set_continue works with no breakpoints. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.user_wait(0.2) line_1 = line_2 = line_3 = False with Timeout(0.1, False): db.set_trace() line_1 = True # EDIT IN BOTH PLACES line_2 = True line_3 = True # Assert that we hit all three lines event though interaction is # blocked. self.assertTrue(line_1 and line_2 and line_3) # As this was the last time we were supposed to stop, this should be # the curframe data. self.assertEqual( db.get_line(self.filename, db.curframe.f_lineno), ' line_1 = True # EDIT IN BOTH PLACES' )
def start(self, auth_msg=''): """ Begins processing commands from the server. """ self.pipe, child_end = gipc.pipe() self._socket_connect() self.reader = gipc.start_process( target=ServerReader, args=(child_end, os.getpid(), self.socket.fileno(), self.tracer.pause_signal), ) with Timeout(5, QdbFailedToConnect(self.tracer.address, self.tracer.retry_attepts), green=self.green): # Receive a message to know that the reader is ready to begin. self.pipe.get() self.send( fmt_msg( 'start', { 'uuid': self.tracer.uuid, 'auth': auth_msg, 'local': (0, 0), }, serial=pickle.dumps, ) ) atexit.register(self.stop)
def test_smart_constructor_can_catch(self, green): """ Asserts that users may use the normal try/catch syntax with the Timeout smart constructor. This test will fail if except Timeout does NOT catch the exception. """ try: raise Timeout(1, green=green) except Timeout: pass
def _new_execution_timeout(self, src): """ Return a new execution timeout context manager. If not execution timeout is in place, returns ExitStack() """ # We use green=False because this could be cpu bound. This will # still throw to the proper greenlet if this is gevented. return (Timeout(self.execution_timeout, QdbExecutionTimeout(src, self.execution_timeout), green=False) if self.execution_timeout else ExitStack())
def test_set_trace_with_stop(self): """ Asserts that calling set_trace will put us into stepping mode. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) cmd_manager.user_wait(0.2) line_1 = False with Timeout(0.1, False): db.set_trace() line_1 = True # EDIT IN BOTH PLACES # Since we are stepping, we should not hit this line. self.assertFalse(line_1)
def test_set_trace_without_stop(self): """ Asserts that calling set_trace with stop=False will start tracing but not stop. WARNING: This test relies on the relative line numbers inside the test. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) line_offset = 8 # The difference in the set_break call and line_3. db.set_break( self.filename, sys._getframe().f_lineno + line_offset, ) cmd_manager.user_wait(0.2) line_1 = line_2 = line_3 = False with Timeout(0.1, False): db.set_trace(stop=False) # Should not stop us here. line_1 = True line_2 = True line_3 = True # Since we are stepping, we should not hit this line. self.assertTrue(line_1) self.assertTrue(line_2) # We should have still stopped at this breakpoint if we are tracing. self.assertFalse(line_3) db.disable() db = Qdb(cmd_manager=NopCommandManager()) line_1 = False with Timeout(0.1, False): db.set_trace(stop=False) line_1 = True self.assertTrue(line_1)
def get_events_from_socket(sck): """ Yields valid events from the server socket. """ while True: try: rlen = sck.recv(4) if len(rlen) != 4: return rlen = unpack('>i', rlen)[0] bytes_received = 0 resp = b'' with Timeout(1, False): while bytes_received < rlen: resp += sck.recv(rlen - bytes_received) bytes_received = len(resp) if bytes_received != rlen: return # We are not getting bytes anymore. if PY3: resp = resp.decode('utf-8') cmd = json.loads(resp) if cmd['e'] == 'disabled': # We are done tracing. return except (socket.error, ValueError) as e: # We can no longer talk the the server. log.warn('Exception raised reading from socket') yield fmt_err_msg('socket', str(e)) return except KeyError: log.warn('Client sent invalid cmd.') yield fmt_err_msg('event', "No 'e' field sent") return else: # Yields only valid commands. yield cmd
def start(self, tracer, auth_msg=''): """ Begins processing commands from the server. """ self.pipe, child_end = self._pipe() self._socket_connect(tracer) self.reader = self._start_process( target=ServerReader, args=(child_end, os.getpid(), self.socket.fileno(), tracer.pause_signal), ) with Timeout(5, QdbFailedToConnect(tracer.address, tracer.retry_attepts)): # Receive a message to know that the reader is ready to begin. while True: try: self.pipe.get() break except IOError as e: # EAGAIN says to try the syscall again. if e.errno != errno.EAGAIN: raise self.send( fmt_msg( 'start', { 'uuid': tracer.uuid, 'auth': auth_msg, 'local': (0, 0), }, serial=json.dumps, ) ) signal.signal( tracer.pause_signal, partial(self._pause_handler, tracer) ) atexit.register(self.stop)
def test_temporary_breakpoint(self): """ Tests conditional breakpoints. WARNING: This test relies on the relative line numbers inside the test. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.user_wait(0.2) loop_counter = 0 line_offset = 6 db.set_break( self.filename, sys._getframe().f_lineno + line_offset, temporary=True, ) with Timeout(0.1, False): db.set_trace(stop=False) while loop_counter < 10: loop_counter += 1 # By hitting it the first time, we cleared the breakpoint and did not # stop there again. self.assertEqual(loop_counter, 10)
def test_timout_isinstance(self, green): """ Asserts that the Timeout smart constructor returns are instances of Timeout. """ self.assertIsInstance(Timeout(1, green=green), Timeout)
def test_set_continue_with_breaks(self): """ Tests the behavior of continue when there are breakpoints in the mix. WARNING: This test relies on the relative line numbers inside the test. """ cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) line_offset = 8 # The difference in the set_break call and line_2. db.set_break( self.filename, sys._getframe().f_lineno + line_offset, ) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.user_wait(0.2) line_1 = line_2 = line_3 = False with Timeout(0.1, False): db.set_trace() line_1 = True line_2 = True line_3 = True # Assert we only got to line_1 because of the breakpoint. # These are split up to give more helpful messages if the test fails. self.assertTrue(line_1) self.assertFalse(line_2) self.assertFalse(line_3) # We are still in stepping mode so we should be reporting the stack. self.assertEqual( db.get_line(self.filename, db.curframe.f_lineno), ' db.get_line(self.filename, db.curframe.f_lineno),' ) sys.settrace(None) db.disable() cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager) line_2_offset = 13 # The difference in the set_break call and line_2. line_3_offset = 10 # THe difference in the set_break call and line_3. db.set_break( self.filename, sys._getframe().f_lineno + line_2_offset, ) db.set_break( self.filename, sys._getframe().f_lineno + line_3_offset, ) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.enqueue(lambda t: t.set_continue()) cmd_manager.user_wait(0.2) line_1 = line_2 = line_3 = False with Timeout(0.1, False): db.set_trace() line_1 = True line_2 = True line_3 = True self.assertTrue(line_1) self.assertTrue(line_2) self.assertFalse(line_3) self.assertEqual( db.get_line(self.filename, db.curframe.f_lineno), ' db.get_line(self.filename, db.curframe.f_lineno),' )
def test_timout_isinstance(self, no_gevent): """ Asserts that the Timeout smart constructor returns are instances of Timeout. """ self.assertIsInstance(Timeout(1, no_gevent=no_gevent), Timeout)