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 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 testCreateFileCausesReload(self): reactor = Reactor() d = DynamicHtml([self.tempdir], reactor=reactor) open(self.tempdir+'/file1.sf', 'w').write('def main(*args, **kwargs): \n yield "one"') reactor.step() result = d.handleRequest(scheme='http', netloc='host.nl', path='/file1', query='?query=something', fragments='#fragments', arguments={'query': 'something'}) self.assertEquals('HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\none', ''.join(result))
def testChangingFileBeforeRetrievingFirstPage(self): reactor = Reactor() open(join(self.tempdir, 'one.sf'), 'w').write('def main(*args,**kwargs):\n yield "one"') open(join(self.tempdir, 'two.sf'), 'w').write('def main(*args,**kwargs):\n yield "two"') d = DynamicHtml([self.tempdir], reactor=reactor) open(join(self.tempdir, 'one.sf'), 'w').write('def main(*args,**kwargs):\n yield "one++"') reactor.step() header, body = ''.join(d.handleRequest(path='/two')).split('\r\n'*2) self.assertEquals('two', body)
def testHeaders(self): reactor = Reactor() d = DynamicHtml([self.tempdir], reactor=reactor) open(self.tempdir+'/file.sf', 'w').write(""" def main(Headers={}, *args, **kwargs): yield str(Headers) """) reactor.step() result = d.handleRequest(scheme='http', netloc='host.nl', path='/file', query='?query=something', fragments='#fragments', arguments={'query': 'something'}, Headers={'key': 'value'}) self.assertEquals("""HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n{'key': 'value'}""", ''.join(result))
def testFileMovedIntoDirectoryCausesReload(self): reactor = Reactor() open('/tmp/file1.sf', 'w').write('def main(*args, **kwargs): \n yield "one"') d = DynamicHtml([self.tempdir], reactor=reactor) result = asString(d.handleRequest(scheme='http', netloc='host.nl', path='/file1', query='?query=something', fragments='#fragments', arguments={'query': 'something'})) self.assertEquals('HTTP/1.0 404 Not Found\r\nContent-Type: text/html; charset=utf-8\r\n\r\nFile "file1" does not exist.', result) rename('/tmp/file1.sf', self.tempdir+'/file1.sf') reactor.step() result = d.handleRequest(scheme='http', netloc='host.nl', path='/file1', query='?query=something', fragments='#fragments', arguments={'query': 'something'}) self.assertEquals('HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\none', ''.join(result))
def testImportFromSecondPath(self): reactor = Reactor() path1, path2 = self.createTwoPaths() open(join(path2, 'one.sf'), 'w').write('def main(*args,**kwargs):\n yield "one"') open(join(path1, 'page.sf'), 'w').write('import one\ndef main(*args,**kwargs):\n yield one.main(*args,**kwargs)') d = DynamicHtml([path1, path2], reactor=reactor) result = ''.join(d.handleRequest(path='/page')) header, body = result.split('\r\n\r\n') self.assertEquals('one', body) open(join(path2, 'one.sf'), 'w').write('def main(*args,**kwargs):\n yield "two"') reactor.step() result = ''.join(d.handleRequest(path='/page')) header, body = result.split('\r\n\r\n') self.assertEquals('two', body)
def testPassYield(self): reactor = Reactor() tmplatename = join(self.tempdir, 'withyield.sf') d = DynamicHtml([self.tempdir], reactor=reactor) open(tmplatename, 'w').write( "def main(*args, **kwargs):\n" " yield 'HTTP/1.0 200 OK\\r\\n\\r\\n'\n" " yield Yield\n" " yield 'text2'\n") reactor.step() r = list(d.handleRequest(path='/withyield')) self.assertEquals("HTTP/1.0 200 OK\r\n\r\n", r[0]) self.assertTrue(Yield is r[1], r[1]) self.assertEquals("text2", r[2])
def testErrorHandlingCustomHook(self): tracebacks = [] def error_handling_hook(traceback): tracebacks.append(traceback) reactor = Reactor() d = DynamicHtml([self.tempdir], reactor=reactor, errorHandlingHook=error_handling_hook) with open(join(self.tempdir, "page_with_error.sf"), 'w') as fp: fp.write(""" def main(*args, **kwargs): yield 1/0""") reactor.step() r = list(d.handleRequest(path='/page_with_error')) self.assertEqual(1, len(tracebacks))
def testExceptionsInProcessNotSuppressed(self): reactor = Reactor() def p(): raise RuntimeError('The Error') reactor.addProcess(p) self.assertEquals([p], reactor._processes.keys()) try: reactor.step() self.fail('Should not come here.') except RuntimeError, e: self.assertEquals('The Error', str(e)) self.assertEquals([], reactor._processes.keys())
def testFirstDirectoryHasTheRightFileButSecondFileChanges(self): reactor = Reactor() path1, path2 = self.createTwoPaths() open(join(path1, 'page.sf'), 'w').write('def main(*args,**kwargs):\n yield "one"') open(join(path2, 'page.sf'), 'w').write('def main(*args,**kwargs):\n yield "two"') d = DynamicHtml([path1, path2], reactor=reactor) result = ''.join(d.handleRequest(path='/page')) header, body = result.split('\r\n\r\n') self.assertEquals('one', body) open(join(path2, 'page.sf'), 'w').write('def main(*args,**kwargs):\n yield "three"') reactor.step() result = ''.join(d.handleRequest(path='/page')) header, body = result.split('\r\n\r\n') self.assertEquals('one', body)
def testShutdownWithRemainingProcesses(self): reactor = Reactor() lambdaFunc = lambda: None reactor.addProcess(lambdaFunc) self.assertEquals([lambdaFunc], reactor._processes.keys()) self.assertEquals('Reactor shutdown: terminating %s\n' % lambdaFunc, self.withSTDOUTRedirected(reactor.shutdown)) self.assertEquals([], reactor._processes.keys()) reactor = Reactor() lambdaFunc = lambda: reactor.suspend() reactor.addProcess(lambdaFunc) reactor.step() self.assertEquals([lambdaFunc], reactor._suspended.keys()) self.assertEquals('Reactor shutdown: terminating %s\n' % lambdaFunc, self.withSTDOUTRedirected(reactor.shutdown)) self.assertEquals([], reactor._suspended.keys())
def testSocketHandshake(self): with Reactor() as reactor: lhs, rhs = socketpair() def peter(channel): with channel: message = yield yield 'Hello ' + message[-4:] def jack(channel): with channel: x = yield 'My name is Jack' self.assertEquals(None, x) self.response = yield Gio(reactor, jack(SocketContext(lhs))) Gio(reactor, peter(SocketContext(rhs))) reactor.step().step().step().step() self.assertEquals('Hello Jack', self.response)
def testLargeBuffers(self): with stdout_replaced(): with Reactor() as reactor: lhs, rhs = socketpair() messages = [] messageSize = 1024*128 def peter(channel): with channel: while True: messages.append((yield)) def jack(channel): with channel: yield 'X' * messageSize Gio(reactor, jack(SocketContext(lhs))) Gio(reactor, peter(SocketContext(rhs))) while sum(len(message) for message in messages) < messageSize: reactor.step() self.assertTrue(len(messages) > 1) # test is only sensible when multiple parts are sent self.assertEquals(messageSize, len(''.join(messages)))
def testPassCallableAsFirstThing(self): reactor = Reactor() tmplatename = join(self.tempdir, 'withcallable.sf') d = DynamicHtml([self.tempdir], reactor=reactor) open(tmplatename, 'w').write( "def main(*args, **kwargs):\n" " def f():\n" " pass\n" " yield f\n" " yield f\n" " yield 'this is no status line'\n" " yield f\n" " yield 'text2'\n") reactor.step() r = list(d.handleRequest(path='/withcallable')) self.assertTrue(callable(r[0])) self.assertTrue(callable(r[1])) self.assertEquals("HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n", r[2]) self.assertEquals("this is no status line", r[3]) self.assertTrue(callable(r[4])) self.assertEquals("text2", r[5])
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 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 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 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 testLargeBuffers(self): with stdout_replaced(): with Reactor() as reactor: lhs, rhs = socketpair() messages = [] messageSize = 1024 * 128 def peter(channel): with channel: while True: messages.append((yield)) def jack(channel): with channel: yield 'X' * messageSize Gio(reactor, jack(SocketContext(lhs))) Gio(reactor, peter(SocketContext(rhs))) while sum(len(message) for message in messages) < messageSize: reactor.step() self.assertTrue( len(messages) > 1) # test is only sensible when multiple parts are sent self.assertEquals(messageSize, len(''.join(messages)))
def testProcessPriority(self): reactor = Reactor() trace = [] defaultPass = iter(xrange(99)) def defaultPrio(): trace.append('default_%s' % defaultPass.next()) highPass = iter(xrange(99)) def highPrio(): trace.append('high_%s' % highPass.next()) lowPass = iter(xrange(99)) def lowPrio(): trace.append('low_%s' % lowPass.next()) reactor.addProcess(defaultPrio) # prio will be 0, "very high" reactor.addProcess(highPrio, prio=1) reactor.addProcess(lowPrio, prio=3) reactor.step() self.assertEquals([ 'default_0', ], trace) reactor.step() self.assertEquals(set([ 'default_0', 'high_0', 'default_1', ]), set(trace)) reactor.step() self.assertEquals(set([ 'default_0', 'high_0', 'default_1', 'high_1', 'default_2', ]), set(trace)) reactor.step() self.assertEquals(set([ 'default_0', 'high_0', 'default_1', 'high_1', 'default_2', 'high_2', 'low_0', 'default_3', ]), set(trace))
def testAddProcessFunction(self): reactor = Reactor() trace = [] processMe = [1, 2] def p(): try: result = processMe.pop(0) * 2 trace.append(result) except IndexError: reactor.removeProcess() trace.append('removedProcess') reactor.addProcess(p) reactor.step() self.assertEquals([2], trace) reactor.step() self.assertEquals([2, 4], trace) reactor.step() self.assertEquals([2, 4, 'removedProcess'], trace) reactor.addProcess(lambda: None) reactor.step() self.assertEquals([2, 4, 'removedProcess'], trace)
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)) try: reactor.addProcess(lambda: None, prio=-1) self.fail('Should not come here.') except ValueError, e: self.assertEquals('Invalid priority: -1', str(e)) lambdaFunc = lambda: reactor.suspend() reactor.addProcess(lambdaFunc) reactor.step() try: reactor.addProcess(lambdaFunc) self.fail('Should not come here.') except ValueError, e: self.assertEquals('Process is suspended', str(e)) def testProcessAddsNotWhenAlreadyInThere(self): reactor = Reactor() aProcess = lambda: None reactor.addProcess(aProcess) try: reactor.addProcess(aProcess) self.fail('Should not come here.') except ValueError, e: self.assertEquals('Process is already in processes', str(e))