class AsyncReaderTest(WeightlessTestCase): def dispatch(self, *args, **kwargs): return compose(self.handler(*args, **kwargs)) def setUp(self): WeightlessTestCase.setUp(self) self.reactor = Reactor() self.port = randint(2**10, 2**16) self.httpserver = HttpServer(self.reactor, self.port, self.dispatch) self.httpserver.listen() def tearDown(self): self.httpserver.shutdown() self.reactor.shutdown() WeightlessTestCase.tearDown(self) def testHttpRequest(self): self.assertEquals('GET / HTTP/1.0\r\n', _httpRequest('GET', '/')) self.assertEquals('POST / HTTP/1.0\r\n', _httpRequest('POST', '/')) def testPassRequestThruToBackOfficeServer(self): done = [False] backofficeport = self.port + 1 def passthruhandler(*args, **kwargs): request = kwargs['RequestURI'] response = yield httpget('localhost', backofficeport, request) yield response done[0] = True self.handler = passthruhandler expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n" responses = (i for i in ['hel', 'lo!']) backofficeserver = testserver(backofficeport, responses, expectedrequest) client = clientget('localhost', self.port, '/depot?arg=1&arg=2') while not done[0]: self.reactor.step() response = client.recv(99) self.assertEquals('hello!', response) def testConnectFails(self): exceptions = [] def failingserver(*args, **kwarg): try: response = yield httpget(*target) except Exception, e: exceptions.append(exc_info()) self.handler = failingserver clientget('localhost', self.port, '/') target = ('localhost', 'port', '/') # non-numeric port try: with self.stderr_replaced(): with self.loopingReactor(): while not exceptions: pass except Exception, e: pass
class HttpsServerTest(TestCase): def setUp(self): TestCase.setUp(self) self.reactor = Reactor() def tearDown(self): self.reactor.shutdown() self.reactor = None TestCase.tearDown(self) 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 testConnectBindAddress(self): reactor = CallTrace() port = PortNumberGenerator.next() server = HttpsServer(reactor, port, lambda **kwargs: None, bindAddress='127.0.0.1', keyfile='ssl/server.pkey', certfile='ssl/server.cert') server.listen() self.assertEquals(('127.0.0.1', port), server._sok.getsockname())
def testShutdownReactor(self): reactor = Reactor() sok1 = MockSocket() sok2 = MockSocket() sok3 = MockSocket() def callback(): reactor.suspend() reactor.addReader(sok1, lambda: None) reactor.addWriter(sok2, lambda: None) reactor.addWriter(sok3, callback) reactor.step() self.assertFalse(sok3.fileno() in reactor._fds) self.assertFalse(sok3.fileno() in reactor._fds) with self.stdout_replaced() as s: reactor.shutdown() self.assertTrue(str(sok1) in s.getvalue(), s.getvalue()) self.assertTrue(str(sok2) in s.getvalue(), s.getvalue()) self.assertTrue(str(sok3) in s.getvalue()) self.assertTrue(sok1.closed) self.assertTrue(sok2.closed) self.assertTrue(sok3.closed)
class WeightlessTestCase(TestCase): 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 tearDown(self): t0 = time() if hasattr(self, 'httpd') and hasattr(self.httpd, 'shutdown'): self.httpd.shutdown() self.assertEquals({}, self.reactor._readers) self.assertEquals({}, self.reactor._writers) self.assertEquals({}, self.reactor._suspended) #self.assertEquals([], self.reactor._processes) for t in self.reactor._timers: cb = t.callback code = cb.func_code print 'WARNING: dangling timer in reactor. Remaining timout: %s with callback to %s() in %s at line %s.' \ % (t.time-t0, cb.func_name, code.co_filename, code.co_firstlineno) self.assertEquals([], self.reactor._timers) self.reactor.shutdown() rmtree(self.tempdir) os.remove(self.tempfile) def select(self, aString, index): while index < len(aString): char = aString[index] index = index + 1 if not char in string.whitespace: return char, index return '', index def cursor(self, aString, index): return aString[:index - 1] + "---->" + aString[index - 1:] def assertEqualsWS(self, s1, s2): index1 = 0 index2 = 0 while True: char1, index1 = self.select(s1, index1) char2, index2 = self.select(s2, index2) if char1 != char2: self.fail('%s != %s' % (self.cursor(s1, index1), self.cursor(s2, index2))) if not char1 or not char2: break def send(self, host, port, message): sok = socket() sok.connect((host, port)) sok.sendall(message) return sok def httpGet(self, host, port, path): return self.send(host, port, 'GET %(path)s HTTP/1.0\r\n\r\n' % locals()) def httpPost(self, host='localhost', port=None, path='/', data='', contentType='text/plain'): return self.send(host, port or self.port, 'POST %s HTTP/1.0\r\n' % path + 'Content-Type: %s; charset=\"utf-8\"\r\n' % contentType + 'Content-Length: %s\r\n' % len(data) + '\r\n' + data) @contextmanager def loopingReactor(self, timeOutInSec = 3): blockEnd = False timerHasFired = [] def timeOut(): timerHasFired.append(True) timer = self.reactor.addTimer(timeOutInSec, timeOut) def loop(): while not(timerHasFired or blockEnd): t = self.reactor.addTimer(0.01, lambda: None) try: self.reactor.step() finally: try: self.reactor.removeTimer(t) except ValueError: pass thread = Thread(None, loop) thread.start() try: yield finally: blockEnd = True assert not timerHasFired self.reactor.removeTimer(timer) thread.join() @contextmanager def stderr_replaced(self): oldstderr = sys.stderr mockStderr = StringIO() sys.stderr = mockStderr try: yield mockStderr finally: sys.stderr = oldstderr @contextmanager def stdout_replaced(self): oldstdout = sys.stdout mockStdout = StringIO() sys.stdout = mockStdout try: yield mockStdout finally: sys.stdout = oldstdout def referenceHttpServer(self, port, request): def server(httpd): httpd.serve_forever() class Handler(BaseHTTPRequestHandler): def log_message(*args, **kwargs): pass def do_GET(self, *args, **kwargs): request.append({ 'command': self.command, 'path': self.path, 'headers': self.headers}) self.send_response(200, "GET RESPONSE") def do_POST(self, *args, **kwargs): request.append({ 'command': self.command, 'path': self.path, 'headers': self.headers, 'body': self.rfile.read(int(self.headers["Content-Length"]))}) self.send_response(200, "POST RESPONSE") self.httpd = TCPServer(("", port), Handler) thread=Thread(None, lambda: server(self.httpd)) thread.start()
class WeightlessTestCase(TestCase): 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 tearDown(self): t0 = time() if hasattr(self, 'httpd') and hasattr(self.httpd, 'shutdown'): self.httpd.shutdown() self.assertEquals({}, self.reactor._readers) self.assertEquals({}, self.reactor._writers) self.assertEquals({}, self.reactor._suspended) #self.assertEquals([], self.reactor._processes) for t in self.reactor._timers: cb = t.callback code = cb.func_code print 'WARNING: dangling timer in reactor. Remaining timout: %s with callback to %s() in %s at line %s.' \ % (t.time-t0, cb.func_name, code.co_filename, code.co_firstlineno) self.assertEquals([], self.reactor._timers) self.reactor.shutdown() rmtree(self.tempdir) os.remove(self.tempfile) def select(self, aString, index): while index < len(aString): char = aString[index] index = index + 1 if not char in string.whitespace: return char, index return '', index def cursor(self, aString, index): return aString[:index - 1] + "---->" + aString[index - 1:] def assertEqualsWS(self, s1, s2): index1 = 0 index2 = 0 while True: char1, index1 = self.select(s1, index1) char2, index2 = self.select(s2, index2) if char1 != char2: self.fail('%s != %s' % (self.cursor(s1, index1), self.cursor(s2, index2))) if not char1 or not char2: break def send(self, host, port, message): sok = socket() sok.connect((host, port)) sok.sendall(message) return sok def httpGet(self, host, port, path): return self.send(host, port, 'GET %(path)s HTTP/1.0\r\n\r\n' % locals()) def httpPost(self, host='localhost', port=None, path='/', data='', contentType='text/plain'): return self.send( host, port or self.port, 'POST %s HTTP/1.0\r\n' % path + 'Content-Type: %s; charset=\"utf-8\"\r\n' % contentType + 'Content-Length: %s\r\n' % len(data) + '\r\n' + data) @contextmanager def loopingReactor(self, timeOutInSec=3): blockEnd = False timerHasFired = [] def timeOut(): timerHasFired.append(True) timer = self.reactor.addTimer(timeOutInSec, timeOut) def loop(): while not (timerHasFired or blockEnd): t = self.reactor.addTimer(0.01, lambda: None) try: self.reactor.step() finally: try: self.reactor.removeTimer(t) except ValueError: pass thread = Thread(None, loop) thread.start() try: yield finally: blockEnd = True assert not timerHasFired self.reactor.removeTimer(timer) thread.join() @contextmanager def stderr_replaced(self): oldstderr = sys.stderr mockStderr = StringIO() sys.stderr = mockStderr try: yield mockStderr finally: sys.stderr = oldstderr @contextmanager def stdout_replaced(self): oldstdout = sys.stdout mockStdout = StringIO() sys.stdout = mockStdout try: yield mockStdout finally: sys.stdout = oldstdout def referenceHttpServer(self, port, request): def server(httpd): httpd.serve_forever() class Handler(BaseHTTPRequestHandler): def log_message(*args, **kwargs): pass def do_GET(self, *args, **kwargs): request.append({ 'command': self.command, 'path': self.path, 'headers': self.headers }) self.send_response(200, "GET RESPONSE") def do_POST(self, *args, **kwargs): request.append({ 'command': self.command, 'path': self.path, 'headers': self.headers, 'body': self.rfile.read(int(self.headers["Content-Length"])) }) self.send_response(200, "POST RESPONSE") self.httpd = TCPServer(("", port), Handler) thread = Thread(None, lambda: server(self.httpd)) thread.start()