From 4d99799ee724070fe0fe7404f655854d223f6e93 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 9 May 2011 20:40:33 -0400 Subject: [PATCH] - given that Oracle's issue is not just open connections, but *closed* ones too, go really heavy handed and start marking tests as "requires.ad_hoc_engines", add a flag --low-connections that will switch the engine reaper mechanism to use as *few* distinct engines and connections as possible, many engine tests that really need their own engines are just skipped. --- test/bootstrap/config.py | 5 +++++ test/bootstrap/noseplugin.py | 6 +++++- test/engine/test_execute.py | 7 +++++++ test/engine/test_transaction.py | 3 ++- test/lib/engines.py | 13 +++++++++++++ test/lib/requires.py | 14 +++++++++++++- 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/test/bootstrap/config.py b/test/bootstrap/config.py index e1a32c5b48..bdfc8189f5 100644 --- a/test/bootstrap/config.py +++ b/test/bootstrap/config.py @@ -63,6 +63,11 @@ def _engine_strategy(options, opt_str, value, parser): pre_configure = [] post_configure = [] +def _setup_options(opt, file_config): + global options + options = opt +pre_configure.append(_setup_options) + def _monkeypatch_cdecimal(options, file_config): if options.cdecimal: import sys diff --git a/test/bootstrap/noseplugin.py b/test/bootstrap/noseplugin.py index c43e81f705..9cdfcee0e5 100644 --- a/test/bootstrap/noseplugin.py +++ b/test/bootstrap/noseplugin.py @@ -54,6 +54,9 @@ class NoseSQLAlchemy(Plugin): help="Use mock pool (asserts only one connection used)") opt("--zero-timeout", action="callback", callback=_zero_timeout, help="Set pool_timeout to zero, applies to QueuePool only") + opt("--low-connections", action="store_true", dest="low_connections", + help="Use a low number of distinct connections - i.e. for Oracle TNS" + ) opt("--enginestrategy", action="callback", type="string", callback=_engine_strategy, help="Engine strategy (plain or threadlocal, defaults to plain)") @@ -175,7 +178,8 @@ class NoseSQLAlchemy(Plugin): def stopContext(self, ctx): engines.testing_reaper._stop_test_ctx() - testing.global_cleanup_assertions() + if not config.options.low_connections: + testing.global_cleanup_assertions() #def handleError(self, test, err): #pass diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 9cca5fc2cd..33b34ca1b3 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -197,6 +197,7 @@ class ExecuteTest(fixtures.TestBase): eq_(testing.db.execute(users_autoinc.select()).fetchall(), [(1, None)]) + @testing.requires.ad_hoc_engines def test_engine_level_options(self): eng = engines.testing_engine(options={'execution_options' : {'foo': 'bar'}}) @@ -246,6 +247,8 @@ class CompiledCacheTest(fixtures.TestBase): eq_(conn.execute("select count(*) from users").scalar(), 3) class LoggingNameTest(fixtures.TestBase): + __requires__ = 'ad_hoc_engines', + def _assert_names_in_execute(self, eng, eng_name, pool_name): eng.execute(select([1])) for name in [b.name for b in self.buf.buffer]: @@ -329,6 +332,7 @@ class LoggingNameTest(fixtures.TestBase): self._assert_no_name_in_execute(eng) class EchoTest(fixtures.TestBase): + __requires__ = 'ad_hoc_engines', def setup(self): self.level = logging.getLogger('sqlalchemy.engine').level @@ -558,6 +562,8 @@ class AlternateResultProxyTest(fixtures.TestBase): self._test_proxy(base.BufferedColumnResultProxy) class EngineEventsTest(fixtures.TestBase): + __requires__ = 'ad_hoc_engines', + def tearDown(self): Engine.dispatch._clear() @@ -823,6 +829,7 @@ class ProxyConnectionTest(fixtures.TestBase): the deprecated ConnectionProxy interface. """ + __requires__ = 'ad_hoc_engines', @testing.uses_deprecated(r'.*Use event.listen') @testing.fails_on('firebird', 'Data type unknown') diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index 4d65688587..f626a0ae08 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -519,6 +519,7 @@ tlengine = None class TLTransactionTest(fixtures.TestBase): + __requires__ = ('ad_hoc_engines', ) @classmethod def setup_class(cls): @@ -1115,7 +1116,7 @@ class ForUpdateTest(fixtures.TestBase): self.assert_(len(errors) != 0) class IsolationLevelTest(fixtures.TestBase): - __requires__ = ('isolation_level',) + __requires__ = ('isolation_level', 'ad_hoc_engines') def _default_isolation_level(self): if testing.against('sqlite'): diff --git a/test/lib/engines.py b/test/lib/engines.py index 6202c0a3df..7b830e6437 100644 --- a/test/lib/engines.py +++ b/test/lib/engines.py @@ -51,6 +51,19 @@ class ConnectionKiller(object): # self._safe(conn.rollback) def _stop_test_ctx(self): + if config.options.low_connections: + self._stop_test_ctx_minimal() + else: + self._stop_test_ctx_aggressive() + + def _stop_test_ctx_minimal(self): + from test.lib import testing + self.close_all() + for rec in self.testing_engines.keys(): + if rec is not testing.db: + rec.dispose() + + def _stop_test_ctx_aggressive(self): self.close_all() for conn in self.conns: self._safe(conn.close) diff --git a/test/lib/requires.py b/test/lib/requires.py index 44ba6ffac2..f79c53c44c 100644 --- a/test/lib/requires.py +++ b/test/lib/requires.py @@ -16,7 +16,7 @@ from testing import \ fails_on_everything_except,\ fails_if from sqlalchemy import util - +from test.lib import config import testing import sys @@ -375,3 +375,15 @@ def sqlite(fn): skip_if(lambda: not _has_sqlite()) ) +def ad_hoc_engines(fn): + """Test environment must allow ad-hoc engine/connection creation. + + DBs that scale poorly for many connections, even when closed, i.e. + Oracle, may use the "--low-connections" option which flags this requirement + as not present. + + """ + return _chain_decorators_on( + fn, + skip_if(lambda: config.options.low_connections) + ) -- 2.39.5