188 lines
5 KiB
Python
188 lines
5 KiB
Python
# Copyright (c) Twisted Matrix Laboratories.
|
|
# See LICENSE for details.
|
|
|
|
"""
|
|
Tests for L{twisted.application.service}.
|
|
"""
|
|
|
|
from __future__ import absolute_import, division
|
|
|
|
from zope.interface import implementer
|
|
from zope.interface.exceptions import BrokenImplementation
|
|
from zope.interface.verify import verifyObject
|
|
|
|
from twisted.persisted.sob import IPersistable
|
|
from twisted.application.service import Application, IProcess
|
|
from twisted.application.service import IService, IServiceCollection
|
|
from twisted.application.service import Service
|
|
from twisted.trial.unittest import TestCase
|
|
|
|
|
|
@implementer(IService)
|
|
class AlmostService(object):
|
|
"""
|
|
Implement IService in a way that can fail.
|
|
|
|
In general, classes should maintain invariants that adhere
|
|
to the interfaces that they claim to implement --
|
|
otherwise, it is a bug.
|
|
|
|
This is a buggy class -- the IService implementation is fragile,
|
|
and several methods will break it. These bugs are intentional,
|
|
as the tests trigger them -- and then check that the class,
|
|
indeed, no longer complies with the interface (IService)
|
|
that it claims to comply with.
|
|
|
|
Since the verification will, by definition, only fail on buggy classes --
|
|
in other words, those which do not actually support the interface they
|
|
claim to support, we have to write a buggy class to properly verify
|
|
the interface.
|
|
"""
|
|
|
|
def __init__(self, name, parent, running):
|
|
self.name = name
|
|
self.parent = parent
|
|
self.running = running
|
|
|
|
|
|
def makeInvalidByDeletingName(self):
|
|
"""
|
|
Probably not a wise method to call.
|
|
|
|
This method removes the :code:`name` attribute,
|
|
which has to exist in IService classes.
|
|
"""
|
|
del self.name
|
|
|
|
|
|
def makeInvalidByDeletingParent(self):
|
|
"""
|
|
Probably not a wise method to call.
|
|
|
|
This method removes the :code:`parent` attribute,
|
|
which has to exist in IService classes.
|
|
"""
|
|
del self.parent
|
|
|
|
|
|
def makeInvalidByDeletingRunning(self):
|
|
"""
|
|
Probably not a wise method to call.
|
|
|
|
This method removes the :code:`running` attribute,
|
|
which has to exist in IService classes.
|
|
"""
|
|
del self.running
|
|
|
|
|
|
def setName(self, name):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
|
|
@param name: ignored
|
|
"""
|
|
|
|
|
|
def setServiceParent(self, parent):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
|
|
@param parent: ignored
|
|
"""
|
|
|
|
|
|
def disownServiceParent(self):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
"""
|
|
|
|
|
|
def privilegedStartService(self):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
"""
|
|
|
|
|
|
def startService(self):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
"""
|
|
|
|
|
|
def stopService(self):
|
|
"""
|
|
See L{twisted.application.service.IService}.
|
|
"""
|
|
|
|
|
|
|
|
class ServiceInterfaceTests(TestCase):
|
|
"""
|
|
Tests for L{twisted.application.service.IService} implementation.
|
|
"""
|
|
def setUp(self):
|
|
"""
|
|
Build something that implements IService.
|
|
"""
|
|
self.almostService = AlmostService(parent=None, running=False,
|
|
name=None)
|
|
|
|
|
|
def test_realService(self):
|
|
"""
|
|
Service implements IService.
|
|
"""
|
|
myService = Service()
|
|
verifyObject(IService, myService)
|
|
|
|
|
|
def test_hasAll(self):
|
|
"""
|
|
AlmostService implements IService.
|
|
"""
|
|
verifyObject(IService, self.almostService)
|
|
|
|
|
|
def test_noName(self):
|
|
"""
|
|
AlmostService with no name does not implement IService.
|
|
"""
|
|
self.almostService.makeInvalidByDeletingName()
|
|
with self.assertRaises(BrokenImplementation):
|
|
verifyObject(IService, self.almostService)
|
|
|
|
|
|
def test_noParent(self):
|
|
"""
|
|
AlmostService with no parent does not implement IService.
|
|
"""
|
|
self.almostService.makeInvalidByDeletingParent()
|
|
with self.assertRaises(BrokenImplementation):
|
|
verifyObject(IService, self.almostService)
|
|
|
|
|
|
def test_noRunning(self):
|
|
"""
|
|
AlmostService with no running does not implement IService.
|
|
"""
|
|
self.almostService.makeInvalidByDeletingRunning()
|
|
with self.assertRaises(BrokenImplementation):
|
|
verifyObject(IService, self.almostService)
|
|
|
|
|
|
|
|
class ApplicationTests(TestCase):
|
|
"""
|
|
Tests for L{twisted.application.service.Application}.
|
|
"""
|
|
def test_applicationComponents(self):
|
|
"""
|
|
Check L{twisted.application.service.Application} instantiation.
|
|
"""
|
|
app = Application('app-name')
|
|
|
|
self.assertTrue(verifyObject(IService, IService(app)))
|
|
self.assertTrue(
|
|
verifyObject(IServiceCollection, IServiceCollection(app)))
|
|
self.assertTrue(verifyObject(IProcess, IProcess(app)))
|
|
self.assertTrue(verifyObject(IPersistable, IPersistable(app)))
|