2
# Author: Facundo Batista <facundo@canonical.com>
4
# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
6
# Copyright 2009 Canonical Ltd.
8
# This program is free software: you can redistribute it and/or modify it
9
# under the terms of the GNU General Public License version 3, as published
10
# by the Free Software Foundation.
12
# This program is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranties of
14
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15
# PURPOSE. See the GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License along
18
# with this program. If not, see <http://www.gnu.org/licenses/>.
20
'''Tests for the Event Queue.'''
25
from ubuntuone.syncdaemon import (
29
from contrib.testing import testcase
30
from twisted.internet import defer
33
class BaseEQTestCase(testcase.BaseTwistedTestCase):
34
''' Setup an EQ for test. '''
38
testcase.BaseTwistedTestCase.setUp(self)
39
self.fsmdir = self.mktemp('fsmdir')
40
self.root_dir = self.mktemp('root_dir')
41
self.fs = filesystem_manager.FileSystemManager(self.fsmdir,
42
testcase.FakeVolumeManager(self.root_dir))
43
mdobj = self.fs.create(path=self.root_dir,
44
share_id='', is_dir=True)
45
self.fs.set_by_path(path=self.root_dir,
46
local_hash=None, server_hash=None)
47
self.eq = event_queue.EventQueue(self.fs)
50
'''Clean up the tests.'''
51
testcase.BaseTwistedTestCase.tearDown(self)
55
class SubscriptionTests(BaseEQTestCase):
56
'''Test to subscribe and unsubscribe to the EQ.'''
58
def test_subscription(self):
59
'''Test that subscription works.'''
63
self.assertTrue(o in self.eq._listeners)
69
self.assertTrue(self.eq._listeners.count(o) == 1)
71
def test_unsubscription(self):
72
'''Test that unsubscription works.'''
76
self.eq.unsubscribe(o)
77
self.assertFalse(o in self.eq._listeners)
79
# duplicate ok (two suscs)
83
self.eq.unsubscribe(o)
84
self.assertFalse(o in self.eq._listeners)
86
# duplicate error (two unsuscs)
90
self.eq.unsubscribe(o)
91
self.assertRaises(ValueError, self.eq.unsubscribe, o)
96
self.eq.unsubscribe(o)
98
self.eq.unsubscribe(o)
99
self.assertFalse(o in self.eq._listeners)
102
class PushTests(BaseEQTestCase):
103
'''Test the event distribution machinery.'''
105
def test_push_simple(self):
106
'''Test that events can be pushed (not listening yet).'''
108
self.assertRaises(TypeError, self.eq.push)
111
self.assertRaises(event_queue.InvalidEventError,
112
self.eq.push, "no-such-event")
114
# not enough or incorrect args for that event
115
self.assertRaises(TypeError, self.eq.push, "FS_FILE_MOVE")
116
self.assertRaises(TypeError, self.eq.push, "FS_FILE_MOVE", 1, 2, 3)
117
self.assertRaises(TypeError,
118
self.eq.push, "FS_FILE_MOVE", 1, 2, path_to=3)
119
self.assertRaises(TypeError,
120
self.eq.push, "FS_FILE_MOVE", 1, path_from=2, path_to=3)
122
# all ok... args, kwargs, and mixed
123
self.eq.push("FS_FILE_MOVE", 1, 2)
124
self.eq.push("FS_FILE_MOVE", path_from=1, path_to=2)
125
self.eq.push("FS_FILE_MOVE", 1, path_to=2)
127
def test_listened_pushs(self):
128
'''Push events and listem them.'''
130
# helper class, pylint: disable-msg=C0111
134
def handle_FS_FILE_CREATE(self, a):
140
self.eq.push("FS_FILE_CREATE", 1)
141
self.assertEqual(c.a, 1)
142
self.eq.unsubscribe(c)
144
# don't get what don't listen
147
self.eq.push("FS_FILE_DELETE", 1)
148
self.assertEqual(c.a, None)
149
self.eq.unsubscribe(c)
151
def test_signatures(self):
152
'''Check that the handle signatures are forced when passing.'''
154
# helper class, pylint: disable-msg=C0111
156
def handle_FS_FILE_CREATE(self, a, b): # it should be only 'a' here
164
self.assertRaises(TypeError, self.eq.push, "FS_FILE_CREATE")
165
self.assertRaises(TypeError, self.eq.push, "FS_FILE_CREATE", 1, 2)
167
# approved by EQ, but the listener has a wrong signature
168
# this is logged as an error/exception, so we hook to the logger
169
handler = testcase.MementoHandler()
170
handler.setLevel(logging.ERROR)
171
self.eq.log.addHandler(handler)
173
self.eq.push("FS_FILE_CREATE", 1)
174
self.assertEquals(1, len(handler.records))
175
self.assertEquals('FS_FILE_CREATE', handler.records[0].args[0])
176
self.assertEquals(C, type(handler.records[0].args[1]))
178
self.eq.log.removeHandler(handler)
179
self.eq.unsubscribe(c)
182
class PushTestsWithCallback(BaseEQTestCase):
183
'''Test the error handling in the event distribution machinery.'''
185
def test_keep_going(self):
186
''' Check that if a listener raises an Exception or have a
187
wrong signature, the next listeners are called.
190
# helper class, pylint: disable-msg=C0111
191
class BadListener(object):
192
def handle_FS_FILE_CREATE(self, a, b): # it should be only 'a' here
195
class GoodListener(object):
196
def handle_FS_FILE_CREATE(self, a):
201
self.eq.subscribe(bl)
202
self.eq.subscribe(gl)
205
""" unsubscribe the listeners """
206
self.eq.unsubscribe(bl)
207
self.eq.unsubscribe(gl)
208
self.addCleanup(cleanup)
211
self.assertRaises(TypeError, self.eq.push, "FS_FILE_CREATE")
212
self.assertRaises(TypeError, self.eq.push, "FS_FILE_CREATE", 1, 2)
214
# approved by EQ, but one listener has a wrong signature
215
self.eq.push("FS_FILE_CREATE", 1)
216
def callback(result):
217
""" asserts that GoodListener was called. """
218
self.assertTrue(result)
219
self.assertEquals(1, result)
221
d.addCallback(callback)
224
def test_default_handler(self):
225
''' Check that handler_default is called. '''
227
# helper class, pylint: disable-msg=C0111
228
class Listener(object):
229
def handle_default(self, *args, **kwargs):
236
""" unsubscribe the listeners """
237
self.eq.unsubscribe(l)
238
self.addCleanup(cleanup)
240
# push some event and expect it'll be handled by handle_default
241
self.eq.push("FS_FILE_CREATE", 1)
242
def callback(result):
243
""" asserts that GoodListener was called. """
244
self.assertEquals(2, len(result))
245
self.assertEquals('FS_FILE_CREATE', result[0])
246
self.assertEquals(1, result[1])
248
d.addCallback(callback)
251
def test_ordered_dispatch(self):
252
""" Check that the events are pushed to all listeners in order. """
254
# helper class, pylint: disable-msg=C0111
255
class Listener(object):
256
def __init__(self, eq):
260
def handle_FS_FILE_CREATE(self, a):
261
self.events.append('FS_FILE_CREATE')
262
self.eq.push('FS_FILE_MOVE', a, 2)
264
def handle_FS_FILE_DELETE(self, a):
265
self.events.append('FS_FILE_DELETE')
267
def handle_FS_FILE_MOVE(self, *args):
268
self.events.append('FS_FILE_MOVE')
271
# create 10 listeners in order to create an event madness
273
for i in xrange(0, 10):
274
l = Listener(self.eq)
279
""" unsubscribe the listeners """
281
self.eq.unsubscribe(l)
282
self.addCleanup(cleanup)
284
# push some events to unleash the event madness
285
self.eq.push("FS_FILE_CREATE", 1)
286
self.eq.push('FS_FILE_DELETE', 2)
288
def callback(result):
289
""" asserts that Listener was called in the right order"""
290
listeners_events = [listener.events for listener in listeners]
291
for l_events in listeners_events:
292
for other_l_events in listeners_events:
293
self.assertEqual(l_events, other_l_events)
295
d.addCallback(callback)
300
# pylint: disable-msg=C0111
301
return unittest.TestLoader().loadTestsFromName(__name__)
303
if __name__ == "__main__":