Ausgabe der neuen DB Einträge

This commit is contained in:
hubobel 2022-01-02 21:50:48 +01:00
parent bad48e1627
commit cfbbb9ee3d
2399 changed files with 843193 additions and 43 deletions

View file

@ -0,0 +1,9 @@
# -*- test-case-name: twisted._threads.test -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Tests for L{twisted._threads}.
"""
from __future__ import absolute_import, division, print_function

View file

@ -0,0 +1,61 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Test cases for convenience functionality in L{twisted._threads._convenience}.
"""
from __future__ import absolute_import, division, print_function
from twisted.trial.unittest import SynchronousTestCase
from .._convenience import Quit
from .._ithreads import AlreadyQuit
class QuitTests(SynchronousTestCase):
"""
Tests for L{Quit}
"""
def test_isInitiallySet(self):
"""
L{Quit.isSet} starts as L{False}.
"""
quit = Quit()
self.assertEqual(quit.isSet, False)
def test_setSetsSet(self):
"""
L{Quit.set} sets L{Quit.isSet} to L{True}.
"""
quit = Quit()
quit.set()
self.assertEqual(quit.isSet, True)
def test_checkDoesNothing(self):
"""
L{Quit.check} initially does nothing and returns L{None}.
"""
quit = Quit()
self.assertIs(quit.check(), None)
def test_checkAfterSetRaises(self):
"""
L{Quit.check} raises L{AlreadyQuit} if L{Quit.set} has been called.
"""
quit = Quit()
quit.set()
self.assertRaises(AlreadyQuit, quit.check)
def test_setTwiceRaises(self):
"""
L{Quit.set} raises L{AlreadyQuit} if it has been called previously.
"""
quit = Quit()
quit.set()
self.assertRaises(AlreadyQuit, quit.set)

View file

@ -0,0 +1,65 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Tests for L{twisted._threads._memory}.
"""
from __future__ import absolute_import, division, print_function
from zope.interface.verify import verifyObject
from twisted.trial.unittest import SynchronousTestCase
from .. import AlreadyQuit, IWorker, createMemoryWorker
class MemoryWorkerTests(SynchronousTestCase):
"""
Tests for L{MemoryWorker}.
"""
def test_createWorkerAndPerform(self):
"""
L{createMemoryWorker} creates an L{IWorker} and a callable that can
perform work on it. The performer returns C{True} if it accomplished
useful work.
"""
worker, performer = createMemoryWorker()
verifyObject(IWorker, worker)
done = []
worker.do(lambda: done.append(3))
worker.do(lambda: done.append(4))
self.assertEqual(done, [])
self.assertEqual(performer(), True)
self.assertEqual(done, [3])
self.assertEqual(performer(), True)
self.assertEqual(done, [3, 4])
def test_quitQuits(self):
"""
Calling C{quit} on the worker returned by L{createMemoryWorker} causes
its C{do} and C{quit} methods to raise L{AlreadyQuit}; its C{perform}
callable will start raising L{AlreadyQuit} when the work already
provided to C{do} has been exhausted.
"""
worker, performer = createMemoryWorker()
done = []
def moreWork():
done.append(7)
worker.do(moreWork)
worker.quit()
self.assertRaises(AlreadyQuit, worker.do, moreWork)
self.assertRaises(AlreadyQuit, worker.quit)
performer()
self.assertEqual(done, [7])
self.assertEqual(performer(), False)
def test_performWhenNothingToDoYet(self):
"""
The C{perform} callable returned by L{createMemoryWorker} will return
no result when there's no work to do yet. Since there is no work to
do, the performer returns C{False}.
"""
worker, performer = createMemoryWorker()
self.assertEqual(performer(), False)

View file

@ -0,0 +1,290 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Tests for L{twisted._threads._team}.
"""
from __future__ import absolute_import, division, print_function
from twisted.trial.unittest import SynchronousTestCase
from twisted.python.context import call, get
from twisted.python.components import proxyForInterface
from twisted.python.failure import Failure
from .. import IWorker, Team, createMemoryWorker, AlreadyQuit
class ContextualWorker(proxyForInterface(IWorker, "_realWorker")):
"""
A worker implementation that supplies a context.
"""
def __init__(self, realWorker, **ctx):
"""
Create with a real worker and a context.
"""
self._realWorker = realWorker
self._context = ctx
def do(self, work):
"""
Perform the given work with the context given to __init__.
@param work: the work to pass on to the real worker.
"""
super(ContextualWorker, self).do(lambda: call(self._context, work))
class TeamTests(SynchronousTestCase):
"""
Tests for L{Team}
"""
def setUp(self):
"""
Set up a L{Team} with inspectable, synchronous workers that can be
single-stepped.
"""
coordinator, self.coordinateOnce = createMemoryWorker()
self.coordinator = ContextualWorker(coordinator, worker="coordinator")
self.workerPerformers = []
self.allWorkersEver = []
self.allUnquitWorkers = []
self.activePerformers = []
self.noMoreWorkers = lambda: False
def createWorker():
if self.noMoreWorkers():
return None
worker, performer = createMemoryWorker()
self.workerPerformers.append(performer)
self.activePerformers.append(performer)
cw = ContextualWorker(worker, worker=len(self.workerPerformers))
self.allWorkersEver.append(cw)
self.allUnquitWorkers.append(cw)
realQuit = cw.quit
def quitAndRemove():
realQuit()
self.allUnquitWorkers.remove(cw)
self.activePerformers.remove(performer)
cw.quit = quitAndRemove
return cw
self.failures = []
def logException():
self.failures.append(Failure())
self.team = Team(coordinator, createWorker, logException)
def coordinate(self):
"""
Perform all work currently scheduled in the coordinator.
@return: whether any coordination work was performed; if the
coordinator was idle when this was called, return L{False}
(otherwise L{True}).
@rtype: L{bool}
"""
did = False
while self.coordinateOnce():
did = True
return did
def performAllOutstandingWork(self):
"""
Perform all work on the coordinator and worker performers that needs to
be done.
"""
continuing = True
while continuing:
continuing = self.coordinate()
for performer in self.workerPerformers:
if performer in self.activePerformers:
performer()
continuing = continuing or self.coordinate()
def test_doDoesWorkInWorker(self):
"""
L{Team.do} does the work in a worker created by the createWorker
callable.
"""
def something():
something.who = get("worker")
self.team.do(something)
self.coordinate()
self.assertEqual(self.team.statistics().busyWorkerCount, 1)
self.performAllOutstandingWork()
self.assertEqual(something.who, 1)
self.assertEqual(self.team.statistics().busyWorkerCount, 0)
def test_initialStatistics(self):
"""
L{Team.statistics} returns an object with idleWorkerCount,
busyWorkerCount, and backloggedWorkCount integer attributes.
"""
stats = self.team.statistics()
self.assertEqual(stats.idleWorkerCount, 0)
self.assertEqual(stats.busyWorkerCount, 0)
self.assertEqual(stats.backloggedWorkCount, 0)
def test_growCreatesIdleWorkers(self):
"""
L{Team.grow} increases the number of available idle workers.
"""
self.team.grow(5)
self.performAllOutstandingWork()
self.assertEqual(len(self.workerPerformers), 5)
def test_growCreateLimit(self):
"""
L{Team.grow} increases the number of available idle workers until the
C{createWorker} callable starts returning None.
"""
self.noMoreWorkers = lambda: len(self.allWorkersEver) >= 3
self.team.grow(5)
self.performAllOutstandingWork()
self.assertEqual(len(self.allWorkersEver), 3)
self.assertEqual(self.team.statistics().idleWorkerCount, 3)
def test_shrinkQuitsWorkers(self):
"""
L{Team.shrink} will quit the given number of workers.
"""
self.team.grow(5)
self.performAllOutstandingWork()
self.team.shrink(3)
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 2)
def test_shrinkToZero(self):
"""
L{Team.shrink} with no arguments will stop all outstanding workers.
"""
self.team.grow(10)
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 10)
self.team.shrink()
self.assertEqual(len(self.allUnquitWorkers), 10)
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 0)
def test_moreWorkWhenNoWorkersAvailable(self):
"""
When no additional workers are available, the given work is backlogged,
and then performed later when the work was.
"""
self.team.grow(3)
self.coordinate()
def something():
something.times += 1
something.times = 0
self.assertEqual(self.team.statistics().idleWorkerCount, 3)
for i in range(3):
self.team.do(something)
# Make progress on the coordinator but do _not_ actually complete the
# work, yet.
self.coordinate()
self.assertEqual(self.team.statistics().idleWorkerCount, 0)
self.noMoreWorkers = lambda: True
self.team.do(something)
self.coordinate()
self.assertEqual(self.team.statistics().idleWorkerCount, 0)
self.assertEqual(self.team.statistics().backloggedWorkCount, 1)
self.performAllOutstandingWork()
self.assertEqual(self.team.statistics().backloggedWorkCount, 0)
self.assertEqual(something.times, 4)
def test_exceptionInTask(self):
"""
When an exception is raised in a task passed to L{Team.do}, the
C{logException} given to the L{Team} at construction is invoked in the
exception context.
"""
self.team.do(lambda: 1/0)
self.performAllOutstandingWork()
self.assertEqual(len(self.failures), 1)
self.assertEqual(self.failures[0].type, ZeroDivisionError)
def test_quit(self):
"""
L{Team.quit} causes future invocations of L{Team.do} and L{Team.quit}
to raise L{AlreadyQuit}.
"""
self.team.quit()
self.assertRaises(AlreadyQuit, self.team.quit)
self.assertRaises(AlreadyQuit, self.team.do, list)
def test_quitQuits(self):
"""
L{Team.quit} causes all idle workers, as well as the coordinator
worker, to quit.
"""
for x in range(10):
self.team.do(list)
self.performAllOutstandingWork()
self.team.quit()
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 0)
self.assertRaises(AlreadyQuit, self.coordinator.quit)
def test_quitQuitsLaterWhenBusy(self):
"""
L{Team.quit} causes all busy workers to be quit once they've finished
the work they've been given.
"""
self.team.grow(10)
for x in range(5):
self.team.do(list)
self.coordinate()
self.team.quit()
self.coordinate()
self.assertEqual(len(self.allUnquitWorkers), 5)
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 0)
self.assertRaises(AlreadyQuit, self.coordinator.quit)
def test_quitConcurrentWithWorkHappening(self):
"""
If work happens after L{Team.quit} sets its C{Quit} flag, but before
any other work takes place, the L{Team} should still exit gracefully.
"""
self.team.do(list)
originalSet = self.team._quit.set
def performWorkConcurrently():
originalSet()
self.performAllOutstandingWork()
self.team._quit.set = performWorkConcurrently
self.team.quit()
self.assertRaises(AlreadyQuit, self.team.quit)
self.assertRaises(AlreadyQuit, self.team.do, list)
def test_shrinkWhenBusy(self):
"""
L{Team.shrink} will wait for busy workers to finish being busy and then
quit them.
"""
for x in range(10):
self.team.do(list)
self.coordinate()
self.assertEqual(len(self.allUnquitWorkers), 10)
# There should be 10 busy workers at this point.
self.team.shrink(7)
self.performAllOutstandingWork()
self.assertEqual(len(self.allUnquitWorkers), 3)

View file

@ -0,0 +1,308 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Tests for L{twisted._threads._threadworker}.
"""
from __future__ import absolute_import, division, print_function
import gc
import weakref
from twisted.trial.unittest import SynchronousTestCase
from threading import ThreadError, local
from .. import ThreadWorker, LockWorker, AlreadyQuit
class FakeQueueEmpty(Exception):
"""
L{FakeQueue}'s C{get} has exhausted the queue.
"""
class WouldDeadlock(Exception):
"""
If this were a real lock, you'd be deadlocked because the lock would be
double-acquired.
"""
class FakeThread(object):
"""
A fake L{threading.Thread}.
@ivar target: A target function to run.
@type target: L{callable}
@ivar started: Has this thread been started?
@type started: L{bool}
"""
def __init__(self, target):
"""
Create a L{FakeThread} with a target.
"""
self.target = target
self.started = False
def start(self):
"""
Set the "started" flag.
"""
self.started = True
class FakeQueue(object):
"""
A fake L{Queue} implementing C{put} and C{get}.
@ivar items: A lit of items placed by C{put} but not yet retrieved by
C{get}.
@type items: L{list}
"""
def __init__(self):
"""
Create a L{FakeQueue}.
"""
self.items = []
def put(self, item):
"""
Put an item into the queue for later retrieval by L{FakeQueue.get}.
@param item: any object
"""
self.items.append(item)
def get(self):
"""
Get an item.
@return: an item previously put by C{put}.
"""
if not self.items:
raise FakeQueueEmpty()
return self.items.pop(0)
class FakeLock(object):
"""
A stand-in for L{threading.Lock}.
@ivar acquired: Whether this lock is presently acquired.
"""
def __init__(self):
"""
Create a lock in the un-acquired state.
"""
self.acquired = False
def acquire(self):
"""
Acquire the lock. Raise an exception if the lock is already acquired.
"""
if self.acquired:
raise WouldDeadlock()
self.acquired = True
def release(self):
"""
Release the lock. Raise an exception if the lock is not presently
acquired.
"""
if not self.acquired:
raise ThreadError()
self.acquired = False
class ThreadWorkerTests(SynchronousTestCase):
"""
Tests for L{ThreadWorker}.
"""
def setUp(self):
"""
Create a worker with fake threads.
"""
self.fakeThreads = []
self.fakeQueue = FakeQueue()
def startThread(target):
newThread = FakeThread(target=target)
newThread.start()
self.fakeThreads.append(newThread)
return newThread
self.worker = ThreadWorker(startThread, self.fakeQueue)
def test_startsThreadAndPerformsWork(self):
"""
L{ThreadWorker} calls its C{createThread} callable to create a thread,
its C{createQueue} callable to create a queue, and then the thread's
target pulls work from that queue.
"""
self.assertEqual(len(self.fakeThreads), 1)
self.assertEqual(self.fakeThreads[0].started, True)
def doIt():
doIt.done = True
doIt.done = False
self.worker.do(doIt)
self.assertEqual(doIt.done, False)
self.assertRaises(FakeQueueEmpty, self.fakeThreads[0].target)
self.assertEqual(doIt.done, True)
def test_quitPreventsFutureCalls(self):
"""
L{ThreadWorker.quit} causes future calls to L{ThreadWorker.do} and
L{ThreadWorker.quit} to raise L{AlreadyQuit}.
"""
self.worker.quit()
self.assertRaises(AlreadyQuit, self.worker.quit)
self.assertRaises(AlreadyQuit, self.worker.do, list)
class LockWorkerTests(SynchronousTestCase):
"""
Tests for L{LockWorker}.
"""
def test_fakeDeadlock(self):
"""
The L{FakeLock} test fixture will alert us if there's a potential
deadlock.
"""
lock = FakeLock()
lock.acquire()
self.assertRaises(WouldDeadlock, lock.acquire)
def test_fakeDoubleRelease(self):
"""
The L{FakeLock} test fixture will alert us if there's a potential
double-release.
"""
lock = FakeLock()
self.assertRaises(ThreadError, lock.release)
lock.acquire()
self.assertEqual(None, lock.release())
self.assertRaises(ThreadError, lock.release)
def test_doExecutesImmediatelyWithLock(self):
"""
L{LockWorker.do} immediately performs the work it's given, while the
lock is acquired.
"""
storage = local()
lock = FakeLock()
worker = LockWorker(lock, storage)
def work():
work.done = True
work.acquired = lock.acquired
work.done = False
worker.do(work)
self.assertEqual(work.done, True)
self.assertEqual(work.acquired, True)
self.assertEqual(lock.acquired, False)
def test_doUnwindsReentrancy(self):
"""
If L{LockWorker.do} is called recursively, it postpones the inner call
until the outer one is complete.
"""
lock = FakeLock()
worker = LockWorker(lock, local())
levels = []
acquired = []
def work():
work.level += 1
levels.append(work.level)
acquired.append(lock.acquired)
if len(levels) < 2:
worker.do(work)
work.level -= 1
work.level = 0
worker.do(work)
self.assertEqual(levels, [1, 1])
self.assertEqual(acquired, [True, True])
def test_quit(self):
"""
L{LockWorker.quit} frees the resources associated with its lock and
causes further calls to C{do} and C{quit} to fail.
"""
lock = FakeLock()
ref = weakref.ref(lock)
worker = LockWorker(lock, local())
lock = None
self.assertIsNot(ref(), None)
worker.quit()
gc.collect()
self.assertIs(ref(), None)
self.assertRaises(AlreadyQuit, worker.quit)
self.assertRaises(AlreadyQuit, worker.do, list)
def test_quitWhileWorking(self):
"""
If L{LockWorker.quit} is invoked during a call to L{LockWorker.do}, all
recursive work scheduled with L{LockWorker.do} will be completed and
the lock will be released.
"""
lock = FakeLock()
ref = weakref.ref(lock)
worker = LockWorker(lock, local())
def phase1():
worker.do(phase2)
worker.quit()
self.assertRaises(AlreadyQuit, worker.do, list)
phase1.complete = True
phase1.complete = False
def phase2():
phase2.complete = True
phase2.acquired = lock.acquired
phase2.complete = False
worker.do(phase1)
self.assertEqual(phase1.complete, True)
self.assertEqual(phase2.complete, True)
self.assertEqual(lock.acquired, False)
lock = None
gc.collect()
self.assertIs(ref(), None)
def test_quitWhileGettingLock(self):
"""
If L{LockWorker.do} is called concurrently with L{LockWorker.quit}, and
C{quit} wins the race before C{do} gets the lock attribute, then
L{AlreadyQuit} will be raised.
"""
class RacyLockWorker(LockWorker):
def _lock_get(self):
self.quit()
return self.__dict__['_lock']
def _lock_set(self, value):
self.__dict__['_lock'] = value
_lock = property(_lock_get, _lock_set)
worker = RacyLockWorker(FakeLock(), local())
self.assertRaises(AlreadyQuit, worker.do, list)