2
# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
3
# Author: Natalia B. Bidart <natalia.bidart@canonical.com>
5
# Copyright 2009-2010 Canonical Ltd.
7
# This program is free software: you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License version 3, as published
9
# by the Free Software Foundation.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranties of
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
# PURPOSE. See the GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License along
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
18
"""Base tests cases and test utilities."""
24
from dbus.mainloop.glib import DBusGMainLoop
25
from twisted.internet import defer
26
from twisted.python import failure
27
from twisted.trial.unittest import TestCase
30
class DBusTestCase(TestCase):
31
"""Test the DBus event handling."""
34
"""Setup the infrastructure fo the test (dbus service)."""
35
self.loop = DBusGMainLoop(set_as_default=True)
36
self.bus = dbus.bus.BusConnection(mainloop=self.loop)
37
# monkeypatch busName.__del__ to avoid errors on gc
38
# we take care of releasing the name in shutdown
39
dbus.service.BusName.__del__ = lambda _: None
40
self.bus.set_exit_on_disconnect(False)
41
self.signal_receivers = set()
44
"""Cleanup the test."""
45
d = self.cleanup_signal_receivers(self.signal_receivers)
46
d.addBoth(self._tear_down)
49
def _tear_down(self, _):
54
def error_handler(self, error):
55
"""Default error handler for DBus calls."""
56
if isinstance(error, failure.Failure):
57
self.fail(error.getErrorMessage())
59
def cleanup_signal_receivers(self, signal_receivers):
60
"""Cleanup self.signal_receivers and returns a deferred."""
62
for match in signal_receivers:
66
"""Callback that accepts *args."""
70
self.bus.call_async(dbus.bus.BUS_DAEMON_NAME,
71
dbus.bus.BUS_DAEMON_PATH,
72
dbus.bus.BUS_DAEMON_IFACE, 'RemoveMatch', 's',
73
(str(match),), callback, self.error_handler)
76
return defer.DeferredList(deferreds)
78
return defer.succeed(True)
81
class MementoHandler(logging.Handler):
82
"""A handler class which store logging records in a list."""
84
def __init__(self, *args, **kwargs):
85
"""Create the instance, and add a records attribute."""
86
logging.Handler.__init__(self, *args, **kwargs)
89
def emit(self, record):
90
"""Just add the record to self.records."""
91
self.records.append(record)
93
def check(self, level, *msgs):
94
"""Verifies that the msgs are logged in the specified level."""
95
for rec in self.records:
96
if rec.levelno == level and all(m in rec.message for m in msgs):
100
def check_debug(self, *msgs):
101
"""Shortcut for checking in DEBUG."""
102
return self.check(logging.DEBUG, *msgs)
104
def check_info(self, *msgs):
105
"""Shortcut for checking in INFO."""
106
return self.check(logging.INFO, *msgs)
108
def check_warning(self, *msgs):
109
"""Shortcut for checking in WARNING."""
110
return self.check(logging.WARNING, *msgs)
112
def check_error(self, *msgs):
113
"""Shortcut for checking in ERROR."""
114
return self.check(logging.ERROR, *msgs)
116
def check_exception(self, exception_class, *msgs):
117
"""Shortcut for checking exceptions."""
118
for rec in self.records:
119
if rec.levelno == logging.ERROR and \
120
all(m in rec.exc_text for m in msgs) and \
121
exception_class == rec.exc_info[0]: