diff --git a/maint/appengine/README b/maint/appengine/README new file mode 100644 index 00000000..6a77f3d2 --- /dev/null +++ b/maint/appengine/README @@ -0,0 +1,11 @@ +Unit test support for app engine. Currently very limited as most of +our tests depend on direct network access, but these tests ensure that the +modules that are supposed to work on app engine don't depend on any +forbidden modules. + +The code lives in maint/appengine/common, but should be run from the py25 +or py27 subdirectories (which contain an app.yaml and a bunch of symlinks). +runtests.py is the entry point; cgi_runtests.py is used internally. +dev_appserver.py doesn't work with virtualenv +(http://code.google.com/p/googleappengine/issues/detail?id=4339) so these +tests are not hooked into tox yet. diff --git a/maint/appengine/common/cgi_runtests.py b/maint/appengine/common/cgi_runtests.py new file mode 100644 index 00000000..13f0d91d --- /dev/null +++ b/maint/appengine/common/cgi_runtests.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +import logging +import unittest + +# Most of our tests depend on IOLoop, which is not importable on app engine. +# Run the tests that work, and check that forbidden imports don't sneak +# in to modules that are supposed to work on app engine. +TEST_MODULES = [ + 'tornado.httputil.doctests', + #'tornado.iostream.doctests', + 'tornado.util.doctests', + #'tornado.test.auth_test', + #'tornado.test.curl_httpclient_test', + 'tornado.test.escape_test', + #'tornado.test.gen_test', + #'tornado.test.httpclient_test', + #'tornado.test.httpserver_test', + 'tornado.test.httputil_test', + #'tornado.test.import_test', + #'tornado.test.ioloop_test', + #'tornado.test.iostream_test', + #'tornado.test.process_test', + #'tornado.test.simple_httpclient_test', + #'tornado.test.stack_context_test', + 'tornado.test.template_test', + #'tornado.test.testing_test', + #'tornado.test.twisted_test', + #'tornado.test.web_test', + #'tornado.test.wsgi_test', +] + +def import_everything(): + # import tornado.auth + # import tornado.autoreload + # import tornado.curl_httpclient # depends on pycurl + # import tornado.database # depends on MySQLdb + import tornado.escape + # import tornado.httpclient + # import tornado.httpserver + import tornado.httputil + # import tornado.ioloop + # import tornado.iostream + import tornado.locale + import tornado.options + # import tornado.netutil + # import tornado.platform.twisted # depends on twisted + # import tornado.process + # import tornado.simple_httpclient + import tornado.stack_context + import tornado.template + import tornado.testing + import tornado.util + import tornado.web + # import tornado.websocket + import tornado.wsgi + +def all(): + return unittest.defaultTestLoader.loadTestsFromNames(TEST_MODULES) + +if __name__ == '__main__': + print "Content-Type: text/plain\r\n\r\n", + + import_everything() + + import tornado.testing + try: + tornado.testing.main() + except SystemExit, e: + if e.code == 0: + print "PASS" + else: + raise diff --git a/maint/appengine/common/runtests.py b/maint/appengine/common/runtests.py new file mode 100644 index 00000000..c648285f --- /dev/null +++ b/maint/appengine/common/runtests.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +import os +import random +import signal +import subprocess +import sys +import time +import urllib2 + +if __name__ == "__main__": + tornado_root = os.path.abspath(os.path.join(os.path.dirname(__file__), + '../../..')) + # dev_appserver doesn't seem to set SO_REUSEADDR + port = random.randrange(10000, 11000) + # does dev_appserver.py ever live anywhere but /usr/local/bin? + proc = subprocess.Popen([sys.executable, + "/usr/local/bin/dev_appserver.py", + os.path.dirname(__file__), + "--port=%d" % port + ], + cwd=tornado_root) + time.sleep(3) + try: + resp = urllib2.urlopen("http://localhost:%d/" % port) + print resp.read() + finally: + os.kill(proc.pid, signal.SIGTERM) + proc.wait() diff --git a/maint/appengine/py25/app.yaml b/maint/appengine/py25/app.yaml new file mode 100644 index 00000000..8bd78921 --- /dev/null +++ b/maint/appengine/py25/app.yaml @@ -0,0 +1,8 @@ +application: tornado-tests-appengine25 +version: 1 +runtime: python +api_version: 1 + +handlers: +- url: / + script: cgi_runtests.py \ No newline at end of file diff --git a/maint/appengine/py25/cgi_runtests.py b/maint/appengine/py25/cgi_runtests.py new file mode 120000 index 00000000..a9fc90e9 --- /dev/null +++ b/maint/appengine/py25/cgi_runtests.py @@ -0,0 +1 @@ +../common/cgi_runtests.py \ No newline at end of file diff --git a/maint/appengine/py25/runtests.py b/maint/appengine/py25/runtests.py new file mode 120000 index 00000000..2cce26b0 --- /dev/null +++ b/maint/appengine/py25/runtests.py @@ -0,0 +1 @@ +../common/runtests.py \ No newline at end of file diff --git a/maint/appengine/py25/tornado b/maint/appengine/py25/tornado new file mode 120000 index 00000000..13b2e093 --- /dev/null +++ b/maint/appengine/py25/tornado @@ -0,0 +1 @@ +../../../tornado \ No newline at end of file diff --git a/maint/appengine/py27/app.yaml b/maint/appengine/py27/app.yaml new file mode 100644 index 00000000..e5dea072 --- /dev/null +++ b/maint/appengine/py27/app.yaml @@ -0,0 +1,9 @@ +application: tornado-tests-appengine27 +version: 1 +runtime: python27 +threadsafe: false +api_version: 1 + +handlers: +- url: / + script: cgi_runtests.py \ No newline at end of file diff --git a/maint/appengine/py27/cgi_runtests.py b/maint/appengine/py27/cgi_runtests.py new file mode 120000 index 00000000..a9fc90e9 --- /dev/null +++ b/maint/appengine/py27/cgi_runtests.py @@ -0,0 +1 @@ +../common/cgi_runtests.py \ No newline at end of file diff --git a/maint/appengine/py27/runtests.py b/maint/appengine/py27/runtests.py new file mode 120000 index 00000000..2cce26b0 --- /dev/null +++ b/maint/appengine/py27/runtests.py @@ -0,0 +1 @@ +../common/runtests.py \ No newline at end of file diff --git a/maint/appengine/py27/tornado b/maint/appengine/py27/tornado new file mode 120000 index 00000000..13b2e093 --- /dev/null +++ b/maint/appengine/py27/tornado @@ -0,0 +1 @@ +../../../tornado \ No newline at end of file diff --git a/tornado/testing.py b/tornado/testing.py index bf49edf8..a03d15d7 100644 --- a/tornado/testing.py +++ b/tornado/testing.py @@ -21,8 +21,16 @@ information. from __future__ import with_statement from cStringIO import StringIO -from tornado.httpclient import AsyncHTTPClient -from tornado.httpserver import HTTPServer +try: + from tornado.httpclient import AsyncHTTPClient + from tornado.httpserver import HTTPServer + from tornado.ioloop import IOLoop +except ImportError: + # These modules are not importable on app engine. Parts of this module + # won't work, but e.g. LogTrapTestCase and main() will. + AsyncHTTPClient = None + HTTPServer = None + IOLoop = None from tornado.stack_context import StackContext, NullContext import contextlib import logging @@ -31,8 +39,6 @@ import sys import time import unittest -from tornado.ioloop import IOLoop - _next_port = 10000 def get_unused_port(): """Returns a (hopefully) unused port number."""