def setUp(self): self.tempdir = mkdtemp() fd, self.tempfile = mkstemp() os.close(fd) self.reactor = Reactor() self.mockreactor = Reactor(lambda r, w, o, t: (r, w, o)) self.port = randint(2**15, 2**16)
def testReaderOrWriterDoesNotMaskKeyboardInterrupt(self): fd, path = mkstemp() reactor = Reactor() def raiser(): raise KeyboardInterrupt('Ctrl-C') reactor.addReader(sok=fd, sink=raiser) self.assertEquals([raiser], [c.callback for c in reactor._readers.values()]) try: reactor.step() self.fail('step() must raise KeyboardInterrupt') except KeyboardInterrupt: self.assertEquals([], [c.callback for c in reactor._readers.values()]) fd, path = mkstemp() reactor = Reactor() reactor.addWriter(sok=fd, source=raiser) try: reactor.step() self.fail('step() must raise KeyboardInterrupt') except KeyboardInterrupt: self.assertEquals([], [c.callback for c in reactor._readers.values()])
def testReaderOrWriterDoesNotMaskSystemExit(self): fd, path = mkstemp() reactor = Reactor() def raiser(): raise SystemExit('shutdown...') reactor.addReader(sok=fd, sink=raiser) self.assertEquals([raiser], [c.callback for c in reactor._readers.values()]) try: reactor.step() self.fail('step() must raise SystemExit') except SystemExit: self.assertEquals([], [c.callback for c in reactor._readers.values()]) fd, path = mkstemp() reactor = Reactor() reactor.addWriter(sok=fd, source=raiser) try: reactor.step() self.fail('step() must raise SystemExit') except SystemExit: self.assertEquals([], [c.callback for c in reactor._readers.values()])
def testClearTimer(self): port = randint(2**10, 2**16) reactor = Reactor() expectedrequest = "GET / HTTP/1.1\r\nHost: localhost\r\nUser-Agent: Weightless/v%s\r\n\r\n" % WlVersion serverThread = server(port, "HTTP/1.1 200 OK\r\n\r\nresponse", expectedrequest) self.exception = None sentData = [] def send(data): sentData.append(data) def throw(exception): self.exception = exception reader = HttpReaderFacade(reactor, "http://localhost:%s" % port, send, throw, timeout=0.01, recvSize=3) while not self.exception: reactor.step() sleep(0.02) # 2 * timeout, just to be sure self.assertTrue(isinstance(self.exception, StopIteration))
def testTimeoutOnServerGoingSilentAfterHeaders(self): port = randint(2**10, 2**16) reactor = Reactor() expectedrequest = "GET / HTTP/1.1\r\nHost: localhost\r\nUser-Agent: Weightless/v%s\r\n\r\n" % WlVersion serverThread = server(port, "HTTP/1.1 200 OK\r\n\r\n", expectedrequest, delay=1) errorArgs = [] class Handler: def send(self, data): pass def throw(self, exception): errorArgs.append(exception) def error(exception): errorArgs.append(exception) reader = HttpReader(reactor, Connector(reactor, 'localhost', port), Handler(), "GET", "localhost", "/", timeout=0.01) reactor.addTimer(0.2, lambda: self.fail("Test Stuck")) while not errorArgs: reactor.step() serverThread.join() self.assertEquals('timeout while receiving data', str(errorArgs[0]))
def testPostMethodDeCompressesDeflatedBody_deflate(self): self.requestData = None def handler(**kwargs): self.requestData = kwargs reactor = Reactor() server = HttpServer(reactor, self.port, handler, timeout=0.01) server.listen() sok = socket() sok.connect(('localhost', self.port)) bodyData = 'bodydatabodydata' bodyDataCompressed = compress(bodyData) contentLengthCompressed = len(bodyDataCompressed) sok.send(( 'POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nContent-Encoding: deflate\r\n\r\n' % contentLengthCompressed) + bodyDataCompressed) while not self.requestData: reactor.step() self.assertEquals(dict, type(self.requestData)) self.assertTrue('Headers' in self.requestData) headers = self.requestData['Headers'] self.assertEquals('POST', self.requestData['Method']) self.assertEquals('application/x-www-form-urlencoded', headers['Content-Type']) self.assertEquals(contentLengthCompressed, int(headers['Content-Length']) ) # TS: is this correct?, maybe decompressed length? self.assertTrue('Body' in self.requestData) self.assertEquals('bodydatabodydata', self.requestData['Body'])
def testPostMethodTimesOutOnBadBody(self): self.requestData = None def handler(**kwargs): self.requestData = kwargs done = [] def onDone(): fromServer = sok.recv(1024) self.assertTrue('HTTP/1.0 400 Bad Request' in fromServer) done.append(True) reactor = Reactor() server = HttpServer(reactor, self.port, handler, timeout=0.01) server.listen() reactor.addTimer(0.02, onDone) sok = socket() sok.connect(('localhost', self.port)) sok.send( 'POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 8\r\n\r\n' ) while not done: reactor.step()
def testSendHeader(self): self.kwargs = None def response(**kwargs): self.kwargs = kwargs yield 'nosense' reactor = Reactor() server = HttpServer(reactor, self.port, response) server.listen() sok = socket() sok.connect(('localhost', self.port)) sok.send( 'GET /path/here HTTP/1.0\r\nConnection: close\r\nApe-Nut: Mies\r\n\r\n' ) while not self.kwargs: reactor.step() self.assertEquals( { 'Body': '', 'RequestURI': '/path/here', 'HTTPVersion': '1.0', 'Method': 'GET', 'Headers': { 'Connection': 'close', 'Ape-Nut': 'Mies' }, 'Client': ('127.0.0.1', MATCHALL) }, self.kwargs)
def testInvalidPOSTRequestStartsOnlyOneTimer(self): # problem in found in OAS, timers not removed properly when whole body hasnt been read yet _httpserver.RECVSIZE = 1 reactor = Reactor() timers = [] orgAddTimer = reactor.addTimer def addTimerInterceptor(*timer): timers.append(timer) return orgAddTimer(*timer) reactor.addTimer = addTimerInterceptor server = HttpServer(reactor, self.port, lambda **kwargs: (x for x in []), timeout=0.01) server.listen() sok = socket() sok.connect(('localhost', self.port)) sok.send('POST / HTTP/1.0\r\nContent-Length: 10\r\n\r\n') reactor.step() sok.send(".") sleep(0.1) reactor.step() sok.send(".") reactor.step() sleep(0.1) while select([sok], [], [], 0) != ([sok], [], []): reactor.step() self.assertEquals(2, len(timers))
def startServer(port, stateDir, lucenePort, gatewayPort, quickCommit=False, **kwargs): setSignalHandlers() print 'Firing up API Server.' reactor = Reactor() statePath = abspath(stateDir) dna = main(reactor=reactor, port=port, statePath=statePath, lucenePort=lucenePort, gatewayPort=gatewayPort, quickCommit=quickCommit, **kwargs) server = be(dna) consume(server.once.observer_init()) registerShutdownHandler(statePath=statePath, server=server, reactor=reactor, shutdownMustSucceed=False) print "Ready to rumble at %s" % port sys.stdout.flush() reactor.loop()
def testImportForeignModules(self): reactor = Reactor() open(self.tempdir + '/file1.sf', 'w').write(""" import sys def main(headers={}, *args, **kwargs): yield str(sys) """) d = DynamicHtml([self.tempdir], reactor=reactor, allowedModules=['sys']) result = d.handleRequest(scheme='http', netloc='host.nl', path='/file1', query='?query=something', fragments='#fragments', arguments={'query': 'something'}) resultText = ''.join(result) self.assertTrue("<module 'sys' (built-in)>" in resultText, resultText) open(self.tempdir + '/file1.sf', 'w').write(""" import sys def main(headers={}, *args, **kwargs): yield sys.__doc__ """) reactor.step() result = ''.join(d.handleRequest(scheme='http', netloc='host.nl', path='/file1', query='?query=something', fragments='#fragments', arguments={'query': 'something'})) self.assertTrue('This module provides access to some objects' in result, result)
def testProcessWithSuspend(self): reactor = Reactor() trace = [] def p(): trace.append(reactor.suspend()) trace.append('suspending') yield trace.append('resuming') yield callback = p().next reactor.addProcess(callback) reactor.addProcess(lambda: None) reactor.step() self.assertEquals([callback], reactor._suspended.keys()) self.assertEquals([callback, 'suspending'], trace) reactor.step() self.assertEquals([callback], reactor._suspended.keys()) self.assertEquals([callback, 'suspending'], trace) reactor.resumeProcess(handle=callback) reactor.step() self.assertEquals([], reactor._suspended.keys()) self.assertEquals([callback, 'suspending', 'resuming'], trace)
def setUp(self): TestCase.setUp(self) self.tempdir = mkdtemp() fd, self.tempfile = mkstemp() os.close(fd) self.reactor = Reactor() self.port = PortNumberGenerator.next()
def testAddProcessSanityCheck(self): reactor = Reactor() try: reactor.addProcess(lambda: None, prio=10) self.fail('Should not come here.') except ValueError, e: self.assertEquals('Invalid priority: 10', str(e))
def testAddProcessGenerator(self): reactor = Reactor() trace = [] @identify def p(): this = yield yield # wait after this trace.append(1) yield trace.append(2) reactor.removeProcess(this.next) yield trace.append('should_not_happen') yield reactor.addProcess(p().next) reactor.step() self.assertEquals([1], trace) reactor.step() self.assertEquals([1, 2], trace) reactor.addProcess(lambda: None) reactor.step() self.assertEquals([1, 2], trace)
def testWritePrio(self): reactor = Reactor() local0, remote0 = socketpair() local1, remote1 = socketpair() local1.setblocking(0) def remoteHandler0(): remote0.send('ape') def remoteHandler1(): remote1.send('nut') reactor.addWriter(remote0, remoteHandler0, 0) reactor.addWriter(remote1, remoteHandler1, 2) reactor.step() #0 self.assertEquals('ape', local0.recv(999)) try: local1.recv(999) self.fail('must be no data on the socket yet') except error: pass reactor.step() #1 try: local1.recv(999) self.fail('must be no data on the socket yet') except error: pass reactor.step() #2 self.assertEquals('nut', local1.recv(999))
def testMinandMaxPrio(self): reactor = Reactor() try: reactor.addReader('', '', -1) self.fail() except ValueError, e: self.assertEquals('Invalid priority: -1', str(e))
def testReadPriorities(self): reactor = Reactor() local0, remote0 = socketpair() local1, remote1 = socketpair() data0 = [] def remoteHandler0(): data0.append(remote0.recv(999)) data1 = [] def remoteHandler1(): data1.append(remote1.recv(999)) reactor.addReader(remote0, remoteHandler0, 0) reactor.addReader(remote1, remoteHandler1, 2) local0.send('ape') local1.send('nut') reactor.step() #0 self.assertEquals(['ape'], data0) self.assertEquals([], data1) reactor.step() #1 self.assertEquals([], data1) reactor.step() #2 self.assertEquals(['nut'], data1)
def testReloadImportedModules(self): reactor = Reactor() open(self.tempdir + '/file1.sf', 'w').write(""" def main(value, *args, **kwargs): return "original template %s" % value """) open(self.tempdir + '/file2.sf', 'w').write(""" import file1 def main(*args, **kwargs): yield file1.main(value='word!', *args, **kwargs) """) d = DynamicHtml([self.tempdir], reactor=reactor) result = ''.join(d.handleRequest(scheme='http', netloc='host.nl', path='/file2')) self.assertTrue('original template word!' in result, result) open(self.tempdir + '/file1.sf', 'w').write(""" def main(value, *args, **kwargs): return "changed template %s" % value """) reactor.step() result = ''.join(d.handleRequest(scheme='http', netloc='host.nl', path='/file2')) self.assertTrue('changed template word!' in result, result)
def testPost(self): with Reactor() as reactor: request = "POST / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\nSOAPAction: blah\r\nUser-Agent: Weightless/v%s\r\n\r\n1\r\nA\r\n1\r\nB\r\n1\r\nC\r\n0\r\n\r\n" % WlVersion serverThread = server(self.port, "HTTP/1.1 200 OK\r\n\r\nresponse", request, loop=9) sentData = [] done = [] def send(data): sentData.append(data) def throw(exception): if isinstance(exception, StopIteration): done.append(True) def next(): yield "A" yield "B" yield "C" yield None reader = HttpReaderFacade(reactor, "http://localhost:%s" % self.port, send, errorHandler=throw, timeout=0.5, headers={'SOAPAction': 'blah'}, bodyHandler=next) reactor.addTimer(3.0, lambda: self.fail("Test Stuck")) while not done: reactor.step() self.assertEquals(['response'], sentData[1:]) self.assertEquals('200', sentData[0]['StatusCode']) expected = 'POST / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\nSOAPAction: blah\r\nUser-Agent: Weightless/v%s\r\n\r\n' % WlVersion + '1\r\nA\r\n' + '1\r\nB\r\n' + '1\r\nC\r\n' + '0\r\n\r\n' self.assertEquals(expected, "".join(request))
def testConnect(self): self.req = False serverResponse = 'Hello World' def onRequest(**kwargs): yield 'HTTP/1.0 200 OK\r\n\r\n' + serverResponse self.req = True port = PortNumberGenerator.next() with Reactor() as reactor: try: server = HttpsServer(reactor, port, onRequest, keyfile='ssl/server.pkey', certfile='ssl/server.cert') server.listen() p = Popen('wget -O - --no-check-certificate --quiet https://localhost:%s' % port, shell=True, stdout=PIPE) popenStdout = [] def readPopenStdout(): popenStdout.append(p.stdout.read()) reactor.addReader(p.stdout, readPopenStdout) while not self.req: reactor.step() reactor.step() self.assertEquals(1, len(popenStdout)) self.assertEquals(serverResponse, popenStdout[0]) finally: server.shutdown() # cleanup reactor.removeReader(p.stdout)
def testDealWithChunkedResponse(self): with Reactor() as reactor: sentData = [] done = [] expectedrequest = "GET / HTTP/1.1\r\nHost: localhost\r\nUser-Agent: Weightless/v%s\r\n\r\n" % WlVersion serverThread = server(self.port, "\r\n".join("""HTTP/1.1 302 Found Date: Fri, 26 Oct 2007 07:23:26 GMT Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 mod_ssl/2.2.3 OpenSSL/0.9.8c Location: /page/softwarestudio.page/show Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 4F <p>The document has moved <a href="/page/softwarestudio.page/show">here</a></p> 0 """.split("\n")), expectedrequest) class Handler: def send(self, data): sentData.append(data) def throw(self, exception): if isinstance(exception, StopIteration): done.append(True) reader = HttpReader(reactor, Connector(reactor, 'localhost', int(self.port)), Handler(), 'GET', 'localhost', '/', recvSize=5) reactor.addTimer(0.2, lambda: self.fail("Test Stuck")) while not done: reactor.step() self.assertEquals("""<p>The document has moved <a href="/page/softwarestudio.page/show">here</a></p>""", "".join(sentData[1:]))
def testSmallFragmentsWhileSendingResponse(self): def response(**kwargs): yield 'some text that is longer than ' yield 'the lenght of fragments sent' reactor = Reactor() server = HttpServer(reactor, self.port, response, recvSize=3) server.listen() sok = socket() sok.connect(('localhost', self.port)) sok.send( 'GET /path/here HTTP/1.0\r\nConnection: close\r\nApe-Nut: Mies\r\n\r\n' ) while not reactor._writers: reactor.step() serverSok, handler = reactor._writers.items()[0] originalSend = serverSok.send def sendOnlyManagesToActuallySendThreeBytesPerSendCall(data, *options): originalSend(data[:3], *options) return 3 serverSok.send = sendOnlyManagesToActuallySendThreeBytesPerSendCall for i in range(21): reactor.step() fragment = sok.recv(4096) self.assertEquals( 'some text that is longer than the lenght of fragments sent', fragment)
def startServer(port, stateDir, luceneserverPort, gatewayPort, quickCommit=False, **ignored): setSignalHandlers() print 'Firing up Index Server.' statePath = abspath(stateDir) writerReactor = Reactor() writer = writerMain( writerReactor=writerReactor, statePath=statePath, luceneserverPort=luceneserverPort, gatewayPort=gatewayPort, quickCommit=quickCommit, ) writerServer = be(writer) # Start writer in main (this) thread: consume(writerServer.once.observer_init()) registerShutdownHandler(statePath=statePath, server=writerServer, reactor=writerReactor, shutdownMustSucceed=False) print "Ready to rumble at port %s" % port stdout.flush() writerReactor.loop()
def testPostMethodReadsBody(self): self.requestData = None def handler(**kwargs): self.requestData = kwargs reactor = Reactor() server = HttpServer(reactor, self.port, handler, timeout=0.01) server.listen() sok = socket() sok.connect(('localhost', self.port)) sok.send( 'POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 8\r\n\r\nbodydata' ) while not self.requestData: reactor.step() self.assertEquals(dict, type(self.requestData)) self.assertTrue('Headers' in self.requestData) headers = self.requestData['Headers'] self.assertEquals('POST', self.requestData['Method']) self.assertEquals('application/x-www-form-urlencoded', headers['Content-Type']) self.assertEquals(8, int(headers['Content-Length'])) self.assertTrue('Body' in self.requestData) self.assertEquals('bodydata', self.requestData['Body'])
def testReactorSuspend(self): handle = ['initial value'] with stdout_replaced() as out: with Reactor() as reactor: def callback(): handle[0] = reactor.suspend() sok1 = MockSocket() reactor.addReader(sok1, callback) self.assertTrue(sok1.fileno() in reactor._fds) reactor.step() self.assertTrue(sok1.fileno() not in reactor._fds) sok2 = MockSocket() reactor.addWriter(sok2, callback) self.assertTrue(sok2.fileno() in reactor._fds) reactor.step() self.assertTrue(sok2.fileno() not in reactor._fds) self.assertTrue(handle[0] != None) self.assertTrue(handle[0] != 'initial value') # cleanup fd's sok1.close() sok2.close() self.assertEquals(2, out.getvalue().count('closing'), out.getvalue())
def testPostMethodDeCompressesDeflatedBody_unrecognizedEncoding(self): self.requestData = None def handler(**kwargs): self.requestData = kwargs return yield reactor = Reactor() server = HttpServer(reactor, self.port, handler, timeout=0.01) server.listen() sok = socket() sok.connect(('localhost', self.port)) bodyData = 'bodydatabodydata' bodyDataCompressed = compress(bodyData) contentLengthCompressed = len(bodyDataCompressed) sok.send(( 'POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nContent-Encoding: unknown\r\n\r\n' % contentLengthCompressed) + bodyDataCompressed) while select([sok], [], [], 0) != ([sok], [], []): reactor.step() self.assertTrue(sok.recv(4096).startswith('HTTP/1.0 400 Bad Request')) self.assertEquals(None, self.requestData)
def testWrongUseAfterSuspending(self): with stdout_replaced(): with Reactor() as reactor: handle = ['initial value'] def callback(): handle[0] = reactor.suspend() sok = MockSocket() reactor.addWriter(sok, callback) reactor.step() self.assertEquals(sok.fileno(), handle[0]) try: reactor.addWriter(sok, callback) self.fail("Exception not raised") except ValueError, e: self.assertEquals('Socket is suspended', str(e)) try: reactor.addReader(sok, callback) self.fail("Exception not raised") except ValueError, e: self.assertEquals('Socket is suspended', str(e)) # cleanup fd's sok.close()
def testReadChunkedAndCompressedPost(self): postData = 'AhjBeehCeehAhjBeehCeehAhjBeehCeehAhjBeehCeeh' postDataCompressed = compress(postData) self.assertEquals(20, len(postDataCompressed)) self.assertEquals(15, len(postDataCompressed[:15])) self.assertEquals(5, len(postDataCompressed[15:])) self.requestData = {} def handler(**kwargs): self.requestData = kwargs reactor = Reactor() server = HttpServer(reactor, self.port, handler, timeout=0.01, recvSize=3) server.listen() sok = socket() sok.connect(('localhost', self.port)) postString = 'POST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nTransfer-Encoding: chunked\r\nContent-Encoding: deflate\r\n\r\nf\r\n%s\r\n5\r\n%s\r\n0\r\n' % ( postDataCompressed[:15], postDataCompressed[15:]) sok.send(postString) reactor.addTimer(0.2, lambda: self.fail("Test Stuck")) while self.requestData.get('Body', None) != postData: reactor.step()
def testSuspendProtocolWithThrow(self): with Reactor() as reactor: suspend = Suspend() def handler(**httpvars): yield 'before suspend' yield suspend try: suspend.getResult() self.fail() except ValueError, e: tbstring = format_exc() yield "result = %s" % tbstring yield 'after suspend' listener = MyMockSocket() port = PortNumberGenerator.next() httpserver = HttpServer(reactor, port, handler, sok=listener) httpserver.listen() reactor.removeReader(listener) # avoid new connections httpserver._acceptor._accept() reactor.step() reactor.step() reactor.step() self.assertEquals(reactor, suspend._reactor) self.assertEquals(0, len(reactor._fds)) def raiser(): raise ValueError("BAD VALUE") try: raiser() except ValueError, e: exc_type, exc_value, exc_traceback = exc_info() suspend.throw(exc_type, exc_value, exc_traceback)