util: move PollMixin to a separate file (pollmixin.py), so testutil can be moved into test/

This commit is contained in:
Brian Warner 2008-10-28 21:15:48 -07:00
parent 3dd9b79e3f
commit 294e3fb682
10 changed files with 55 additions and 51 deletions

View File

@ -18,7 +18,7 @@ from allmydata.immutable.filenode import FileNode, LiteralFileNode
from allmydata.offloaded import Helper from allmydata.offloaded import Helper
from allmydata.control import ControlServer from allmydata.control import ControlServer
from allmydata.introducer.client import IntroducerClient from allmydata.introducer.client import IntroducerClient
from allmydata.util import hashutil, base32, testutil, fileutil from allmydata.util import hashutil, base32, pollmixin, fileutil
from allmydata.uri import LiteralFileURI from allmydata.uri import LiteralFileURI
from allmydata.dirnode import NewDirectoryNode from allmydata.dirnode import NewDirectoryNode
from allmydata.mutable.node import MutableFileNode, MutableWatcher from allmydata.mutable.node import MutableFileNode, MutableWatcher
@ -38,7 +38,7 @@ class StubClient(Referenceable):
def _make_secret(): def _make_secret():
return base32.b2a(os.urandom(hashutil.CRYPTO_VAL_SIZE)) + "\n" return base32.b2a(os.urandom(hashutil.CRYPTO_VAL_SIZE)) + "\n"
class Client(node.Node, testutil.PollMixin): class Client(node.Node, pollmixin.PollMixin):
implements(IStatsProducer) implements(IStatsProducer)
PORTNUMFILE = "client.port" PORTNUMFILE = "client.port"

View File

@ -8,7 +8,7 @@ from twisted.web import client as tw_client
from allmydata import client, introducer from allmydata import client, introducer
from allmydata.immutable import upload from allmydata.immutable import upload
from allmydata.scripts import create_node from allmydata.scripts import create_node
from allmydata.util import testutil, fileutil from allmydata.util import fileutil, pollmixin
import foolscap import foolscap
from foolscap import eventual from foolscap import eventual
from twisted.python import log from twisted.python import log
@ -57,7 +57,7 @@ def discardPage(url, stall=False, *args, **kwargs):
reactor.connectTCP(host, port, factory) reactor.connectTCP(host, port, factory)
return factory.deferred return factory.deferred
class SystemFramework(testutil.PollMixin): class SystemFramework(pollmixin.PollMixin):
numnodes = 5 numnodes = 5
def __init__(self, basedir, mode): def __init__(self, basedir, mode):

View File

@ -16,7 +16,7 @@ from allmydata.checker_results import CheckerResults, CheckAndRepairResults, \
DeepCheckResults, DeepCheckAndRepairResults DeepCheckResults, DeepCheckAndRepairResults
from allmydata.mutable.common import CorruptShareError from allmydata.mutable.common import CorruptShareError
from allmydata.storage import storage_index_to_dir from allmydata.storage import storage_index_to_dir
from allmydata.util import log, testutil, fileutil from allmydata.util import log, testutil, fileutil, pollmixin
from allmydata.stats import PickleStatsGatherer from allmydata.stats import PickleStatsGatherer
from allmydata.key_generator import KeyGeneratorService from allmydata.key_generator import KeyGeneratorService
@ -291,7 +291,7 @@ class LoggingServiceParent(service.MultiService):
return log.msg(*args, **kwargs) return log.msg(*args, **kwargs)
class SystemTestMixin(testutil.PollMixin, testutil.StallMixin): class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
def setUp(self): def setUp(self):
self.sparent = service.MultiService() self.sparent = service.MultiService()

View File

@ -14,7 +14,7 @@ from allmydata.introducer.server import IntroducerService
# test compatibility with old introducer .tac files # test compatibility with old introducer .tac files
from allmydata.introducer import IntroducerNode from allmydata.introducer import IntroducerNode
from allmydata.introducer import old from allmydata.introducer import old
from allmydata.util import testutil, idlib from allmydata.util import testutil, idlib, pollmixin
class FakeNode(Referenceable): class FakeNode(Referenceable):
pass pass
@ -46,7 +46,7 @@ class ServiceMixin:
d.addCallback(flushEventualQueue) d.addCallback(flushEventualQueue)
return d return d
class Introducer(ServiceMixin, unittest.TestCase, testutil.PollMixin): class Introducer(ServiceMixin, unittest.TestCase, pollmixin.PollMixin):
def test_create(self): def test_create(self):
ic = IntroducerClient(None, "introducer.furl", "my_nickname", ic = IntroducerClient(None, "introducer.furl", "my_nickname",
@ -75,7 +75,7 @@ class Introducer(ServiceMixin, unittest.TestCase, testutil.PollMixin):
self.failUnlessEqual(len(i.get_announcements()), 2) self.failUnlessEqual(len(i.get_announcements()), 2)
self.failUnlessEqual(len(i.get_subscribers()), 0) self.failUnlessEqual(len(i.get_subscribers()), 0)
class SystemTestMixin(ServiceMixin, testutil.PollMixin): class SystemTestMixin(ServiceMixin, pollmixin.PollMixin):
def setUp(self): def setUp(self):
ServiceMixin.setUp(self) ServiceMixin.setUp(self)

View File

@ -6,7 +6,7 @@ from twisted.application import service
from foolscap import Tub, eventual from foolscap import Tub, eventual
from allmydata import key_generator from allmydata import key_generator
from allmydata.util import testutil from allmydata.util import pollmixin
from pycryptopp.publickey import rsa from pycryptopp.publickey import rsa
def flush_but_dont_ignore(res): def flush_but_dont_ignore(res):
@ -16,7 +16,7 @@ def flush_but_dont_ignore(res):
d.addCallback(_done) d.addCallback(_done)
return d return d
class KeyGenService(unittest.TestCase, testutil.PollMixin): class KeyGenService(unittest.TestCase, pollmixin.PollMixin):
def setUp(self): def setUp(self):
self.parent = service.MultiService() self.parent = service.MultiService()
self.parent.startService() self.parent.startService()

View File

@ -6,7 +6,7 @@ from twisted.python import usage, runtime
from twisted.internet import defer from twisted.internet import defer
import os.path, re import os.path, re
from allmydata.scripts import runner from allmydata.scripts import runner
from allmydata.util import fileutil, testutil from allmydata.util import fileutil, pollmixin
class CreateNode(unittest.TestCase): class CreateNode(unittest.TestCase):
def workdir(self, name): def workdir(self, name):
@ -93,7 +93,7 @@ class CreateNode(unittest.TestCase):
[], [],
run_by_human=False) run_by_human=False)
class RunNode(unittest.TestCase, testutil.PollMixin): class RunNode(unittest.TestCase, pollmixin.PollMixin):
def workdir(self, name): def workdir(self, name):
basedir = os.path.join("test_runner", "RunNode", name) basedir = os.path.join("test_runner", "RunNode", name)
fileutil.make_dirs(basedir) fileutil.make_dirs(basedir)

View File

@ -2,13 +2,13 @@
from twisted.trial import unittest from twisted.trial import unittest
from twisted.application import service from twisted.application import service
from allmydata.stats import CPUUsageMonitor from allmydata.stats import CPUUsageMonitor
from allmydata.util import testutil from allmydata.util import testutil, pollmixin
class FasterMonitor(CPUUsageMonitor): class FasterMonitor(CPUUsageMonitor):
POLL_INTERVAL = 0.1 POLL_INTERVAL = 0.1
class CPUUsage(unittest.TestCase, testutil.PollMixin, testutil.StallMixin): class CPUUsage(unittest.TestCase, pollmixin.PollMixin, testutil.StallMixin):
def setUp(self): def setUp(self):
self.s = service.MultiService() self.s = service.MultiService()
self.s.startService() self.s.startService()

View File

@ -8,7 +8,7 @@ from twisted.python import failure
from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
from allmydata.util import assertutil, fileutil, testutil, deferredutil from allmydata.util import assertutil, fileutil, testutil, deferredutil
from allmydata.util import limiter, time_format from allmydata.util import limiter, time_format, pollmixin
class Base32(unittest.TestCase): class Base32(unittest.TestCase):
def test_b2a_matches_Pythons(self): def test_b2a_matches_Pythons(self):
@ -330,7 +330,7 @@ class FileUtil(unittest.TestCase):
class PollMixinTests(unittest.TestCase): class PollMixinTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.pm = testutil.PollMixin() self.pm = pollmixin.PollMixin()
def test_PollMixin_True(self): def test_PollMixin_True(self):
d = self.pm.poll(check_f=lambda : True, d = self.pm.poll(check_f=lambda : True,
@ -350,7 +350,7 @@ class PollMixinTests(unittest.TestCase):
def _suc(res): def _suc(res):
self.fail("poll should have failed, not returned %s" % (res,)) self.fail("poll should have failed, not returned %s" % (res,))
def _err(f): def _err(f):
f.trap(testutil.TimeoutError) f.trap(pollmixin.TimeoutError)
return None # success return None # success
d.addCallbacks(_suc, _err) d.addCallbacks(_suc, _err)
return d return d

View File

@ -0,0 +1,36 @@
import time
from twisted.internet import task
class TimeoutError(Exception):
pass
class PollComplete(Exception):
pass
class PollMixin:
def poll(self, check_f, pollinterval=0.01, timeout=100):
# Return a Deferred, then call check_f periodically until it returns
# True, at which point the Deferred will fire.. If check_f raises an
# exception, the Deferred will errback. If the check_f does not
# indicate success within timeout= seconds, the Deferred will
# errback. If timeout=None, no timeout will be enforced, and the loop
# will poll forever (or really until Trial times out).
cutoff = None
if timeout is not None:
cutoff = time.time() + timeout
lc = task.LoopingCall(self._poll, check_f, cutoff)
d = lc.start(pollinterval)
def _convert_done(f):
f.trap(PollComplete)
return None
d.addErrback(_convert_done)
return d
def _poll(self, check_f, cutoff):
if cutoff is not None and time.time() > cutoff:
raise TimeoutError("PollMixin never saw %s return True" % check_f)
if check_f():
raise PollComplete()

View File

@ -1,7 +1,7 @@
import os, signal, time import os, signal, time
from random import randrange from random import randrange
from twisted.internet import reactor, defer, task from twisted.internet import reactor, defer
from twisted.python import failure from twisted.python import failure
def insecurerandstr(n): def insecurerandstr(n):
@ -43,38 +43,6 @@ class SignalMixin:
if self.sigchldHandler: if self.sigchldHandler:
signal.signal(signal.SIGCHLD, self.sigchldHandler) signal.signal(signal.SIGCHLD, self.sigchldHandler)
class TimeoutError(Exception):
pass
class PollComplete(Exception):
pass
class PollMixin:
def poll(self, check_f, pollinterval=0.01, timeout=100):
# Return a Deferred, then call check_f periodically until it returns
# True, at which point the Deferred will fire.. If check_f raises an
# exception, the Deferred will errback. If the check_f does not
# indicate success within timeout= seconds, the Deferred will
# errback. If timeout=None, no timeout will be enforced, and the loop
# will poll forever (or really until Trial times out).
cutoff = None
if timeout is not None:
cutoff = time.time() + timeout
lc = task.LoopingCall(self._poll, check_f, cutoff)
d = lc.start(pollinterval)
def _convert_done(f):
f.trap(PollComplete)
return None
d.addErrback(_convert_done)
return d
def _poll(self, check_f, cutoff):
if cutoff is not None and time.time() > cutoff:
raise TimeoutError("PollMixin never saw %s return True" % check_f)
if check_f():
raise PollComplete()
class StallMixin: class StallMixin:
def stall(self, res=None, delay=1): def stall(self, res=None, delay=1):
d = defer.Deferred() d = defer.Deferred()