def testLimitDestinationReached(self): def test(): sp = SocketPool(reactor=CallTrace(), limits={'destinationSize': 2}) # Limits enforced on put, not async. def stillPooled(): wasStillPooled = [] for destHost, destPort in [('h', 1), ('i', 2), ('j', 3)]: while True: # do ... while (fromPool is not None) fromPool = yield sp.getPooledSocket(host=destHost, port=destPort) if fromPool: wasStillPooled.append(fromPool) if fromPool is None: break raise StopIteration(wasStillPooled) sJ = MockSok('sJ') sJ2 = MockSok('sJ2') yield sp.putSocketInPool(host='h', port=1, sock=MockSok('sH')) yield sp.putSocketInPool(host='i', port=2, sock=MockSok('sI')) yield sp.putSocketInPool(host='j', port=3, sock=sJ) yield sp.putSocketInPool(host='j', port=3, sock=sJ2) with stderr_replaced() as err: yield sp.putSocketInPool(host='j', port=3, sock=MockSok('sJ3')) self.assertEquals('', err.getvalue(), err.getvalue()) wasStillPooled = yield stillPooled() self.assertEquals(4, len(wasStillPooled)) self.assertEquals(['sH', 'sI', 'sJ3', 'sJ2'], wasStillPooled) self.assertEquals(['shutdown', 'close'], sJ.log.calledMethodNames()) asProcess(test())
def testUnusedTimeoutSetInitialisesTimer(self): # Whitebox (unusedTimeout -> addTimer) mockReactor = CallTrace() SocketPool(reactor=mockReactor, unusedTimeout=0.02) self.assertEquals(['addTimer'], mockReactor.calledMethodNames()) self.assertEquals(['seconds', 'callback'], mockReactor.calledMethods[0].kwargs.keys()) self.assertEquals(0.02, mockReactor.calledMethods[0].kwargs['seconds']) # Blackbox def test(): top = be((Observable(), (SocketPool(reactor=reactor(), unusedTimeout=0.02),), )) yield top.any.putSocketInPool(host='x', port=80, sock=MockSok('A')) yield top.any.putSocketInPool(host='x', port=80, sock=MockSok('B')) yield sleep(seconds=0.001) result = yield top.any.getPooledSocket(host='x', port=80) self.assertEquals('B', result) yield sleep(seconds=0.04) result = yield top.any.getPooledSocket(host='x', port=80) self.assertEquals(None, result) asProcess(test())
def testNormalExceptionHandlingFromAsync(self): def g(): raise Exception('Boom!') yield self.assertRaises(Exception, lambda: asProcess(g())) def g(): raise BaseException('Boom!') yield self.assertRaises(BaseException, lambda: asProcess(g()))
def testOnlyAcceptsAGeneratorOrGeneratorFunction(self): self.assertRaises(TypeError, lambda: asProcess()) self.assertRaises(TypeError, lambda: asProcess(object())) def functionNotReturningAGenerator(whatever): return [whatever] self.assertRaises(TypeError, lambda: asProcess(functionNotReturningAGenerator)('whatever')) # Readable message try: asProcess(functionNotReturningAGenerator)('whatever') self.fail() except TypeError, e: self.assertEquals("asProcess() expects a generator, got ['whatever']", str(e))
def testLimitSetNotReached(self): def test(): sp = SocketPool(reactor=CallTrace(), limits={'totalSize': 3}) # Limits enforced on put, not async. def fillAndEmpty(): yield sp.putSocketInPool(host='h', port=1, sock='s2') yield sp.putSocketInPool(host='h', port=1, sock='s1') yield sp.putSocketInPool(host='h', port=1, sock='s0') for i in xrange(3): self.assertEquals('s{0}'.format(i), (yield sp.getPooledSocket(host='h', port=1))) yield fillAndEmpty() yield fillAndEmpty() asProcess(test())
def testDecorator(self): @asProcess def g(): raise StopIteration(1) yield self.assertEquals(1, g()) class A(object): @staticmethod @asProcess def g(): raise StopIteration(3) yield self.assertEquals(3, A.g()) def g(a): raise StopIteration(a) yield # Below does not work; because partials' output does not look like # a normal function. # Could be solved with a callable(g) check; though then @warps # does not work (expects attributes to be there - like a function). # # TS: Not worth the effort - just feed the generator (don't decorate) # when using callable non-functions. self.assertRaises(TypeError, lambda: asProcess(partial(g, a=2)))
def normalAsync(): this = yield reactor.addProcess(this.next) yield # waiting for realReactor's step() result = asProcess(a()) yield # waiting for another step() reactor.removeProcess(this.next) raise Exception(('Stop', result))
def testTimerDoesNotFire(self): def test(): done = [] def handler(): lhs, rhs = socketpair() try: with SocketContext(lhs): # quick hack, can block. with Timer(0.01): yield 'a' yield 'b' finally: lhs.close(); rhs.close() done.append(True) g = Gio(reactor(), handler()) for _ in range(42): yield self.assertEquals([True], done) self.assertEquals([], reactor()._timers) self.assertEquals([], g._contextstack) asProcess(test())
def testGeneratorOrReactorSpecialsExceptionHandlingFromAsync(self): # GeneratorExit, (AssertionError, KeyboardInterrupt, SystemExit); all still quit-the-loop; ... # shutdown call cannot "hang"; ... def gexit(): raise GeneratorExit() yield self.assertRaises(GeneratorExit, lambda: asProcess(gexit())) def asserr(): raise AssertionError() yield self.assertRaises(AssertionError, lambda: asProcess(asserr())) def keyint(): raise KeyboardInterrupt() yield self.assertRaises(KeyboardInterrupt, lambda: asProcess(keyint())) def sysexit(): raise SystemExit() yield self.assertRaises(SystemExit, lambda: asProcess(sysexit()))
def multiple(): def one(): events.append('1 start') yield '/dev/null (1)' events.append('1 yielded') result = yield one_2() events.append('1 delegated') raise StopIteration(result) def one_2(): events.append('1-2 called') raise StopIteration(1) yield def two(): events.append('2 start') yield '/dev/null (2)' events.append('2 yielded') raise StopIteration(2) res1 = asProcess(one()) res2 = asProcess(two()) return (res1, res2)
def testTimerTimesOutOutsideBlock(self): def test(): done = [] def handler(): lhs, rhs = socketpair() try: with SocketContext(lhs): # quick hack, can block. with Timer(0.01): for i in xrange(999999): yield 'a' except TimeoutException: done.append(False) finally: lhs.close; rhs.close() yield g = Gio(reactor(), handler()) while not done: yield self.assertEquals([False], done) self.assertEquals([], reactor()._timers) self.assertEquals([], g._contextstack) asProcess(test())
def testAsyncReturnValuePassing(self): def noRetval(): return yield def noneRetval(): raise StopIteration(None) yield def oneRetval(): raise StopIteration(1) yield def oneRetvalWithIgnoredPushback(): raise StopIteration(1, 'p', 'u', 's', 'h') yield def retvalDependantOnPushbackEval(): one_ = yield oneRetvalWithIgnoredPushback() for _ in ['p', 'u', 's']: _ = yield raise StopIteration((yield)) self.assertEquals(None, asProcess(noRetval())) self.assertEquals(None, asProcess(noneRetval())) self.assertEquals(1, asProcess(oneRetval())) self.assertEquals(1, asProcess(oneRetvalWithIgnoredPushback())) self.assertEquals('h', asProcess(retvalDependantOnPushbackEval()))
def testUnfinishedBusinessInReactorLogs(self): neverCalled = [] def timeAfterFinished(): assert local('__reactor__') is reactor() # Code explaining code :-) currentReactor = reactor() currentReactor.addTimer(1.0, lambda: neverCalled.append(True)) yield 'async work...' currentReactor.addProcess(lambda: neverCalled.append(True)) raise StopIteration(42) with stdout_replaced() as out: result = asProcess(timeAfterFinished()) self.assertEquals(42, result) self.assertEquals(1, out.getvalue().count('Reactor shutdown:'), out.getvalue())
def testLimitSetReachedWithDifferentDestinations(self): def test(): sp = SocketPool(reactor=CallTrace(), limits={'totalSize': 2}) # Limits enforced on put, not async. def stillPooled(): wasStillPooled = [] for destHost, destPort in [('h', 1), ('i', 2), ('j', 3)]: while True: # do ... while (fromPool is not None) fromPool = yield sp.getPooledSocket(host=destHost, port=destPort) if fromPool: wasStillPooled.append(fromPool) if fromPool is None: break raise StopIteration(wasStillPooled) yield sp.putSocketInPool(host='h', port=1, sock=MockSok('sH')) yield sp.putSocketInPool(host='i', port=2, sock=MockSok('sI')) with stderr_replaced() as err: yield sp.putSocketInPool(host='j', port=3, sock=MockSok('sJ')) self.assertEquals('', err.getvalue(), err.getvalue()) wasStillPooled = yield stillPooled() self.assertEquals(2, len(wasStillPooled)) self.assertTrue(set(wasStillPooled).issubset(set(['sH', 'sI', 'sJ']))) asProcess(test())
def testLimitSetReached(self): def test(): sp = SocketPool(reactor=CallTrace(), limits={'totalSize': 2}) # Limits enforced on put, not async. def stillPooled(): wasStillPooled = [] while True: # do ... while (fromPool is not None) fromPool = yield sp.getPooledSocket(host='h', port=1) if fromPool: wasStillPooled.append(fromPool) if fromPool is None: break raise StopIteration(wasStillPooled) s0 = MockSok('s0') s1 = MockSok('s1') yield sp.putSocketInPool(host='h', port=1, sock=s0) yield sp.putSocketInPool(host='h', port=1, sock=s1) with stderr_replaced() as err: yield sp.putSocketInPool(host='h', port=1, sock=MockSok('s2')) self.assertEquals('', err.getvalue(), err.getvalue()) #@@ wasStillPooled = yield stillPooled() self.assertEquals(['s2', 's0'], wasStillPooled) self.assertEquals(['shutdown', 'close'], s1.log.calledMethodNames()) shutCall, closeCall = s1.log.calledMethods self.assertEquals(((SHUT_RDWR,), {}), (shutCall.args, shutCall.kwargs)) self.assertEquals(((), {}), (closeCall.args, closeCall.kwargs)) self.assertEquals([], s0.log.calledMethodNames()) yield sp.putSocketInPool(host='h', port=1, sock=MockSok('s0')) yield sp.putSocketInPool(host='h', port=1, sock=MockSok('s1')) yield sp.putSocketInPool(host='h', port=1, sock=MockSok('s2')) yield sp.putSocketInPool(host='h', port=1, sock=MockSok('s3')) wasStillPooled = yield stillPooled() self.assertEquals(['s3', 's0'], wasStillPooled) asProcess(test())
def testSuspendProtocolForCallables(self): @identify def whileSuspended(): this = yield suspend = yield suspend._reactor.addProcess(this.next) yield suspend._reactor.removeProcess(this.next) suspend.resume('whileSuspended') yield # Wait for GC def suspending(): s = Suspend(whileSuspended().send) yield s raise StopIteration(s.getResult()) def thisAndThat(): this = '42' that = yield suspending() raise StopIteration((this, that)) self.assertEquals(('42', 'whileSuspended'), asProcess(thisAndThat()))
def testUnusedTimeoutOnlyPurgesInactiveSocket(self): # Blackbox def test(): sA, sB, sC, s1, s2, s3 = (MockSok(x) for x in ['A', 'B', 'C', 1, 2, 3]) top = be((Observable(), (SocketPool(reactor=reactor(), unusedTimeout=0.025),), )) # Make sure 1st check all-sockets-ok yield sleep(seconds=(0.001)) # Initial set yield top.any.putSocketInPool(host='x', port=80, sock=sA) yield top.any.putSocketInPool(host='x', port=80, sock=sB) yield top.any.putSocketInPool(host='x', port=80, sock=sC) yield top.any.putSocketInPool(host='example.org', port=8080, sock=s1) yield top.any.putSocketInPool(host='example.org', port=8080, sock=s2) yield top.any.putSocketInPool(host='example.org', port=8080, sock=s3) self.assertEquals([], s2.log.calledMethodNames()) # sample # Pass time, no timeout - 1st check always all-sockets-ok yield sleep(seconds=(0.025 + 0.022)) # +/- 0.003 until next mostly-fatal check self.assertEquals([], s2.log.calledMethodNames()) # sample # Use some, put some back _sockC = yield top.any.getPooledSocket(host='x', port=80) _sockB = yield top.any.getPooledSocket(host='x', port=80) _sock3 = yield top.any.getPooledSocket(host='example.org', port=8080) self.assertEquals([sC, sB, s3], [_sockC, _sockB, _sock3]) self.assertEquals([], sC.log.calledMethodNames()) self.assertEquals([], sB.log.calledMethodNames()) self.assertEquals([], s3.log.calledMethodNames()) yield top.any.putSocketInPool(host='x', port=80, sock=sC) yield top.any.putSocketInPool(host='example.org', port=8080, sock=s3) yield sleep(seconds=0.015) # 0.025 - (0.015 - 0.003) = 0.013 until all-fatal check inPool = [] while True: result = yield top.any.getPooledSocket(host='x', port=80) if result == None: break inPool.append(result) while True: result = yield top.any.getPooledSocket(host='example.org', port=8080) if result == None: break inPool.append(result) self.assertEquals([sC, s3], inPool) self.assertEquals([], sC.log.calledMethodNames()) self.assertEquals([], s3.log.calledMethodNames()) self.assertEquals(['shutdown', 'close'], s1.log.calledMethodNames()) # sample shutdown, close = s1.log.calledMethods self.assertEquals(((SHUT_RDWR,), {}), (shutdown.args, shutdown.kwargs)) self.assertEquals(((), {}), (close.args, close.kwargs)) asProcess(test())
def httprequest(self, **kwargs): raise StopIteration(asProcess(HttpRequest.httprequest(**kwargs))) yield
def testSuspendTimingProtocol(self): # happy path for timing out and not timing out def test(expectTimeout): count = [] timedOut = [] @identify def workInSuspendGenF(): this = yield suspend = yield suspend._reactor.addProcess(process=this.next) try: for i in xrange(5): count.append(True) yield while True: sleep(0.0001) if not expectTimeout: break yield suspend.resume('retval') except TimeoutException: timedOut.append(True) finally: suspend._reactor.removeProcess(process=this.next) yield # Wait for GC def workInSuspend(): g = workInSuspendGenF() def doNext(suspend): g.send(suspend) def onTimeout(): g.throw(TimeoutException, TimeoutException(), None) return doNext, onTimeout def suspendWrap(): doNext, onTimeout = workInSuspend() s = Suspend(doNext=doNext, timeout=0.01, onTimeout=onTimeout) yield s result = s.getResult() if expectTimeout: self.fail('Should not have come here') raise StopIteration(result) try: result = yield suspendWrap() if expectTimeout: self.fail() except TimeoutException: self.assertEquals(5, len(count)) self.assertEquals(expectTimeout, bool(timedOut)) if not expectTimeout: self.assertEquals('retval', result) testRun.append(True) # Simple driver - timing out testRun = [] asProcess(test(expectTimeout=True)) self.assertEquals(True, bool(testRun)) # Simple driver - not timing out del testRun[:] asProcess(test(expectTimeout=False)) self.assertEquals(True, bool(testRun)) # http server - timing out reactor0 = self.reactor self.reactor = reactor1 = Reactor() del testRun[:] port = PortNumberGenerator.next() def reqHandler(**whatever): def inner(): yield test(expectTimeout=True) yield 'HTTP/1.0 200 OK\r\n\r\n' return compose(inner()) servert = HttpServer(reactor=self.reactor, port=port, generatorFactory=reqHandler, bindAddress='127.42.42.42') servert.listen() with self.loopingReactor(): sok = self.httpGet(host='127.42.42.42', port=port, path='/ignored') allData = '' try: while allData != 'HTTP/1.0 200 OK\r\n\r\n': allData += sok.recv(4096) finally: servert.shutdown() self.assertEquals(True, bool(testRun)) # http server - not timing out self.reactor = reactor2 = Reactor() del testRun[:] port = PortNumberGenerator.next() def reqHandler(**whatever): def inner(): yield test(expectTimeout=False) yield 'HTTP/1.0 200 OK\r\n\r\n' return compose(inner()) servert = HttpServer(reactor=self.reactor, port=port, generatorFactory=reqHandler, bindAddress='127.42.42.42') servert.listen() with self.loopingReactor(): sok = self.httpGet(host='127.42.42.42', port=port, path='/ignored') allData = '' try: while allData != 'HTTP/1.0 200 OK\r\n\r\n': allData += sok.recv(4096) finally: servert.shutdown() self.assertEquals(True, bool(testRun)) # cleanup (most) stuff reactor0.shutdown() reactor1.shutdown() reactor2.shutdown()
def commit(self): asProcess(self._connect.send("/commit"))
def testReloadEverythingOnAnyChangeWhenWatching(self): def howOften(name): _anIdState = [0] def anId(): _anIdState[0] += 1 return '{0}:{1}'.format(name, _anIdState[0]) return anId fp_util = join(self.tempdir, 'util.sf') util_contents = ''' reloaded = util_reloaded_id() def f(): return reloaded ''' with open(fp_util, 'w') as f: f.write(util_contents) fp_orphan = join(self.tempdir, 'orphan.sf') with open(fp_orphan, 'w') as f: f.write(''' reloaded = orphan_reloaded_id() def orphan(): return reloaded ''') fp_using_util = join(self.tempdir, 'using-util.sf') with open(fp_using_util, 'w') as f: f.write(''' import util reloaded = using_util_reloaded_id() def using(): return reloaded + ' - ' + util.f() ''') def test(): additionalGlobals = { 'util_reloaded_id': howOften("util-reloaded"), 'using_util_reloaded_id': howOften("using-util-reloaded"), 'orphan_reloaded_id': howOften("orphan-reloaded"), } d = DynamicHtml([self.tempdir], reactor=reactor(), additionalGlobals=additionalGlobals) # Allow cleanup of directoryWatcherReadFD (whitebox) _reactorFdsKeys = reactor()._fds.keys() self.assertEquals(1, len(_reactorFdsKeys)) directoryWatcherReadFD = _reactorFdsKeys[0] yield zleep(0.01) # Allow DirectoryWatcher some reactor time # Initialized once util, orphan, using_util = d.getModule('util'), d.getModule('orphan'), d.getModule('using-util') self.assertEquals( ['util-reloaded:1', 'orphan-reloaded:1', 'using-util-reloaded:1'], [util.reloaded, orphan.reloaded, using_util.reloaded]) self.assertEquals('using-util-reloaded:1 - util-reloaded:1', using_util.using()) # Touch & **all** reloaded with open(fp_util, 'w') as f: f.write(util_contents) yield zleep(0.02) # Allow DirectoryWatcher some reactor time util, orphan, using_util = d.getModule('util'), d.getModule('orphan'), d.getModule('using-util') self.assertEquals( ['util-reloaded:2', 'orphan-reloaded:2', 'using-util-reloaded:2'], [util.reloaded, orphan.reloaded, using_util.reloaded]) self.assertEquals('using-util-reloaded:2 - util-reloaded:2', using_util.using()) # Remove file - nothing happens remove(fp_orphan) yield zleep(0.02) # Allow DirectoryWatcher some reactor time util, orphan, using_util = d.getModule('util'), d.getModule('orphan'), d.getModule('using-util') self.assertNotEqual(None, orphan) self.assertEquals( ['util-reloaded:2', 'orphan-reloaded:2', 'using-util-reloaded:2'], [util.reloaded, orphan.reloaded, using_util.reloaded]) # Modify util - reload **and** remove of deleted happens with open(fp_util, 'w') as f: f.write(util_contents) yield zleep(0.02) # Allow DirectoryWatcher some reactor time util, orphan, using_util = d.getModule('util'), d.getModule('orphan'), d.getModule('using-util') self.assertEquals(None, orphan) self.assertEquals( ['util-reloaded:3', 'using-util-reloaded:3'], [util.reloaded, using_util.reloaded]) self.assertEquals('using-util-reloaded:3 - util-reloaded:3', using_util.using()) # cleanup reactor().removeReader(sok=directoryWatcherReadFD) asProcess(test())
def makeRequest(host, port, request, body=None, timeout=30, **kwargs): httprequest1_1 = be((HttpRequest1_1(), (EmptySocketPool(),), )).httprequest1_1 return asProcess(httprequest1_1(host=host, port=port, request=request, body=body, timeout=timeout, **kwargs))
def observer_init(self): asProcess(self.initialize())
def testDecoratedFunctionRaises(self): def raiser(): raise Exception('Boom!') self.assertRaises(Exception, lambda: asProcess(raiser)())
def commit(self): asProcess(self._connect.send('/commit/'))
def testExecuteQuery(self): result = asProcess(HttpClient(host="localhost", port=self.port).executeQuery("SPARQL")) self.assertEquals(PARSED_RESULT_JSON, result)