Permalink
Browse files

client: cleanup PIL import handling

  • Loading branch information...
1 parent f73d5e2 commit 874e4e6eedb0aa71aa8ae90b1bd59876634d8833 Marc Sibson committed Feb 2, 2011
Showing with 104 additions and 35 deletions.
  1. +84 −14 tests/test_client.py
  2. +20 −21 vncdotool/client.py
View
@@ -1,27 +1,97 @@
-class TestClient(object):
+import mock
+from nose.plugins.skip import SkipTest
+
+from vncdotool.client import VNCDoToolClient, VNCDoToolFactory
+from vncdotool import rfb
+
+class TestVNCDoToolClient(object):
def setUp(self):
- pass
+ self.client = VNCDoToolClient()
+ self.client.transport = mock.Mock()
+ self.client.factory = mock.Mock()
+
+ # mock out a bunch of base class functions
+ self.client.framebufferUpdateRequest = mock.Mock
+ self.client.pointerEvent = mock.Mock()
+ self.client.keyEvent = mock.Mock()
+
+ def _tryPIL(self):
+ try:
+ import PIL
+ except ImportError:
+ raise SkipTest
- def test_keyPress_single(self):
- self.client.keyPress('a')
+ def test_vncConnectionMade(self):
+ self.client.vncConnectionMade()
+ factory = self.client.factory
+ factory.clientConnectionMade.assert_called_once_with(self.client)
+
+ def test_keyPress_single_alpha(self):
+ client = self.client
+ client.keyPress('a')
+ client.keyEvent.assert_a_call_exists_with(ord('a'), down=1)
+ client.keyEvent.assert_a_call_exists_with(ord('a'), down=0)
def test_keyPress_multiple(self):
- self.client.keyPress('ctrl-alt-del')
+ client = self.client
+ client.keyPress('ctrl-alt-del')
- def test_capture(self):
- self.client.capture('foo.png')
+ # XXX doesn't ensure correct order
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_ControlLeft, down=1)
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_AltLeft, down=1)
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_Delete, down=1)
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_ControlLeft, down=0)
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_AltLeft, down=0)
+ client.keyEvent.assert_a_call_exists_with(rfb.KEY_Delete, down=0)
- def test_capture_no_pil(self):
- self.client.capture('foo.png')
+ def test_captureScreen(self):
+ self.client.vncConnectionMade()
+ self.client.captureScreen('foo.png')
def test_multiple_captures(self):
- self.client.capture('foo.png')
- self.client.capture('bar.png')
+ self._tryPIL()
+ self.client.vncConnectionMade()
+ self.client.captureScreen('foo.png')
+ self.client.captureScreen('bar.png')
def test_expect_initial_match(self):
- self.client.expect('bar.png')
+ self._tryPIL()
+ self.client.vncConnectionMade()
+ return # XXX
+ self.client.expectScreen('bar.png')
def test_expect_blocks_until_match(self):
- pass
- self.client.expect('bar.png')
+ self._tryPIL()
+ self.client.vncConnectionMade()
+ return # XXX
+ self.client.expectScreen('bar.png')
# thousands of misses
+
+class TestVNCDoToolFactory(object):
+
+ def setUp(self):
+ self.factory = VNCDoToolFactory()
+
+ def test_init(self):
+ assert self.factory.deferred
+
+ def test_clientConnectionMade(self):
+ deferred = mock.Mock()
+ protocol = mock.Mock()
+ self.factory.deferred = deferred
+
+ self.factory.clientConnectionMade(protocol)
+
+ deferred.callback.assert_called_once_with(protocol)
+ assert self.factory.deferred is None
+
+ def test_clientConnectionFailed(self):
+ deferred = mock.Mock()
+ self.factory.deferred = deferred
+ reason = mock.Mock()
+ connector = mock.Mock()
+
+ self.factory.clientConnectionFailed(connector, reason)
+
+ deferred.errback.assert_called_once_with(reason)
+ assert self.factory.deferred is None
View
@@ -93,7 +93,6 @@ class VNCDoToolClient(rfb.RFBClient):
x = 0
y = 0
screen = None
- image = None
def keyPress(self, key):
""" Send a key press to the server
@@ -131,7 +130,6 @@ def captureScreen(self, filename):
"""
# request initial screen update
self.framebufferUpdateRequest()
-
d = self.updates.get()
d.addCallback(self._captureSave, filename)
@@ -150,11 +148,7 @@ def expectScreen(self, filename, maxrms=0):
screen and target image
"""
self.framebufferUpdateRequest()
-
- # lazy PIL, avoids breaking others
- from PIL import Image
- self.expected = Image.open(filename).histogram()
-
+ self.expected = self.image().open(filename).histogram()
self.deferred = Deferred()
d = self.updates.get()
d.addCallback(self._expectCompare, maxrms)
@@ -190,16 +184,22 @@ def log(self, fmt, *args):
if self.factory.logger:
self.factory.logger(fmt, *args)
+ def image(self):
+ """ Wrap importing PIL.Image so vncdotool can be used without
+ PIL being installed. Of course capture and expect won't work
+ but at least we can still offer key, type, press and move.
+ """
+ from PIL import Image
+ return Image
+
+
#
# base customizations
#
def vncConnectionMade(self):
self.setPixelFormat()
- self.factory.deferred.callback(self)
-
- def framebufferUpdateRequest(self):
self.updates = DeferredQueue()
- rfb.RFBClient.framebufferUpdateRequest(self)
+ self.factory.clientConnectionMade(self)
def bell(self):
print 'ding'
@@ -212,14 +212,8 @@ def paste(self, message):
return self
def updateRectangle(self, x, y, width, height, data):
- # lazy PIL import, allows other commands to work even if PIL
- # isn't installed
- if not self.image:
- from PIL import Image
- self.image = Image
-
size = (width, height)
- update = self.image.fromstring('RGB', size, data, 'raw', 'RGBX')
+ update = self.image().fromstring('RGB', size, data, 'raw', 'RGBX')
if not self.screen:
self.screen = update
# track screen upward screen resizes, often occur during os boot
@@ -232,14 +226,19 @@ def updateRectangle(self, x, y, width, height, data):
class VNCDoToolFactory(rfb.RFBFactory):
- protocol = VNCDoToolClient
+ logger = None
password = None
+
+ protocol = VNCDoToolClient
shared = 1
- logger = None
def __init__(self):
self.deferred = Deferred()
def clientConnectionFailed(self, connector, reason):
- reactor.callLater(0, self.deferred.errback, reason)
+ self.deferred.errback(reason)
+ self.deferred = None
+
+ def clientConnectionMade(self, protocol):
+ self.deferred.callback(protocol)
self.deferred = None

0 comments on commit 874e4e6

Please sign in to comment.