[Python-checkins] r47090 - in sandbox/trunk/pdb: README.txt mconnection.py mpdb.py test/test_mconnection.py test/test_mpdb.py

matt.fleming python-checkins at python.org
Sat Jun 24 17:52:00 CEST 2006


Author: matt.fleming
Date: Sat Jun 24 17:51:59 2006
New Revision: 47090
Modified:
 sandbox/trunk/pdb/README.txt
 sandbox/trunk/pdb/mconnection.py
 sandbox/trunk/pdb/mpdb.py
 sandbox/trunk/pdb/test/test_mconnection.py
 sandbox/trunk/pdb/test/test_mpdb.py
Log:
Started to fix unit tests and introduce some more to test the top-level
routines. Fixed and unclear statement in README.txt
Modified: sandbox/trunk/pdb/README.txt
==============================================================================
--- sandbox/trunk/pdb/README.txt	(original)
+++ sandbox/trunk/pdb/README.txt	Sat Jun 24 17:51:59 2006
@@ -25,10 +25,9 @@
 * Lightweight and heavyweight mechanism for setting up threads
 - The reason we want a lightweight mechanism is so that we can
 	place mpdb.set_trace() inside a script so that we can debug
-	any threads created with the threading module. It has to be
-	lighweight because the programmer might not want all the features
-	of an MPdb instance, if for example they only care about debugging
-	this one thread instance.
+	the script. It has to be lighweight because the programmer
+	might not want all the features of an MPdb instance, if for example
+	they only care about debugging this one thread instance.
 	- We need a heavyweight mechanism to allow a programmer to inspect
 	and control all threads.
 * Provide a proper top-level methods including, set_trace(), post_mortem(),
Modified: sandbox/trunk/pdb/mconnection.py
==============================================================================
--- sandbox/trunk/pdb/mconnection.py	(original)
+++ sandbox/trunk/pdb/mconnection.py	Sat Jun 24 17:51:59 2006
@@ -155,7 +155,6 @@
 """Connect to the server. 'input' reads data from the
 server. 'output' writes data to the server. Specify the
 address of the server (e.g. host:2020). """
-
 h, p = addr.split(':')
 self.host = h
 self.port = int(p)
Modified: sandbox/trunk/pdb/mpdb.py
==============================================================================
--- sandbox/trunk/pdb/mpdb.py	(original)
+++ sandbox/trunk/pdb/mpdb.py	Sat Jun 24 17:51:59 2006
@@ -53,11 +53,13 @@
 self.waiter = threading.Event()
 self.tracers = []
 self.threads = []
+ self._info_cmds.append('target')
 
 def _rebind_input(self, new_input):
 """ This method rebinds the debugger's input to the object specified
 by 'new_input'.
 """
+ self.stdin.flush()
 self.use_rawinput = False
 self.stdin = new_input
 
@@ -84,7 +86,7 @@
 # The output from the command that we've just sent to the server
 # is returned along with the prompt of that server. So we keep reading
 # until we find our prompt.
- while self.prompt not in ret:
+ while self.local_prompt not in ret:
 ret += self.connection.readline()
 self.msg_nocr(ret)
 return
@@ -110,31 +112,32 @@
 return
 
 args = arg.split()
- if 'target'.startswith(args[0]):
+ if 'target'.startswith(args[0]) and len(args[0]) > 2:
 self.msg("target is %s" % self.target)
- else:
- pydb.Pdb.do_info(self, arg)
-
- def do_thread(self, arg):
- """ Enable thread debugging. """
- # XXX Rocky, how are we subclassing info/set commands? This will do
- # for now.
- if arg == 'info':
+ elif 'thread'.startswith(args[0]) and len(args[0])> 2:
 if not self.debug_thread:
 self.msg('Thread debugging is not on.')
 return
- # XXX We need to remove old threads once the script has finished
- # and currently, we don't.
+ # We need some way to remove old thread instances
 self.msg(self.threads)
 return
- if arg == 'debug':
- # We do not continue with the main thread for as long as there
- # is another thread running. (Will change later so you can choose
- # between threads).
+ else:
+ pydb.Pdb.do_info(self, arg)
+
+
+ def do_set(self, arg):
+ """ Extends pydb do_set() to allow setting thread debugging. """
+ if not arg:
+ pydb.Pdb.do_set(self, arg)
+ return
+
+ args = arg.split()
+ if 'thread'.startswith(args[0]):
 threading.settrace(self.thread_trace_dispatch)
- self.msg('Thread debugging on.')
+ self.msg('Thread debugging on')
 self.debug_thread = True
 return
+ 
 
 def thread_trace_dispatch(self, frame, event, arg):
 """ Create an MTracer object so trace the thread. """
@@ -197,14 +200,12 @@
 try:
 from mconnection import (MConnectionClientTCP,
 ConnectionFailed)
- # Matt - Where are the connection parameters? 
 self.connection = MConnectionClientTCP()
 
 except ImportError:
 self.msg('Could not import MConnectionClientTCP')
 return
 elif target == 'serial':
- # Matt - Where are the connection parameters? 
 if self.connection: self.connection.disconnect()
 try:
 from mconnection import (MConnectionSerial,
@@ -234,10 +235,14 @@
 return
 # This interpreter no longer interprets commands but sends
 # them straight across this object's connection to a server.
- self.prompt = "" # Get our prompt from the server now
+ # XXX: In the remote_onecmd method we use the local_prompt string
+ # to find where the end of the message from the server is. We
+ # really need a way to get the prompt from the server for checking
+ # in remote_onecmd, because it may be different to this client's.
+ self.local_prompt = self.prompt
+ self.prompt = ""
 line = self.connection.readline()
 self.msg_nocr(line)
- self._rebind_output(self.connection)
 self.onecmd = self.remote_onecmd
 self.target = 'remote'
 
@@ -306,39 +311,52 @@
 self._rebind_input(self.connection)
 self._rebind_output(self.connection)
 
-def pdbserver(protocol, address, filename):
+def pdbserver(addr):
 """ This method sets up a pdbserver debugger that allows debuggers
 to connect to 'address' using 'protocol'. The argument 'filename'
 is the name of the file that is being debugged.
 """
- pass
- 
-
-def target(protocol, address):
- """ Connect to a pdbserver at 'address' using 'protocol'. """
- pass
-
+ m = MPdb()
+ position = addr.rfind(' ')
+ mainpyfile = addr[position+1:]
+ m.mainpyfile = mainpyfile
+ m.do_pdbserver(addr)
+ m._runscript(mainpyfile)
+ sys.exit()
+
+def target(addr):
+ """ Connect this debugger to a pdbserver at 'addr'. 'addr' is
+ a protocol-specific address. i.e.
+ tcp = 'tcp mydomainname.com:9876'
+ serial = '/dev/ttyC0'
+ """
+ m = MPdb()
+ # Look Ma, no script!
+ m.do_target(addr)
+ while True:
+ try:
+ m.cmdloop()
+ except:
+ sys.exit()
 
 def main():
 """ Main entry point to this module. """
 opts, args = parse_opts()
- if not opts.scriptname:
- if not args[0]:
- print 'Error: mpdb.py must be called with a script name!'
- sys.exit(1)
- else:
- mainpyfile = args[0]
- if not os.path.exists(mainpyfile):
- print 'Error:', mainpyfile, 'does not exist'
- sys.exit(1)
- if opts.remote:
- if not opts.protocol:
- print 'Protocol must be specified for remote debugging'
+ if opts.target:
+ target(opts.target)
+ elif opts.pdbserver:
+ pdbserver(opts.pdbserver)
+ else:
+ if not opts.scriptname:
+ if not args:
+ print 'Error: mpdb.py must be called with a script name if ' \
+ + '-p or -t switches are not specified.'
+ sys.exit(1)
+ else:
+ mainpyfile = args[0]
+ if not os.path.exists(mainpyfile):
+ print 'Error:', mainpyfile, 'does not exist'
 sys.exit(1)
- if not opts.debugger:
- pdbserver(opts.protocol, opts.address, mainpyfile)
- else:
- target(opts.protocol, opts.address)
 mpdb = MPdb()
 while 1:
 try:
@@ -368,23 +386,14 @@
 parser = OptionParser()
 parser.add_option("-s", "--script", dest="scriptname",
 help="The script to debug")
- parser.add_option("-l", "--local-debugee", dest="local",
- action="store_true",
- help="This script is to be debugged locally, from " + \
- "another process")
- parser.add_option("-p", "--protocol", dest="protocol",
- help="The protocol to use for remote communication")
- parser.add_option("-r", "--remote-debugee", dest="remote",
- action="store_true",
- help="This script is to be debugged by a remote " + \
- "debugger")
- parser.add_option("-a", "--address", dest="address", 
- help="The protocol-specific address of this debugger")
- parser.add_option("-d", "--debugger", dest="debugger",
- action="store_true",
- help="Invoke the debugger.")
+ parser.add_option("-t", "--target", dest="target",
+ help="Specify a target to connect to. The arguments" \
+ + " should be of form, 'protocol address'.")
+ parser.add_option("-p", "--pdbserver", dest="pdbserver",
+ help="Start the debugger and execute the pdbserver " \
+ + "command. The arguments should be of the form," \
+ + " 'protocol address scriptname'.")
 (options, args) = parser.parse_args()
- # We don't currently support any arguments
 return (options,args)
 
 if __name__ == '__main__':
Modified: sandbox/trunk/pdb/test/test_mconnection.py
==============================================================================
--- sandbox/trunk/pdb/test/test_mconnection.py	(original)
+++ sandbox/trunk/pdb/test/test_mconnection.py	Sat Jun 24 17:51:59 2006
@@ -87,6 +87,12 @@
 """(tcp) Test connection refused error. """
 self.assertRaises(ConnectionFailed, self.client.connect, __addr__)
 
+ def testInvalidAddressPortPair(self):
+ """(tcp) Test invald hostname, port pair. """
+ addr = 'localhost 8000'
+ # Rocky: Should this be a ValueError or some other sort of exception?
+ self.assertRaises(ValueError, self.server.connect, addr)
+
 def tearDown(self):
 self.server.disconnect()
 self.client.disconnect()
Modified: sandbox/trunk/pdb/test/test_mpdb.py
==============================================================================
--- sandbox/trunk/pdb/test/test_mpdb.py	(original)
+++ sandbox/trunk/pdb/test/test_mpdb.py	Sat Jun 24 17:51:59 2006
@@ -10,28 +10,22 @@
 # Global vars
 __addr__ = 'localhost:8002'
 script = ""
-g_server = None
-g_client = None
-CONNECTED = False
-# Commands to execute on the server
-cmds = ['info target', 'help', 'quit']
+MAXTRIES = 100
 
 sys.path.append("..")
-from mpdb import MPdb
+from mpdb import MPdb, pdbserver, target
+
+TESTFN = 'tester'
+
+def connect_to_target(client, address=None):
+ if address is None:
+ address = __addr__
+ client.do_target('tcp '+address)
+
+ while 'Failed' in client.lines[0]:
+ client.lines = []
+ client.do_target('tcp '+address)
 
-def doTargetConnect(cmds=None):
- global g_client
- while True:
- try:
- g_client.do_target('tcp '+__addr__)
- if CONNECTED:
- break
- except socket.error:
- pass
- if cmds:
- for c in cmds:
- g_client.onecmd(c)
- 
 class MPdbTest(MPdb):
 def __init__(self):
 MPdb.__init__(self)
@@ -44,36 +38,68 @@
 """ Test Case to make sure debugging remotely works properly. """
 def setUp(self):
 self.server = MPdb()
- global g_client
- g_client = MPdbTest()
+ self.client = MPdbTest()
 
 def tearDown(self):
- global CONNECTED
- self.server.connection.disconnect()
- CONNETED = False
- 
- def testPdbserver(self):
- """ Test the pdbserver command. """
- global CONNECTED
+ if self.server.connection:
+ self.server.connection.disconnect()
+ import os
+ if TESTFN in os.listdir('.'):
+ os.unlink(TESTFN)
+
+# Whilst a lot of the tests below seem to duplicate tests from
+# test_mconnection, we need to make sure that the methods that mpdb provides
+# are not having side effects, and causing tests that should pass to fail
+# and vice versa.
 
- self.server_tid = thread.start_new_thread(doTargetConnect, ())
+ def testPdbserver(self):
+ """ Test the pdbserver. """
+ thread.start_new_thread(connect_to_target, (self.client,))
 self.server.do_pdbserver('tcp '+__addr__+' '+script)
- CONNECTED = True
+ self.assertEquals('remote', self.server.target)
 
- def testCommandsOnServer(self):
- """ Test all supported commands on the pdbserver.
- """
- global CONNECTED, g_client
- 
- self.server_tid = thread.start_new_thread(doTargetConnect, (cmds,))
- self.server.do_pdbserver('tcp '+__addr__+' '+script)
- CONNECTED = True
- 
- # XXX mpdb needs a bottom frame before it exits
- self.server.botframe = None
- self.server.cmdloop()
+ def testTarget(self):
+ """ Test the target command. """
+ addr = 'tcp '+__addr__+' '+script
+ thread.start_new_thread(self.client.do_pdbserver, (addr,))
+
+ # There was a problem with earlier unit tests that they were
+ # working "by coincidence". This ensures that we don't "assume"
+ # the connection is ready until the target has changed from "local"
+ # to "remote".
+ connect_to_target(self.client, __addr__)
+ self.assertEquals('remote', self.client.target, 'Target is wrong.')
+
+
+ def testRebindOutput(self):
+ """ Test rebinding output. """
+ f = open(TESTFN, 'w+')
+ self.server._rebind_output(f)
+ self.server.msg('some text')
+ f.close()
+
+ f = open(TESTFN, 'r')
+ line = f.readline()
+ f.close()
+ self.assertEquals('some text\n', line, 'Could not rebind output')
+
+ def testRebindInput(self):
+ """ Test rebinding input. """
+ f = open(TESTFN, 'w+')
+ f.write('help')
+ f.close()
+
+ f = open(TESTFN, 'r')
+ self.server._rebind_input(f)
+ line = self.server.stdin.readline()
+
+ self.assertEquals(line, 'help', 'Could not rebind input.')
+
+ def testTargetRoutine(self):
+ """ Test that the top-level target routine works properly. """
+ invalid_address = 'tcp ::::::'
+ self.assertRaises(ValueError, target, invalid_address)
 
- self.assertEquals('target is remote\n', g_client.lines[1])
 
 def test_main():
 test_support.run_unittest(TestRemoteDebugging)


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /