Commit 02f3744a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Get more of the sqlalchemy tests working

by expanding our test harness to be closer to how the tests get
run under pytest (which we don't support yet)

Also fix a couple minor things that this turned up.  There is a lot more
to be found here: the new harness supports many more of the sqlalchemy
tests, a number of which aren't working for us.  Also there is some
sort of issue with the current tests that we run, since repeating the tests
multiple times will end up crashing.
parent 9df41bb5
...@@ -2479,7 +2479,7 @@ extern "C" bool nonzero(Box* obj) { ...@@ -2479,7 +2479,7 @@ extern "C" bool nonzero(Box* obj) {
|| obj->cls == instancemethod_cls || obj->cls == module_cls || obj->cls == capifunc_cls || obj->cls == instancemethod_cls || obj->cls == module_cls || obj->cls == capifunc_cls
|| obj->cls == builtin_function_or_method_cls || obj->cls == method_cls || obj->cls == frame_cls || obj->cls == builtin_function_or_method_cls || obj->cls == method_cls || obj->cls == frame_cls
|| obj->cls == generator_cls || obj->cls == capi_getset_cls || obj->cls == pyston_getset_cls || obj->cls == generator_cls || obj->cls == capi_getset_cls || obj->cls == pyston_getset_cls
|| obj->cls == wrapperdescr_cls, || obj->cls == wrapperdescr_cls || obj->cls == wrapperobject_cls,
"%s.__nonzero__", getTypeName(obj)); // TODO "%s.__nonzero__", getTypeName(obj)); // TODO
if (rewriter.get()) { if (rewriter.get()) {
...@@ -2817,7 +2817,8 @@ Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, CallRewrit ...@@ -2817,7 +2817,8 @@ Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, CallRewrit
if (rewrite_args) { if (rewrite_args) {
GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any()); GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any());
val = getattrInternalEx<S>(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj); val = getattrInternalEx<S>(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj);
if (!grewrite_args.out_success) { // TODO: maybe callattrs should have return conventions as well.
if (!grewrite_args.out_success || grewrite_args.out_return_convention == GetattrRewriteArgs::NOEXC_POSSIBLE) {
rewrite_args = NULL; rewrite_args = NULL;
} else if (val) { } else if (val) {
r_val = grewrite_args.out_rtn; r_val = grewrite_args.out_rtn;
...@@ -2859,6 +2860,10 @@ Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, CallRewrit ...@@ -2859,6 +2860,10 @@ Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, CallRewrit
class Helper { class Helper {
public: public:
static Box* call(Box* val, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, void** extra_args) { static Box* call(Box* val, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, void** extra_args) {
if (!val) {
assert(S == CAPI);
return NULL;
}
Box** args = (Box**)extra_args[0]; Box** args = (Box**)extra_args[0];
const std::vector<BoxedString*>* keyword_names = (const std::vector<BoxedString*>*)extra_args[1]; const std::vector<BoxedString*>* keyword_names = (const std::vector<BoxedString*>*)extra_args[1];
return runtimeCallInternal<S>(val, NULL, argspec, arg1, arg2, arg3, args, keyword_names); return runtimeCallInternal<S>(val, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
......
...@@ -1770,8 +1770,9 @@ extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) { ...@@ -1770,8 +1770,9 @@ extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
} }
static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) { static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) {
RELEASE_ASSERT(self->cls == instancemethod_cls, ""); // Not the most effficient, but it works:
Py_FatalError("unimplemented"); return runtimeCallInternal<CXX>(self, NULL, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL, NULL);
// TODO add a tpp_call
} }
Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) { Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) {
......
# run_args: -x import gc
import os import os
import sys import sys
import subprocess import subprocess
import traceback import traceback
ENV_NAME = "sqlalchemy_test_env_" + os.path.basename(sys.executable) ENV_NAME = os.path.abspath("sqlalchemy_test_env_" + os.path.basename(sys.executable))
if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(ENV_NAME + "/bin/python").st_mtime: if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(ENV_NAME + "/bin/python").st_mtime:
print "Creating virtualenv to install testing dependencies..." print "Creating virtualenv to install testing dependencies..."
...@@ -28,7 +27,7 @@ if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(EN ...@@ -28,7 +27,7 @@ if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(EN
# subprocess.check_call([os.path.abspath("sqlalchemy_test_env/bin/python"), "-c", "import py; print type(py); print py.builtin"]) # subprocess.check_call([os.path.abspath("sqlalchemy_test_env/bin/python"), "-c", "import py; print type(py); print py.builtin"])
SQLALCHEMY_DIR = os.path.dirname(__file__) + "/../lib/sqlalchemy" SQLALCHEMY_DIR = os.path.abspath(os.path.dirname(__file__) + "/../lib/sqlalchemy")
TEST_DIR = SQLALCHEMY_DIR + "/test" TEST_DIR = SQLALCHEMY_DIR + "/test"
python_exe = os.path.abspath(ENV_NAME + "/bin/python") python_exe = os.path.abspath(ENV_NAME + "/bin/python")
...@@ -37,29 +36,56 @@ sys.path.insert(0, SQLALCHEMY_DIR) ...@@ -37,29 +36,56 @@ sys.path.insert(0, SQLALCHEMY_DIR)
sys.path.append(ENV_NAME + "/site-packages") sys.path.append(ENV_NAME + "/site-packages")
sys.path.append(ENV_NAME + "/lib/python2.7/site-packages") sys.path.append(ENV_NAME + "/lib/python2.7/site-packages")
os.chdir(SQLALCHEMY_DIR)
# make sure this is importable: # make sure this is importable:
import mock import mock
# sqlalchemy has a bad implementation of is_cpython (in compat.py): it's "not pypy and not is jython".
# Monkey-patch in a properly-detected value (it uses this to gate some "requires a predictable gc" tests
# we fail):
import platform
import sqlalchemy.util.compat
sqlalchemy.util.compat.cpython = sqlalchemy.util.cpython = (platform.python_implementation() == "CPython")
import sqlalchemy.testing import sqlalchemy.testing
class Requirements(object): import sqlalchemy.testing.plugin.pytestplugin
def __getattr__(self, n): class Options(object):
def inner(f): pass
if n == "predictable_gc": options = Options()
def f2(*args, **kw): options.__dict__.update({'noassert': False, 'verbose': 1, 'color': 'auto', 'collectonly': False, 'pyargs': False, 'pastebin': None, 'genscript': None, 'include_tag': None, 'plugins': [], 'dbs': None, 'log_debug': None, 'markexpr': '', 'help': False, 'capture': 'fd', 'low_connections': False, 'requirements': None, 'reportchars': 'fxX', 'reversetop': False, 'assertmode': 'rewrite', 'backend_only': False, 'markers': False, 'strict': False, 'usepdb': False, 'inifilename': None, 'version': False, 'log_info': None, 'dropfirst': False, 'maxfail': 25, 'traceconfig': False, 'junitprefix': None, 'force_write_profiles': False, 'durations': None, 'db': None, 'confcutdir': None, 'doctestmodules': False, 'showfixtures': False, 'fulltrace': False, 'file_or_dir': ['/mnt/kmod/pyston/test/lib/sqlalchemy'], 'basetemp': None, 'report': None, 'ignore': None, 'exclude_tag': None, 'resultlog': None, 'doctestglob': 'test*.txt', 'dburi': None, 'exitfirst': False, 'showlocals': False, 'keyword': '', 'doctest_ignore_import_errors': False, 'write_profiles': False, 'runxfail': False, 'quiet': 0, 'cdecimal': False, 'xmlpath': None, 'tbstyle': 'native', 'debug': False, 'nomagic': False})
return class SkipTest(Exception):
return f2 pass
else: sqlalchemy.testing.plugin.plugin_base.set_skip_test(SkipTest)
return f sqlalchemy.testing.plugin.plugin_base.pre_begin(options)
inner.not_ = lambda: inner sqlalchemy.testing.plugin.plugin_base.read_config()
return inner sqlalchemy.testing.plugin.pytestplugin.pytest_sessionstart(None)
sqlalchemy.testing.config.requirements = sqlalchemy.testing.requires = Requirements()
import glob import glob
test_files = glob.glob(TEST_DIR + "/test*.py") + glob.glob(TEST_DIR + "/*/test*.py") test_files = glob.glob(TEST_DIR + "/test*.py") + glob.glob(TEST_DIR + "/*/test*.py")
# These are the ones that pass on CPython (ie that we've stubbed enough of their testing # These are the ones that pass on CPython (ie that we've stubbed enough of their testing
# infrastructure to run): # infrastructure to run):
MODULES_TO_TEST = ['test.engine.test_parseconnect', 'test.ext.test_compiler', 'test.dialect.test_pyodbc', 'test.dialect.test_sybase', 'test.dialect.test_mxodbc', 'test.sql.test_inspect', 'test.sql.test_operators', 'test.sql.test_ddlemit', 'test.sql.test_cte', 'test.base.test_dependency', 'test.base.test_except', 'test.base.test_inspect', 'test.base.test_events', 'test.orm.test_inspect', 'test.orm.test_descriptor'] MODULES_TO_TEST = [
'test.base.test_dependency',
'test.base.test_events',
'test.base.test_except',
'test.base.test_inspect',
'test.dialect.test_mxodbc',
'test.dialect.test_pyodbc',
'test.dialect.test_sybase',
'test.engine.test_parseconnect',
'test.ext.test_compiler',
'test.orm.test_descriptor',
'test.orm.test_inspect',
'test.orm.test_query',
'test.sql.test_cte',
'test.sql.test_ddlemit',
'test.sql.test_inspect',
'test.sql.test_operators',
]
passed = [] passed = []
failed = [] failed = []
...@@ -70,28 +96,36 @@ for fn in test_files: ...@@ -70,28 +96,36 @@ for fn in test_files:
mname = fn[len(SQLALCHEMY_DIR) + 1:-3].replace('/', '.') mname = fn[len(SQLALCHEMY_DIR) + 1:-3].replace('/', '.')
if mname not in MODULES_TO_TEST: if mname not in MODULES_TO_TEST:
continue continue
print print '=' * 50
print mname print mname
try: try:
m = __import__(mname, fromlist=["__all__"]) m = __import__(mname, fromlist=["__all__"])
for nname in dir(m): for clsname in dir(m):
n = getattr(m, nname) cls = getattr(m, clsname)
if not nname.endswith("Test") or not isinstance(n, type): if not clsname.endswith("Test") or not isinstance(cls, type):
continue continue
print "Running", n print "Running", cls
n = n() if hasattr(cls, "setup_class"):
cls.setup_class()
n = cls()
for t in dir(n): for t in dir(n):
if not t.startswith("test_"): if not t.startswith("test_"):
continue continue
if nname == "SubclassGrowthTest" and t == "test_subclass": if clsname == "SubclassGrowthTest" and t == "test_subclass":
# This test should be marked as requiring predictable_pc # This test should be marked as requiring predictable_pc
continue continue
print "Running", t print "Running", t
n.setup() n.setup()
try:
getattr(n, t)() getattr(n, t)()
except SkipTest:
pass
n.teardown() n.teardown()
if hasattr(cls, "teardown_class"):
cls.teardown_class()
gc.collect()
except Exception: except Exception:
print mname, "FAILED" print mname, "FAILED"
traceback.print_exc() traceback.print_exc()
......
...@@ -43,3 +43,5 @@ def f(m): ...@@ -43,3 +43,5 @@ def f(m):
f(C.foo) f(C.foo)
f(C().foo) f(C().foo)
C().foo.__call__()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment