Skip to content
Browse files

create better ui by breaking vnclog out from vncdo

  • Loading branch information...
1 parent 554d955 commit 15f65f12b85a1678243375055a2ff1555064c128 @sibson committed
View
33 README.rst
@@ -79,37 +79,38 @@ The file format is simply a collection of actions::
> echo "type hello" | vncdo -
- > cat some_file.vdo
+ > cat login.vdo
# select the name text box, enter your name and submit
move 100 100 click 1 type "my name" key tab key enter
# grab the result
capture screenshot.png
- > vncdo some_file.vdo
+ > vncdo login.vdo
Creating long lists of commands can be time consuming so vncdotool provides
-a record mode that logs messages and screen captures.
+a log mode that records a users interactions to a file, which you can then
+playback with vncdo.
For best results set your client to use the RAW encoding.
-Others encoding may work but are not fully supported at this time.
+Others encoding may work but are not fully supported at this time.::
-As the log is a text file you can edit it to tweak the behaviour.::
+ > vnclog keylog.vdo
+ > vncviewer localhost:2 # do something and then exit viewer
+ > vncdo keylog.vdo
- > vncdo record 6000 vnc.vdo
- > vncviewer localhost:6000
- > sed -i s/click 1/click 2/ vnc.vdo
- > vncdo vnc.vdo
+If its too hard to remember which port to use you can tell vncdotool to
+launch a client that will be connected to the vnclog session.::
-It may be more convient to automatically launch a VNC client connected to vncdotool in record mode with::
+ > vnclog --viewer vncviewer keylog.vdo
- > vncdo viewer somefile.vdo
-
-By running in service mode vncdotool will create a new file for every client connection and record each clients activity.
+By running with --forever vncdotool will create a new file for every client
+connection and record each clients activity.
This can be useful for quickly recording a number of testcases.::
- > vncdo service 6000
- > vncviewer localhost:6000 # then exit and start new session
- > vncviewer localhost:6000
+ > vnclog --forever --listen 6000 /tmp
+ > vncviewer localhost::6000 # then exit and start new session
+ > vncviewer localhost::6000
+ > ls /tmp/*.vdo
Feedback
--------------------------------
View
0 debian/vncrecordd.default → debian/vnclogd.default
File renamed without changes.
View
2 debian/vncrecordd.upstart → debian/vnclogd.upstart
@@ -20,5 +20,5 @@ script
. $DEFAULTFILE
fi
- /usr/bin/vncdotool --logfile $LOGFILE -o $OUTPUT_DIR -s $SERVER $VNCDOTOOL_FLAGS service $PORT
+ /usr/bin/vnclog --forever --logfile $LOGFILE -s $SERVER $VNCDOTOOL_FLAGS --listen $PORT $OUTPUT
end script
View
5 setup.py
@@ -23,8 +23,9 @@
entry_points={
"console_scripts": [
- 'vncdo=vncdotool.command:main',
- 'vncdotool=vncdotool.command:main',
+ 'vncdo=vncdotool.command:vncdo',
+ 'vncdotool=vncdotool.command:vncdo',
+ 'vnclog=vncdotool.command:vnclog',
],
},
packages=['vncdotool'],
View
27 tests/functional/test_proxy.py
@@ -1,6 +1,8 @@
-import pexpect
import unittest
import sys
+
+import pexpect
+
from vncdotool import rfb
@@ -10,18 +12,19 @@ def setUp(self):
self.server = pexpect.spawn(cmd, timeout=2)
self.server.logfile_read = sys.stdout
- cmd = 'vncdo -d 99 record 1842 -'
- self.logger = pexpect.spawn(cmd, timeout=2)
- self.logger.logfile_read = sys.stdout
+ cmd = 'vnclog --listen 1842 -s :99 -'
+ self.recorder = pexpect.spawn(cmd, timeout=2)
+ self.recorder.logfile_read = sys.stdout
def tearDown(self):
self.server.terminate(force=True)
- if self.logger:
- self.logger.terminate(force=True)
+ if self.recorder:
+ self.recorder.terminate(force=True)
def run_vncdo(self, commands):
- cmd = 'vncdo -s localhost:1842 ' + commands
- vnc = pexpect.spawn(cmd, logfile=sys.stdout, timeout=2)
+ cmd = 'vncdo -s localhost::1842 ' + commands
+ vnc = pexpect.spawn(cmd, timeout=2)
+ vnc.logfile_read = sys.stdout
retval = vnc.wait()
assert retval == 0, (retval, str(vnc))
@@ -43,8 +46,8 @@ def test_key_alpha(self):
self.assertKeyDown(ord('z'))
self.assertKeyUp(ord('z'))
- self.logger.expect('keydown z')
- self.logger.expect('keyup z')
+ self.recorder.expect('keydown z')
+ self.recorder.expect('keyup z')
def test_key_ctrl_a(self):
self.run_vncdo('key ctrl-a')
@@ -56,5 +59,5 @@ def test_key_ctrl_a(self):
def test_mouse(self):
self.run_vncdo('move 111 222 click 1')
self.assertMouse(111, 222, 1)
- self.logger.expect('move 111 222')
- self.logger.expect('click 1')
+ self.recorder.expect('move 111 222')
+ self.recorder.expect('click 1')
View
2 tests/functional/test_screen.py
@@ -35,7 +35,7 @@ def run_server(self, server):
self.server.logfile_read = sys.stdout
def run_vncdo(self, commands, exitcode=0):
- cmd = 'vncdo -d 10 ' + commands
+ cmd = 'vncdo -s :10 ' + commands
vnc = pexpect.spawn(cmd, logfile=sys.stdout, timeout=5)
vnc.logfile_read = sys.stdout
vnc.expect(pexpect.EOF)
View
5 tests/functional/test_send_events.py
@@ -13,8 +13,7 @@ class TestSendEvents(object):
def setUp(self):
cmd = 'vncev -rfbport 5933 -rfbwait 1000'
- self.server = pexpect.spawn(cmd, timeout=2)
- self.server.logfile_read = sys.stdout
+ self.server = pexpect.spawn(cmd, logfile=sys.stdout, timeout=2)
def tearDown(self):
self.server.terminate(force=True)
@@ -36,7 +35,7 @@ def assertDisconnect(self):
self.server.expect(disco)
def run_vncdo(self, commands):
- cmd = 'vncdo -d 33 ' + commands
+ cmd = 'vncdo -v -s :33 ' + commands
vnc = pexpect.spawn(cmd, logfile=sys.stdout, timeout=5)
retval = vnc.wait()
assert retval == 0, retval
View
49 tests/unit/test_command.py
@@ -154,14 +154,12 @@ def test_insert_delay(self):
self.assertEqual(self.deferred.addCallback.call_args_list, expected)
-class TestMain(object):
+class TestParseHost(object):
def setUp(self):
- self.isolation = mock.isolate.object(command.main)
+ self.isolation = mock.isolate.object(command.parse_host)
self.isolation.start()
- self.factory = command.VNCDoToolFactory.return_value
self.options = mock.Mock()
- self.options.display = 0
self.options.server = '127.0.0.1'
parse_args = command.VNCDoToolOptionParser.return_value.parse_args
parse_args.return_value = (self.options, [])
@@ -171,32 +169,37 @@ def tearDown(self):
self.isolation.stop()
self.isolation = None
- def test_single_host_name(self):
- self.options.server = '10.11.12.13'
- command.main()
- assert self.options.server == '10.11.12.13'
+ def test_default(self):
+ command.parse_host(self.options)
+ assert self.options.host == '127.0.0.1'
assert self.options.port == 5900
+ def test_host_display(self):
+ self.options.server = '10.11.12.13:10'
+ command.parse_host(self.options)
+ assert self.options.host == '10.11.12.13'
+ assert self.options.port == 5910
+
def test_host_port(self):
- self.options.server = '10.11.12.13:4444'
- command.main()
+ self.options.server = '10.11.12.13::4444'
+ command.parse_host(self.options)
assert self.options.host == '10.11.12.13'
assert self.options.port == 4444
- def test_localhost_display(self):
- self.options.display = 10
- command.main()
- assert self.options.host == '127.0.0.1'
- assert self.options.port == 5910
-
- def test_host_display(self):
+ def test_just_host(self):
self.options.server = '10.11.12.13'
- self.options.display = 10
- command.main()
- assert self.options.host == '10.11.12.13'
+ command.parse_host(self.options)
+ assert self.options.server == '10.11.12.13'
+ assert self.options.port == 5900
+
+ def test_just_display(self):
+ self.options.server = ':10'
+ command.parse_host(self.options)
+ assert self.options.host == '127.0.0.1'
assert self.options.port == 5910
- def test_host_default(self):
- command.main()
+ def test_just_port(self):
+ self.options.server = '::1111'
+ command.parse_host(self.options)
assert self.options.host == '127.0.0.1'
- assert self.options.port == 5900
+ assert self.options.port == 1111
View
179 vncdotool/command.py
@@ -36,8 +36,7 @@ def log_connected(pcol):
def error(reason):
- reason.printTraceback()
-
+ log.critical(reason.getErrorMessage())
reactor.exit_status = 10
reactor.stop()
@@ -163,64 +162,39 @@ def build_tool(options, args):
return factory
-def build_proxy(options, port=0):
+def build_proxy(options):
factory = VNCLoggingServerFactory(options.host, int(options.port))
- port = reactor.listenTCP(port, factory)
+ port = reactor.listenTCP(options.listen, factory)
reactor.exit_status = 0
- factory.listening = port.getHost().port
+ factory.listen_port = port.getHost().port
return factory
-def main():
- usage = '%prog [options] (CMD CMDARGS|-|filename)'
- description = 'Command line interaction with a VNC server'
-
+def build_optparser(usage, description):
op = VNCDoToolOptionParser(usage=usage, description=description)
op.disable_interspersed_args()
- op.add_option('--delay', action='store', metavar='MILLISECONDS',
- default=os.environ.get('VNCDOTOOL_DELAY', 0), type='int',
- help='delay MILLISECONDS between actions [%defaultms]')
-
op.add_option('-d', '--display', action='store', metavar='DISPLAY',
type='int', default=0,
help='connect to vnc server display :DISPLAY [%default]')
- op.add_option('--nocursor', action='store_true',
- help='no mouse pointer in screen captures')
-
- op.add_option('--localcursor', action='store_true',
- help='mouse pointer drawn client-side, useful when server does not include cursor')
-
- op.add_option('-o', '--output', metavar='PATH',
- default=tempfile.gettempdir(),
- help='store all output at PATH [%default]')
-
- op.add_option('-p', '--password', action='store', metavar='PASSwORD',
+ op.add_option('-p', '--password', action='store', metavar='PASSWORD',
help='use password to access server')
- op.add_option('-s', '--server', action='store', metavar='ADDRESS',
+ op.add_option('-s', '--server', action='store', metavar='SERVER',
default='127.0.0.1',
- help='connect to vnc server at ADDRESS[:PORT] [%default]')
+ help='connect to VNC server at ADDRESS[:DISPLAY|::PORT] [%default]')
op.add_option('--logfile', action='store', metavar='FILE',
help='output logging information to FILE')
op.add_option('-v', '--verbose', action='count')
- op.add_option('--viewer', action='store', metavar='CMD',
- default='vncviewer',
- help='Use CMD to launch viewer in session mode [%default]')
-
- op.add_option('-w', '--warp', action='store', type='float',
- metavar='FACTOR', default=1.0,
- help='pause time is accelerated by FACTOR [x%default]')
+ return op
- options, args = op.parse_args()
- if not len(args):
- op.error('no command provided')
+def setup_logging(options):
# route Twisted log messages via stdlib logging
if options.logfile:
handler = logging.handlers.RotatingFileHandler(options.logfile,
@@ -236,45 +210,110 @@ def main():
PythonLoggingObserver().start()
- try:
- options.host, options.port = options.server.split(':')
- except ValueError:
- options.host = options.server
- options.port = options.display + 5900
- options.port = int(options.port)
- log.info('connecting to %s:%s', options.host, options.port)
+def parse_host(options):
+ split = options.server.split(':')
- if 'record' in args:
- args.pop(0)
- port = int(args.pop(0))
- output = args.pop(0)
- factory = build_proxy(options, port)
- if output != '-':
- factory.output = open(output, 'w')
- elif 'service' in args:
- args.pop(0)
- port = int(args.pop(0))
- factory = build_proxy(options, port)
- factory.output = options.output
- elif 'viewer' in args:
- args.pop(0)
- output = args.pop(0)
- factory = build_proxy(options)
- if output == '-':
- factory.output = sys.stdout
- else:
- factory.output = open(output, 'w')
+ if not split[0]:
+ options.host = '127.0.0.1'
+ else:
+ options.host = split[0]
+
+ if len(split) == 3: # ::port
+ options.port = int(split[2])
+ elif len(split) == 2: # :display
+ options.port = int(split[1]) + 5900
+ else:
+ options.port = 5900
+
+ return options
+
+
+def vnclog():
+ usage = '%prog [options] OUTPUT'
+ description = 'Capture user interactions with a VNC Server'
+
+ op = build_optparser(usage, description)
+
+ op.add_option('--listen', metavar='PORT', type='int',
+ help='listen for client connections on PORT [%default]')
+ op.set_defaults(listen=5902)
+
+ op.add_option('--forever', action='store_true',
+ help='continually accept new connections')
+
+ op.add_option('--viewer', action='store', metavar='CMD',
+ help='launch an interactive client using CMD [%default]')
+
+ options, args = op.parse_args()
+
+ setup_logging(options)
- cmd = '%s localhost::%s' % (options.viewer, factory.listening)
+ parse_host(options)
+
+ if len(args) != 1:
+ op.error('incorrect number of arguments')
+ output = args[0]
+
+
+ factory = build_proxy(options)
+
+ if options.forever and os.path.isdir(output):
+ factory.output = output
+ elif options.forever:
+ op.error('--forever requires OUTPUT to be a directory')
+ elif output == '-':
+ factory.output = sys.stdout
+ else:
+ factory.output = open(output, 'w')
+
+ if options.listen == 0:
+ log.info('accepting connections on ::%d', factory.listen_port)
+
+ factory.password = options.password
+
+ if options.viewer:
+ cmdline = '%s localhost::%s' % (options.viewer, factory.listen_port)
proc = reactor.spawnProcess(ExitingProcess(),
- options.viewer, cmd.split(),
+ options.viewer, cmdline.split(),
env=os.environ)
- else:
- factory = build_tool(options, args)
- if options.password:
- factory.password = options.password
+ reactor.run()
+
+ sys.exit(reactor.exit_status)
+
+
+def vncdo():
+ usage = '%prog [options] (CMD CMDARGS|-|filename)'
+ description = 'Command line control of a VNC server'
+
+ op = build_optparser(usage, description)
+
+ op.add_option('--delay', action='store', metavar='MILLISECONDS',
+ default=os.environ.get('VNCDOTOOL_DELAY', 0), type='int',
+ help='delay MILLISECONDS between actions [%defaultms]')
+
+ op.add_option('--nocursor', action='store_true',
+ help='no mouse pointer in screen captures')
+
+ op.add_option('--localcursor', action='store_true',
+ help='mouse pointer drawn client-side, useful when server does not include cursor')
+
+ op.add_option('-w', '--warp', action='store', type='float',
+ metavar='FACTOR', default=1.0,
+ help='pause time is accelerated by FACTOR [x%default]')
+
+ options, args = op.parse_args()
+ if not len(args):
+ op.error('no command provided')
+
+ setup_logging(options)
+ parse_host(options)
+
+ log.info('connecting to %s:%s', options.host, options.port)
+
+ factory = build_tool(options, args)
+ factory.password = options.password
if options.nocursor:
factory.nocursor = True
@@ -288,4 +327,4 @@ def main():
if __name__ == '__main__':
- main()
+ vncdo()

0 comments on commit 15f65f1

Please sign in to comment.
Something went wrong with that request. Please try again.