Example #1
0
    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'
        )
Example #2
0
    def test_set_continue_no_breaks(self):
        """
        Asserts that set_continue works with no breakpoints.
        """
        db = Qdb(cmd_manager=QueueCommandManager)

        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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'
        )
Example #3
0
    def test_set_step(self):
        """
        Tests the functionality of set_step by asserting that it only executes
        the next line and no more.
        """
        db = Qdb(cmd_manager=QueueCommandManager)

        # Queue up a step command.
        db.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()

        db = Qdb(cmd_manager=QueueCommandManager)

        db.cmd_manager.enqueue(lambda t: t.set_step())
        db.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)
Example #4
0
    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.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        line_offset = 8  # The difference in the set_break call and line_3.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
        )
        db.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)
Example #5
0
    def test_eval_state_update(self):
        """
        Tests that eval may update the state of the program.
        """
        # We will try to corrupt this variable with a stateful operation.
        test_var = 'pure'  # NOQA

        db = Qdb(
            uuid='eval_test',
            cmd_manager=self.cmd_manager,
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
            green=True,
        )
        gyield()
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('eval', "test_var = 'mutated'")
        )
        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.assertEqual(test_var, 'mutated')
Example #6
0
    def test_eval_pprint(self, input_, exc, output):
        """
        Tests that evaling code returns the proper results.
        """
        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})

        db = Qdb(
            uuid='eval_test',
            cmd_manager=cmd_manager(),
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
        )
        gyield()
        self.server.session_store.send_to_tracer(uuid=db.uuid,
                                                 event=fmt_msg(
                                                     'pprint', input_))
        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'], input_)
        self.assertEqual(print_['exc'], exc)
        self.assertEqual(print_['output'], output)
Example #7
0
    def test_eval_state_update(self):
        """
        Tests that eval may update the state of the program.
        """
        # We will try to corrupt this variable with a stateful operation.
        test_var = 'pure'  # NOQA

        db = Qdb(
            uuid='eval_test',
            cmd_manager=self.cmd_manager,
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
        )
        sleep(0.01)
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('eval', "test_var = 'mutated'")
        )
        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.assertEqual(test_var, 'mutated')
Example #8
0
    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'
        )
Example #9
0
 def test_is_singleton(self):
     """
     Tests that two newly created Qdb objects are the same.
     """
     self.assertIs(
         Qdb(cmd_manager=NopCommandManager()),
         Qdb(cmd_manager=NopCommandManager())
     )
Example #10
0
    def test_stack_transpose_no_skip(self, direction):
        """
        Tests moving up the stack.
        """
        events = []

        def capture_event(self, event, payload):
            events.append(fmt_msg(event, payload))

        class cmd_manager(type(self.cmd_manager)):
            """
            Wrap send_stack by just capturing the output to make assertions on
            it.
            """
            def send_stack(self, tracer):
                with patch.object(cmd_manager, 'send_event', capture_event):
                    super(cmd_manager, self).send_stack(tracer)

        db = Qdb(
            uuid='test_' + direction,
            cmd_manager=cmd_manager(),
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
            green=True,
        )
        gyield()
        if direction == 'down':
            # We are already located in the bottom frame, let's go up one
            # so that we may try going down.
            self.server.session_store.send_to_tracer(
                uuid=db.uuid,
                event=fmt_msg('up')
            )

        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg(direction)
        )
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('disable', 'soft')
        )
        gyield()
        db.set_trace()

        start_ind = events[-2]['p']['index']
        shift_ind = events[-1]['p']['index']

        if direction == 'up':
            self.assertEqual(start_ind - shift_ind, 1)
        elif direction == 'down':
            self.assertEqual(shift_ind - start_ind, 1)
        else:
            self.fail("direction is not 'up' or 'down'")  # wut did u do?
Example #11
0
    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))
        )
Example #12
0
    def test_send_stack_results(self, use_skip_fn):
        """
        Tests that the results from sending the stack are accurate.
        WARNING: This test uses lines of it's own source as string literals,
        be sure to edit the source and the string if you make any changes.
        """
        def skip_fn(filename):
            return not fix_filename(__file__) in filename

        events = []

        def capture_event(self, event, payload):
            events.append(fmt_msg(event, payload))

        class cmd_manager(type(self.cmd_manager)):
            """
            Wrap send_stack by just capturing the output to make assertions on
            it.
            """
            def send_stack(self, tracer):
                with patch.object(cmd_manager, 'send_event', capture_event):
                    super(cmd_manager, self).send_stack(tracer)

        db = Qdb(
            uuid='send_stack_test',
            cmd_manager=cmd_manager(),
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
            skip_fn=skip_fn if use_skip_fn else None,
            green=True,
        )
        gyield()
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('continue')
        )
        db.set_trace(stop=True)
        self.assertTrue(events)  # EDIT IN BOTH PLACES

        event = events[0]
        if use_skip_fn:
            # Assert that we actually suppressed some frames.
            self.assertTrue(len(event['p']['stack']) < len(db.stack))

        self.assertEqual(
            # I love dictionaries so much!
            event['p']['stack'][event['p']['index']]['code'],
            '        self.assertTrue(events)  # EDIT IN BOTH PLACES',
        )

        self.server.session_store.slaughter(db.uuid)
Example #13
0
    def test_set_trace_with_stop(self):
        """
        Asserts that calling set_trace will put us into stepping mode.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        db.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)
Example #14
0
    def test_set_trace_with_stop(self):
        """
        Asserts that calling set_trace will put us into stepping mode.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        db.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)
Example #15
0
    def test_set_step(self):
        """
        Tests the functionality of set_step by asserting that it only executes
        the next line and no more.
        """
        db = Qdb(cmd_manager=QueueCommandManager)

        # Queue up a step command.
        db.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()

        db = Qdb(cmd_manager=QueueCommandManager)

        db.cmd_manager.enqueue(lambda t: t.set_step())
        db.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)
Example #16
0
    def test_clear_break(self):
        """
        Tests clearing a breakpoint.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        clear_break_offset = 14
        set_break_offset = 8
        db.cmd_manager.enqueue(lambda t: t.clear_break(
            self.filename,
            sys._getframe().f_lineno + clear_break_offset))
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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 xrange(2):
                pass
            continued = True

        self.assertTrue(continued)
Example #17
0
    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])
Example #18
0
    def test_as_ctx_mgr(self):
        """
        Tests the debugger as a context manager.
        """
        line_1 = False
        cmd_stop = None
        with patch.object(NopCommandManager, 'start') as cmd_start, \
                patch.object(NopCommandManager, 'stop') as cmd_stop, \
                Qdb(cmd_manager=NopCommandManager()) as db:
            db.set_trace()
            cmd_start.assert_called_once_with(db, '')
            line_1 = True
            self.assertTrue(line_1)
            self.assertIs(Qdb._instance, db)
            self.assertEqual(
                db.get_line(
                    self.filename,
                    db.curframe.f_lineno),
                '                    db.curframe.f_lineno),'
            )

        # Assert the __exit__ clears the singleton so a new one can be used.
        self.assertIs(Qdb._instance, None)
        # Assert that __exit__ stopped the command manager.
        cmd_stop.assert_called_once_with()
Example #19
0
    def test_pause(self):
        """
        Asserts that sending a pause to the process will raise the pause signal
        in the tracer process.
        """
        pause_called = [False]

        def pause_handler(signal, stackframe):
            """
            Pause handler that marks that we made it into this function.
            """
            pause_called[0] = True

        db = Qdb(
            cmd_manager=self.cmd_manager,
            host=self.tracer_host,
            port=self.tracer_port,
            green=True,
        )
        signal.signal(db.pause_signal, pause_handler)
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('pause')
        )

        self.assertTrue(pause_called)
Example #20
0
    def test_conditional_breakpoint_raises(self):
        """
        Tests conditional breakpoints that raise an exception.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        line = None
        exc = ValueError('lol wut r u doing?')
        cond = 'raiser()'

        stopped = [False]

        def stop():
            stopped[0] = True
            return True  # Execute the assertion.

        cmd_manager = QueueCommandManager()
        db = Qdb(cmd_manager=cmd_manager)
        cmd_manager.enqueue(lambda t: stop() and self.assertEqual(line, 1))
        line_offset = 9
        # Set a condition that will raise a ValueError.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
            cond=cond,
        )
        db.set_trace(stop=False)

        def raiser():
            raise exc

        line = 1
        line = 2  # This line number is used in the data assertion.
        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 = 13
        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])
Example #21
0
 def test_conditional_breakpoint(self):
     """
     Tests valid conditional breakpoints.
     WARNING: This test relies on the relative line numbers inside the test.
     """
     db = Qdb(cmd_manager=QueueCommandManager)
     loop_counter = 0
     db.cmd_manager.enqueue(lambda t: self.assertEqual(loop_counter, 5))
     line_offset = 5
     db.set_break(
         self.filename,
         sys._getframe().f_lineno + line_offset,
         cond='loop_counter == 5'
     )
     db.set_trace(stop=False)
     while loop_counter < 10:
         loop_counter += 1
Example #22
0
    def test_redirect_stderr(self):
        """
        Tests that stderr is stored on the tracer.
        """
        sys.stderr = stderr = StringIO()
        db = Qdb(cmd_manager=NopCommandManager)

        data_to_write = 'stderr'
        db.set_trace(stop=False)

        print >> sys.stderr, data_to_write,  # Write some data to stderr.

        db.disable()
        self.assertEqual(db.stderr.getvalue(), data_to_write)

        # Assert that the stream was restored.
        self.assertIs(sys.stderr, stderr)
Example #23
0
    def test_clear_break(self):
        """
        Tests clearing a breakpoint.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        clear_break_offset = 14
        set_break_offset = 8
        db.cmd_manager.enqueue(lambda t: t.clear_break(
            self.filename,
            sys._getframe().f_lineno + clear_break_offset
        ))
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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 xrange(2):
                pass
            continued = True

        self.assertTrue(continued)
Example #24
0
 def test_why_are_you_executing_all_these_commands(self):
     db = Qdb(
         uuid='send_stack_test',
         cmd_manager=self.cmd_manager,
         host=self.tracer_host,
         port=self.tracer_port,
         redirect_output=False,
         green=True,
     )
     gyield()
     for n in range(sys.getrecursionlimit()):
         self.server.session_store.send_to_tracer(uuid=db.uuid,
                                                  event=fmt_msg(
                                                      'eval', 'None'))
     self.server.session_store.send_to_tracer(uuid=db.uuid,
                                              event=fmt_msg('continue'))
     with gevent.Timeout(1):
         db.set_trace(stop=True)
Example #25
0
    def test_eval_results(self, input_, exc, output):
        """
        Tests that evaling code returns the proper results.
        """
        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
                })

        db = Qdb(
            uuid='eval_test',
            cmd_manager=cmd_manager(),
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
            green=True,
        )
        gyield()
        self.server.session_store.send_to_tracer(
            uuid=db.uuid,
            event=fmt_msg('eval', input_)
        )
        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'], input_)
        self.assertEqual(print_['exc'], exc)
        self.assertEqual(print_['output'], output)
Example #26
0
    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])
Example #27
0
    def test_conditional_breakpoint_raises(self):
        """
        Tests conditional breakpoints that raise an exception.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        line = None
        exc = ValueError('lol wut r u doing?')
        cond = 'raiser()'

        stopped = [False]

        def stop():
            stopped[0] = True
            return True  # Execute the assertion.

        cmd_manager = QueueCommandManager()
        db = Qdb(cmd_manager=cmd_manager)
        cmd_manager.enqueue(lambda t: stop() and self.assertEqual(line, 1))
        line_offset = 9
        # Set a condition that will raise a ValueError.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
            cond=cond,
        )
        db.set_trace(stop=False)

        def raiser():
            raise exc

        line = 1
        line = 2  # This line number is used in the data assertion.
        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 = 13
        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])
Example #28
0
    def test_file_cache_from_string(self):
        """
        Asserts that manual caching from a string works.
        """
        contents = dedent(
            """\
            line 1
            line 2
            line 3
            line 4
            """
        )
        db = Qdb(cmd_manager=NopCommandManager())
        db.cache_file('file', contents=contents)

        # Check the whole 'file'.
        self.assertEquals(db.get_file('file'), contents[:-1])  # drop '\n'

        for n in range(1, 5):
            # Check all the lines.
            self.assertEquals('line %d' % n, db.get_line('file', n))
Example #29
0
 def test_why_are_you_executing_all_these_commands(self):
     db = Qdb(
         uuid='send_stack_test',
         cmd_manager=self.cmd_manager,
         host=self.tracer_host,
         port=self.tracer_port,
         redirect_output=False,
         green=True,
     )
     gyield()
     for n in range(sys.getrecursionlimit()):
         self.server.session_store.send_to_tracer(
             uuid=db.uuid,
             event=fmt_msg('eval', 'None')
         )
     self.server.session_store.send_to_tracer(
         uuid=db.uuid,
         event=fmt_msg('continue')
     )
     with gevent.Timeout(1):
         db.set_trace(stop=True)
Example #30
0
    def test_redirect_stdout(self):
        """
        Tests that stdout is stored on the tracer.
        """
        sys.stdout = stdout = StringIO()
        db = Qdb(cmd_manager=OutputCatchingNopCommandManager)

        data_to_write = 'stdout'
        db.set_trace(stop=False)

        print data_to_write,  # Write some data to stdout.

        db.disable()
        msg = db.cmd_manager.msgs[0]
        self.assertEqual(msg.input_, '<stdout>')
        self.assertFalse(msg.exc)
        self.assertEqual(msg.output, data_to_write)
        self.assertEqual(stdout.getvalue(), data_to_write)

        # Assert that the stream was restored.
        self.assertIs(sys.stdout, stdout)
Example #31
0
    def test_inject_default_ns_no_trample(self):
        """
        Tests adding the default namespace does not override a defined name.
        """
        ns = {'a': 1, 'b': 2}

        with Qdb(cmd_manager=NopCommandManager, default_namespace=ns) as db, \
                db.inject_default_namespace(sys._getframe()):
            a = 'a'
            b = 'b'
            self.assertEqual(a, 'a')
            self.assertEqual(b, 'b')
Example #32
0
    def test_file_cache_from_disk(self):
        """
        Asserts that the disk caching works.
        """
        # We will use this file, as it is the only file we know that exists.
        # The first time this is run after a change, __file__ will point to
        # the source code file; however, if we run this twice in a row, it
        # points to the byte-compiled file.
        filename = fix_filename(__file__)
        db = Qdb(cmd_manager=NopCommandManager())
        db.cache_file(filename)

        with open(filename) as f:
            contents = f.read()[:-1]  # Drop the last newline.

            # Assert that querying the entire file works.
            self.assertEquals(db.get_file(filename), contents)

            for n, line in zip(count(start=1), contents.splitlines()):
                # Iterate over all the lines of the file, asserting that we
                # have saved them correctly. This also asserts that the line
                # indexing is working as intended.
                self.assertEquals(db.get_line(filename, n), line)
Example #33
0
    def test_send_disabled(self):
        """
        Tests that disabling sends a 'disabled' message back to the server.
        """
        class cmd_manager(self.cmd_manager):
            disabled = False

            def send_disabled(self):
                self.disabled = True

        db = Qdb(
            uuid='send_disabled_test',
            cmd_manager=cmd_manager,
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
        )
        sleep(0.01)
        db.set_trace(stop=False)
        db.disable()

        self.assertTrue(db.cmd_manager.disabled)
        self.server.session_store.slaughter(db.uuid)
Example #34
0
    def test_temporary_breakpoint(self):
        """
        Tests conditional breakpoints.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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)
Example #35
0
    def test_redirect_stderr(self):
        """
        Tests that stderr is stored on the tracer.
        """
        sys.stderr = stderr = StringIO()
        cmd_manager = OutputCatchingNopCommandManager()
        db = Qdb(cmd_manager=cmd_manager)

        data_to_write = 'stderr'
        db.set_trace(stop=False)

        # Write some data to stderr.
        print(data_to_write, end='', file=sys.stderr)

        db.disable()

        msg = cmd_manager.msgs[0]
        self.assertEqual(msg.input_, '<stderr>')
        self.assertFalse(msg.exc)
        self.assertEqual(msg.output, data_to_write)
        self.assertEqual(stderr.getvalue(), data_to_write)

        # Assert that the stream was restored.
        self.assertIs(sys.stderr, stderr)
Example #36
0
    def test_inject_default_ns(self):
        """
        Tests adding a default namespace to a frame.
        """
        ns = {'a': 1, 'b': 2}

        # rip pyflakes
        with Qdb(cmd_manager=NopCommandManager, default_namespace=ns) as db, \
                db.inject_default_namespace(sys._getframe()):
            self.assertEqual(a, 1)  # NOQA
            self.assertEqual(b, 2)  # NOQA

        # Assert that the namespace was cleaned.
        with self.assertRaises(NameError):
            a  # NOQA

        with self.assertRaises(NameError):
            b  # NOQA
Example #37
0
    def test_inject_default_ns_curframe(self):
        """
        Tests adding a default namespace to the curframe.
        """
        ns = {'a': 1, 'b': 2}

        # rip pyflakes
        with Qdb(cmd_manager=NopCommandManager, default_namespace=ns) as db:
            db.curframe = sys._getframe()
            with db.inject_default_namespace():
                self.assertEqual(a, 1)  # NOQA
                self.assertEqual(b, 2)  # NOQA

            with self.assertRaises(NameError):
                a  # NOQA

            with self.assertRaises(NameError):
                b  # NOQA
Example #38
0
 def test_conditional_breakpoint(self):
     """
     Tests valid conditional breakpoints.
     WARNING: This test relies on the relative line numbers inside the test.
     """
     db = Qdb(cmd_manager=QueueCommandManager)
     loop_counter = 0
     db.cmd_manager.enqueue(lambda t: self.assertEqual(loop_counter, 5))
     line_offset = 5
     db.set_break(self.filename,
                  sys._getframe().f_lineno + line_offset,
                  cond='loop_counter == 5')
     db.set_trace(stop=False)
     while loop_counter < 10:
         loop_counter += 1
Example #39
0
    def test_clear_output_buffers(self):
        """
        Tests that we can clear the output buffers to free up some memory.
        """

        db = Qdb(cmd_manager=NopCommandManager)
        stdout_data, stderr_data = 'stdout', 'stderr'
        db.set_trace(stop=False)

        print stdout_data,
        print >> sys.stderr, stderr_data,

        db.disable()

        # Assert that the data actually got written.
        self.assertEqual(db.stdout.getvalue(), stdout_data)
        self.assertEqual(db.stderr.getvalue(), stderr_data)

        db.clear_output_buffers()

        # Assert that the data actually got cleared.
        self.assertEqual(db.stdout.getvalue(), '')
        self.assertEqual(db.stderr.getvalue(), '')
Example #40
0
    def test_redirect_stderr(self):
        """
        Tests that stderr is stored on the tracer.
        """
        sys.stderr = stderr = StringIO()
        db = Qdb(cmd_manager=NopCommandManager)

        data_to_write = 'stderr'
        db.set_trace(stop=False)

        print >> sys.stderr, data_to_write,  # Write some data to stderr.

        db.disable()
        self.assertEqual(db.stderr.getvalue(), data_to_write)

        # Assert that the stream was restored.
        self.assertIs(sys.stderr, stderr)
Example #41
0
    def test_file_cache_from_string(self):
        """
        Asserts that manual caching from a string works.
        """
        contents = dedent("""\
            line 1
            line 2
            line 3
            line 4
            """)
        db = Qdb(cmd_manager=NopCommandManager())
        db.cache_file('file', contents=contents)

        # Check the whole 'file'.
        self.assertEquals(db.get_file('file'), contents[:-1])  # drop '\n'

        for n in range(1, 5):
            # Check all the lines.
            self.assertEquals('line %d' % n, db.get_line('file', n))
Example #42
0
    def test_clear_output_buffers(self):
        """
        Tests that we can clear the output buffers to free up some memory.
        """

        db = Qdb(cmd_manager=NopCommandManager)
        stdout_data, stderr_data = 'stdout', 'stderr'
        db.set_trace(stop=False)

        print stdout_data,
        print >> sys.stderr, stderr_data,

        db.disable()

        # Assert that the data actually got written.
        self.assertEqual(db.stdout.getvalue(), stdout_data)
        self.assertEqual(db.stderr.getvalue(), stderr_data)

        db.clear_output_buffers()

        # Assert that the data actually got cleared.
        self.assertEqual(db.stdout.getvalue(), '')
        self.assertEqual(db.stderr.getvalue(), '')
Example #43
0
    def test_file_cache_from_disk(self):
        """
        Asserts that the disk caching works.
        """
        # We will use this file, as it is the only file we know that exists.
        # The first time this is run after a change, __file__ will point to
        # the source code file; however, if we run this twice in a row, it
        # points to the byte-compiled file.
        filename = fix_filename(__file__)
        db = Qdb(cmd_manager=NopCommandManager())
        db.cache_file(filename)

        with open(filename) as f:
            contents = f.read()[:-1]  # Drop the last newline.

            # Assert that querying the entire file works.
            self.assertEqual(db.get_file(filename), contents)

            for n, line in zip(count(start=1), contents.splitlines()):
                # Iterate over all the lines of the file, asserting that we
                # have saved them correctly. This also asserts that the line
                # indexing is working as intended.
                self.assertEqual(db.get_line(filename, n), line)
Example #44
0
    def test_redirect_stdout(self):
        """
        Tests that stdout is stored on the tracer.
        """
        sys.stdout = stdout = StringIO()
        cmd_manager = OutputCatchingNopCommandManager()
        db = Qdb(cmd_manager=cmd_manager)

        data_to_write = 'stdout'
        db.set_trace(stop=False)

        # Write some data to stdout.
        print(data_to_write, end='')

        db.disable()
        msg = cmd_manager.msgs[0]
        self.assertEqual(msg.input_, '<stdout>')
        self.assertFalse(msg.exc)
        self.assertEqual(msg.output, data_to_write)
        self.assertEqual(stdout.getvalue(), data_to_write)

        # Assert that the stream was restored.
        self.assertIs(sys.stdout, stdout)
Example #45
0
    def test_temporary_breakpoint(self):
        """
        Tests conditional breakpoints.
        WARNING: This test relies on the relative line numbers inside the test.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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)
Example #46
0
    def test_send_disabled(self):
        """
        Tests that disabling sends a 'disabled' message back to the server.
        """
        class cmd_manager(self.cmd_manager):
            disabled = False

            def send_disabled(self):
                self.disabled = True

        db = Qdb(
            uuid='send_disabled_test',
            cmd_manager=cmd_manager,
            host=self.tracer_host,
            port=self.tracer_port,
            redirect_output=False,
        )
        sleep(0.01)
        db.set_trace(stop=False)
        db.disable()

        self.assertTrue(db.cmd_manager.disabled)
        self.server.session_store.slaughter(db.uuid)
Example #47
0
    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.
        """
        db = Qdb(cmd_manager=QueueCommandManager)

        # Queue up a next command to next over the function call.
        db.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.
        db.cmd_manager.user_wait(0.2)

        # A mutable structure to check if f is called.
        f_called = [False]

        def f():
            f_called[0] = 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[0])

        # 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()
        db = Qdb(cmd_manager=QueueCommandManager)

        f_called[0] = False

        # This time we will be only stepping, so we should not execute the
        # entire call to f.
        db.cmd_manager.enqueue(lambda t: t.set_step())
        db.cmd_manager.user_wait(0.2)

        with Timeout(0.1, False):
            db.set_trace()
            f()

        # We should not have hit this line in f.
        self.assertFalse(f_called[0])
        # 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[0] = True')
Example #48
0
    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.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        line_offset = 8  # The difference in the set_break call and line_2.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
        )
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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 = Qdb(cmd_manager=QueueCommandManager)
        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,
        )
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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),')
Example #49
0
    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.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        line_offset = 8  # The difference in the set_break call and line_3.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
        )
        db.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)
Example #50
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()
Example #51
0
    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.
        """
        db = Qdb(cmd_manager=QueueCommandManager)
        line_offset = 8  # The difference in the set_break call and line_2.
        db.set_break(
            self.filename,
            sys._getframe().f_lineno + line_offset,
        )
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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 = Qdb(cmd_manager=QueueCommandManager)
        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,
        )
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.cmd_manager.enqueue(lambda t: t.set_continue())
        db.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),'
        )
Example #52
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()