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_eval_timeout(self): """ Tests that evaluating user repl commands will raise Timeouts. """ def g(): while True: pass prints = [] class cmd_manager(type(self.cmd_manager)): """ Captures print commands to make assertions on them. """ def send_print(self, input_, exc, output): prints.append({ 'input': input_, 'exc': exc, 'output': output }) to_eval = 'g()' db = Qdb( uuid='timeout_test', cmd_manager=cmd_manager(), host=self.tracer_host, port=self.tracer_port, redirect_output=False, execution_timeout=1, green=True, ) gyield() self.server.session_store.send_to_tracer( uuid=db.uuid, event=fmt_msg('eval', to_eval) ) self.server.session_store.send_to_tracer( uuid=db.uuid, event=fmt_msg('continue') ) db.set_trace(stop=True) self.server.session_store.slaughter(db.uuid) self.assertTrue(prints) print_ = prints[0] self.assertEqual(print_['input'], to_eval) self.assertTrue(print_['exc']) self.assertEqual( print_['output'], db.exception_serializer(QdbExecutionTimeout(to_eval, 1)) )
def test_conditional_breakpoint_timeout(self): """ Tests conditional breakpoints that cause timeouts. WARNING: This test relies on the relative line numbers inside the test. """ stopped = [False] def stop(): stopped[0] = True return True # Execute the assertion. line = None cond = 'g()' cmd_manager = QueueCommandManager() db = Qdb(cmd_manager=cmd_manager, execution_timeout=1) cmd_manager.enqueue(lambda t: stop() and self.assertEqual(line, 1)) line_offset = 10 # Set a condition that will time out. db.set_break( self.filename, sys._getframe().f_lineno + line_offset, cond='g()', ) db.set_trace(stop=False) def g(): while True: pass line = 1 line = 2 line = 3 db.disable() errors = [e['p'] for e in cmd_manager.sent if e['e'] == 'error'] self.assertEqual(len(errors), 1) error = errors[0] self.assertEqual(error['type'], 'condition') negative_line_offset = 14 exc = QdbExecutionTimeout(cond, db.execution_timeout) self.assertEqual( error['data'], { 'line': sys._getframe().f_lineno - negative_line_offset, 'cond': cond, 'exc': type(exc).__name__, 'output': db.exception_serializer(exc), } ) # Make sure we stopped when we raised the exception. self.assertTrue(stopped[0])
def test_watchlist(self): """ Tests the watchlist by evaluating a constant, local function, local variable, global function, and global variable. """ db = Qdb(cmd_manager=NopCommandManager, execution_timeout=1) too_long_msg = db.exception_serializer( QdbExecutionTimeout('too_long()', 1)) db.extend_watchlist( '2 + 2', 'local_var', 'local_fn()', 'global_var', 'global_fn()', 'too_long()', ) def new_curframe(): """ Test function for checking for NameErrors on the watchlist. This changes the curframe of the tracer to eval the watchlist with a new set of locals. """ self.assertEqual(db.watchlist['2 + 2'], (None, 4)) self.assertEqual( db.watchlist['local_var'], ('NameError', "NameError: name 'local_var' is not defined")) self.assertEqual( db.watchlist['local_fn()'], ('NameError', "NameError: name 'local_fn' is not defined")) self.assertEqual(db.watchlist['global_var'], (None, 'global_var')) self.assertEqual(db.watchlist['global_fn()'], (None, 'global_fn')) local_var = 'local_var' # NOQA local_fn = lambda: 'local_fn' # NOQA def too_long(): while True: pass # Set trace and check innitial assertions. db.set_trace() self.assertEqual(db.watchlist['2 + 2'], (None, 4)) self.assertEqual(db.watchlist['local_var'], (None, 'local_var')) self.assertEqual(db.watchlist['local_fn()'], (None, 'local_fn')) self.assertEqual(db.watchlist['global_var'], (None, 'global_var')) self.assertEqual(db.watchlist['global_fn()'], (None, 'global_fn')) # Testing this as a tuple causes strange behavior. self.assertEqual(db.watchlist['too_long()'][0], 'QdbExecutionTimeout') self.assertEqual(db.watchlist['too_long()'][1], too_long_msg) local_var = 'updated_local_var' # NOQA local_fn = lambda: 'updated_local_fn' # NOQA self.assertEqual(db.watchlist['2 + 2'], (None, 4)) self.assertEqual(db.watchlist['local_var'], (None, 'updated_local_var')) self.assertEqual(db.watchlist['local_fn()'], (None, 'updated_local_fn')) self.assertEqual(db.watchlist['global_var'], (None, 'global_var')) self.assertEqual(db.watchlist['global_fn()'], (None, 'global_fn')) new_curframe()