test debugger coverage 66 try to make tests pass with draft bdbx which may replace bdb in 3 13 a test python script for the debug tests testcode dedent i 1 i 2 if i 3 printi create test and code objects to simulate a debug session won t test super call since two bdbs are very different test that userline creates a string message for a frame test that userexception creates a string message for a frame test module functions together test the loadbreakpoints method calls idb test that syncsourceline will set the flist gotofileline with fixed frame tests for debugger debugger that need tk root close needs debugger top set in makegui stack tests fail with debugger here cls debugger debugger debuggercls pyshell cls idb cls debugger root root real root needed for real makegui run interacting abortloop real root needed for real makegui run interacting abortloop test closing the window in an idle state reset the stackviewer to force it to be recreated check that the newly created stackviewer has the test gui as a field create a stackviewer and load the test stack test creation of stackviewer test the loadstack method against a fixed test stack check the test stack is assigned and the list contains the repr of them test the showsource method against a fixed test stack patch out the file list to monitor it patch out isfile to pretend file exists a test python script for the debug tests i 1 i 2 if i 3 print i create test and code objects to simulate a debug session won t test super call since two bdbs are very different test that user_line creates a string message for a frame test that user_exception creates a string message for a frame test module functions together test the load_breakpoints method calls idb call set_breakpoint 5 times test that sync_source_line will set the flist gotofileline with fixed frame tests for debugger debugger that need tk root close needs debugger top set in make_gui stack tests fail with debugger here cls debugger debugger debugger cls pyshell cls idb cls debugger root root real root needed for real make_gui run interacting abort_loop real root needed for real make_gui run interacting abort_loop test closing the window in an idle state reset the stackviewer to force it to be recreated check that the newly created stackviewer has the test gui as a field create a stackviewer and load the test stack test creation of stackviewer test the load_stack method against a fixed test stack check the test stack is assigned and the list contains the repr of them test the show_source method against a fixed test stack patch out the file list to monitor it patch out isfile to pretend file exists
from idlelib import debugger
from collections import namedtuple
from textwrap import dedent
from tkinter import Tk

from test.support import requires
import unittest
from unittest import mock
from unittest.mock import Mock, patch


TEST_CODE = dedent()


class MockFrame:
    "Minimal mock frame."

    def __init__(self, code, lineno):
        self.f_code = code
        self.f_lineno = lineno


class IdbTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.gui = Mock()
        cls.idb = debugger.Idb(cls.gui)

        
        code_obj = compile(TEST_CODE, 'idlelib/file.py', mode='exec')
        frame1 = MockFrame(code_obj, 1)
        frame1.f_back = None
        frame2 = MockFrame(code_obj, 2)
        frame2.f_back = frame1
        cls.frame = frame2
        cls.msg = 'file.py:2: <module>()'

    def test_init(self):
        self.assertIs(self.idb.gui, self.gui)
        

    def test_user_line(self):
        
        self.gui.interaction = Mock()
        self.idb.user_line(self.frame)
        self.gui.interaction.assert_called_once_with(self.msg, self.frame)

    def test_user_exception(self):
        
        exc_info = (type(ValueError), ValueError(), None)
        self.gui.interaction = Mock()
        self.idb.user_exception(self.frame, exc_info)
        self.gui.interaction.assert_called_once_with(
                self.msg, self.frame, exc_info)


class FunctionTest(unittest.TestCase):
    

    def test_functions(self):
        rpc_obj = compile(TEST_CODE,'rpc.py', mode='exec')
        rpc_frame = MockFrame(rpc_obj, 2)
        rpc_frame.f_back = rpc_frame
        self.assertTrue(debugger._in_rpc_code(rpc_frame))
        self.assertEqual(debugger._frame2message(rpc_frame),
                         'rpc.py:2: <module>()')

        code_obj = compile(TEST_CODE, 'idlelib/debugger.py', mode='exec')
        code_frame = MockFrame(code_obj, 1)
        code_frame.f_back = None
        self.assertFalse(debugger._in_rpc_code(code_frame))
        self.assertEqual(debugger._frame2message(code_frame),
                         'debugger.py:1: <module>()')

        code_frame.f_back = code_frame
        self.assertFalse(debugger._in_rpc_code(code_frame))
        code_frame.f_back = rpc_frame
        self.assertTrue(debugger._in_rpc_code(code_frame))


class DebuggerTest(unittest.TestCase):
    "Tests for Debugger that do not need a real root."

    @classmethod
    def setUpClass(cls):
        cls.pyshell = Mock()
        cls.pyshell.root = Mock()
        cls.idb = Mock()
        with patch.object(debugger.Debugger, 'make_gui'):
            cls.debugger = debugger.Debugger(cls.pyshell, cls.idb)
        cls.debugger.root = Mock()

    def test_cont(self):
        self.debugger.cont()
        self.idb.set_continue.assert_called_once()

    def test_step(self):
        self.debugger.step()
        self.idb.set_step.assert_called_once()

    def test_quit(self):
        self.debugger.quit()
        self.idb.set_quit.assert_called_once()

    def test_next(self):
        with patch.object(self.debugger, 'frame') as frame:
            self.debugger.next()
            self.idb.set_next.assert_called_once_with(frame)

    def test_ret(self):
        with patch.object(self.debugger, 'frame') as frame:
            self.debugger.ret()
            self.idb.set_return.assert_called_once_with(frame)

    def test_clear_breakpoint(self):
        self.debugger.clear_breakpoint('test.py', 4)
        self.idb.clear_break.assert_called_once_with('test.py', 4)

    def test_clear_file_breaks(self):
        self.debugger.clear_file_breaks('test.py')
        self.idb.clear_all_file_breaks.assert_called_once_with('test.py')

    def test_set_load_breakpoints(self):
        
        FileIO = namedtuple('FileIO', 'filename')

        class MockEditWindow(object):
            def __init__(self, fn, breakpoints):
                self.io = FileIO(fn)
                self.breakpoints = breakpoints

        self.pyshell.flist = Mock()
        self.pyshell.flist.inversedict = (
            MockEditWindow('test1.py', [4, 4]),
            MockEditWindow('test2.py', [13, 44, 45]),
        )
        self.debugger.set_breakpoint('test0.py', 1)
        self.idb.set_break.assert_called_once_with('test0.py', 1)
        self.debugger.load_breakpoints()  
        self.idb.set_break.assert_has_calls(
            [mock.call('test0.py', 1),
             mock.call('test1.py', 4),
             mock.call('test1.py', 4),
             mock.call('test2.py', 13),
             mock.call('test2.py', 44),
             mock.call('test2.py', 45)])

    def test_sync_source_line(self):
        
        test_code = compile(TEST_CODE, 'test_sync.py', 'exec')
        test_frame = MockFrame(test_code, 1)
        self.debugger.frame = test_frame

        self.debugger.flist = Mock()
        with patch('idlelib.debugger.os.path.exists', return_value=True):
            self.debugger.sync_source_line()
        self.debugger.flist.gotofileline.assert_called_once_with('test_sync.py', 1)


class DebuggerGuiTest(unittest.TestCase):
    

    @classmethod
    def setUpClass(cls):
        requires('gui')
        cls.root = root = Tk()
        root.withdraw()
        cls.pyshell = Mock()
        cls.pyshell.root = root
        cls.idb = Mock()






    @classmethod
    def tearDownClass(cls):
        cls.root.destroy()
        del cls.root

    def setUp(self):
        self.debugger = debugger.Debugger(self.pyshell, self.idb)
        self.debugger.root = self.root
        
        

    def test_run_debugger(self):
        self.debugger.run(1, 'two')
        self.idb.run.assert_called_once_with(1, 'two')
        self.assertEqual(self.debugger.interacting, 0)

    def test_close(self):
        
        self.debugger.close()
        self.pyshell.close_debugger.assert_called_once()

    def test_show_stack(self):
        self.debugger.show_stack()
        self.assertEqual(self.debugger.stackviewer.gui, self.debugger)

    def test_show_stack_with_frame(self):
        test_frame = MockFrame(None, None)
        self.debugger.frame = test_frame

        
        self.debugger.stackviewer = None
        self.idb.get_stack.return_value = ([], 0)
        self.debugger.show_stack()

        
        self.assertEqual(self.debugger.stackviewer.gui, self.debugger)
        self.idb.get_stack.assert_called_once_with(test_frame, None)


class StackViewerTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        requires('gui')
        cls.root = Tk()
        cls.root.withdraw()

    @classmethod
    def tearDownClass(cls):
        cls.root.destroy()
        del cls.root

    def setUp(self):
        self.code = compile(TEST_CODE, 'test_stackviewer.py', 'exec')
        self.stack = [
            (MockFrame(self.code, 1), 1),
            (MockFrame(self.code, 2), 2)
        ]
        
        self.sv = debugger.StackViewer(self.root, None, None)
        self.sv.load_stack(self.stack)

    def test_init(self):
        
        gui = None
        flist = None
        master_window = self.root
        sv = debugger.StackViewer(master_window, flist, gui)
        self.assertTrue(hasattr(sv, 'stack'))

    def test_load_stack(self):
        
        
        self.assertEqual(self.sv.stack, self.stack)
        self.assertTrue('?.<module>(), line 1:' in self.sv.get(0))
        self.assertEqual(self.sv.get(1), '?.<module>(), line 2: ')

    def test_show_source(self):
        
        
        self.sv.flist = Mock()
        
        with patch('idlelib.debugger.os.path.isfile', return_value=True) as isfile:
            self.sv.show_source(1)
            isfile.assert_called_once_with('test_stackviewer.py')
            self.sv.flist.open.assert_called_once_with('test_stackviewer.py')


class NameSpaceTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        requires('gui')
        cls.root = Tk()
        cls.root.withdraw()

    @classmethod
    def tearDownClass(cls):
        cls.root.destroy()
        del cls.root

    def test_init(self):
        debugger.NamespaceViewer(self.root, 'Test')


if __name__ == '__main__':
    unittest.main(verbosity=2)