def test_hanging_connect_within_overflow(self): """test that a single connect() call which is hanging does not block other connections from proceeding.""" dbapi = Mock() mutex = threading.Lock() def hanging_dbapi(): time.sleep(2) with mutex: return dbapi.connect() def fast_dbapi(): with mutex: return dbapi.connect() creator = threading.local() def create(): return creator.mock_connector() def run_test(name, pool, should_hang): if should_hang: creator.mock_connector = hanging_dbapi else: creator.mock_connector = fast_dbapi conn = pool.connect() conn.operation(name) time.sleep(1) conn.close() p = pool.QueuePool(creator=create, pool_size=2, max_overflow=3) threads = [ threading.Thread( target=run_test, args=("success_one", p, False)), threading.Thread( target=run_test, args=("success_two", p, False)), threading.Thread( target=run_test, args=("overflow_one", p, True)), threading.Thread( target=run_test, args=("overflow_two", p, False)), threading.Thread( target=run_test, args=("overflow_three", p, False)) ] for t in threads: t.start() time.sleep(.2) for t in threads: t.join(timeout=join_timeout) eq_( dbapi.connect().operation.mock_calls, [call("success_one"), call("success_two"), call("overflow_two"), call("overflow_three"), call("overflow_one")] )
def test_call_with_kwargs(self): mock_scope_func = Mock() SessionMaker = sa.orm.sessionmaker() Session = scoped_session(sa.orm.sessionmaker(), mock_scope_func) s0 = SessionMaker() assert s0.autocommit == False mock_scope_func.return_value = 0 s1 = Session() assert s1.autocommit == False assert_raises_message( sa.exc.InvalidRequestError, "Scoped session is already present", Session, autocommit=True ) mock_scope_func.return_value = 1 s2 = Session(autocommit=True) assert s2.autocommit == True
def test_deferred_instance_event_subclass_propagate_baseclass(self): """ 1. instance event listen on class, w propagate 2. map one subclass of class, map base class, leave 2nd subclass unmapped 3. event fire on sub should receive one and only one event 4. event fire on base should receive one and only one event 5. map 2nd subclass 6. event fire on 2nd subclass should receive one and only one event """ users, User = (self.tables.users, self.classes.User) class SubUser(User): pass class SubUser2(User): pass canary = Mock() event.listen(User, "load", canary, propagate=True, raw=False) # reversing these fixes.... m = mapper(SubUser, users) m2 = mapper(User, users) instance = Mock() m.class_manager.dispatch.load(instance) eq_(canary.mock_calls, [call(instance.obj())]) m2.class_manager.dispatch.load(instance) eq_(canary.mock_calls, [call(instance.obj()), call(instance.obj())]) m3 = mapper(SubUser2, users) m3.class_manager.dispatch.load(instance) eq_(canary.mock_calls, [call(instance.obj()), call(instance.obj()), call(instance.obj())])
def mock_connection(): def mock_cursor(): def execute(*args, **kwargs): if conn.explode == "execute": raise MockDisconnect("Lost the DB connection on execute") elif conn.explode == "interrupt": conn.explode = "explode_no_disconnect" raise MockExitIsh("Keyboard / greenlet / etc interruption") elif conn.explode == "interrupt_dont_break": conn.explode = None raise MockExitIsh("Keyboard / greenlet / etc interruption") elif conn.explode in ( "execute_no_disconnect", "explode_no_disconnect", ): raise MockError( "something broke on execute but we didn't lose the " "connection") elif conn.explode in ( "rollback", "rollback_no_disconnect", "explode_no_disconnect", ): raise MockError( "something broke on execute but we didn't lose the " "connection") elif args and "SELECT" in args[0]: cursor.description = [("foo", None, None, None, None, None)] else: return def close(): cursor.fetchall = cursor.fetchone = Mock( side_effect=MockError("cursor closed")) cursor = Mock(execute=Mock(side_effect=execute), close=Mock(side_effect=close)) return cursor def cursor(): while True: yield mock_cursor() def rollback(): if conn.explode == "rollback": raise MockDisconnect("Lost the DB connection on rollback") if conn.explode == "rollback_no_disconnect": raise MockError( "something broke on rollback but we didn't lose the " "connection") else: return def commit(): if conn.explode == "commit": raise MockDisconnect("Lost the DB connection on commit") elif conn.explode == "commit_no_disconnect": raise MockError("something broke on commit but we didn't lose the " "connection") else: return conn = Mock( rollback=Mock(side_effect=rollback), commit=Mock(side_effect=commit), cursor=Mock(side_effect=cursor()), ) return conn
def test_pyodbc_version_productversion(self): dialect = pyodbc.MSDialect_pyodbc() conn = Mock(scalar=Mock(return_value="11.0.9216.62")) eq_(dialect._get_server_version_info(conn), (11, 0, 9216, 62))
def test_recycle_pool_no_race(self): def slow_close(): slow_closing_connection._slow_close() time.sleep(.5) slow_closing_connection = Mock() slow_closing_connection.connect.return_value.close = slow_close class Error(Exception): pass dialect = Mock() dialect.is_disconnect = lambda *arg, **kw: True dialect.dbapi.Error = Error pools = [] class TrackQueuePool(pool.QueuePool): def __init__(self, *arg, **kw): pools.append(self) super(TrackQueuePool, self).__init__(*arg, **kw) def creator(): return slow_closing_connection.connect() p1 = TrackQueuePool(creator=creator, pool_size=20) from sqlalchemy import create_engine eng = create_engine(testing.db.url, pool=p1, _initialize=False) eng.dialect = dialect # 15 total connections conns = [eng.connect() for i in range(15)] # return 8 back to the pool for conn in conns[3:10]: conn.close() def attempt(conn): time.sleep(random.random()) try: conn._handle_dbapi_exception(Error(), "statement", {}, Mock(), Mock()) except tsa.exc.DBAPIError: pass # run an error + invalidate operation on the remaining 7 open connections threads = [] for conn in conns: t = threading.Thread(target=attempt, args=(conn, )) t.start() threads.append(t) for t in threads: t.join() # return all 15 connections to the pool for conn in conns: conn.close() # re-open 15 total connections conns = [eng.connect() for i in range(15)] # 15 connections have been fully closed due to invalidate assert slow_closing_connection._slow_close.call_count == 15 # 15 initial connections + 15 reconnections assert slow_closing_connection.connect.call_count == 30 assert len(pools) <= 2, len(pools)
def cursor(): while True: yield Mock(description=[], close=Mock(side_effect=Exception("explode")))
def test_bind_base_table_base_class(self): base_class_bind = Mock() session = self._fixture({self.tables.base_table: base_class_bind}) is_(session.get_bind(self.classes.BaseClass), base_class_bind)
def test_bind_base_class_joined_sub_class(self): base_class_bind = Mock() session = self._fixture({self.classes.BaseClass: base_class_bind}) is_(session.get_bind(self.classes.JoinedSubClass), base_class_bind)
def cursor(): return Mock()
def shutdown(value): if value: db.connect = Mock(side_effect=Exception("connect failed")) else: db.connect = Mock(side_effect=connect)
def test_legacy_schema_flag(self, cfg, expected): with testing.expect_deprecated("The legacy_schema_aliasing parameter"): e = engine_from_config( cfg, module=Mock(version="MS SQL Server 11.0.92")) is_(e.dialect.legacy_schema_aliasing, expected)
def test_recycle_pool_no_race(self): def slow_close(): slow_closing_connection._slow_close() time.sleep(.5) slow_closing_connection = Mock() slow_closing_connection.connect.return_value.close = slow_close class Error(Exception): pass dialect = Mock() dialect.is_disconnect = lambda *arg, **kw: True dialect.dbapi.Error = Error pools = [] class TrackQueuePool(pool.QueuePool): def __init__(self, *arg, **kw): pools.append(self) super(TrackQueuePool, self).__init__(*arg, **kw) def creator(): return slow_closing_connection.connect() p1 = TrackQueuePool(creator=creator, pool_size=20) from sqlalchemy import create_engine eng = create_engine(testing.db.url, pool=p1, _initialize=False) eng.dialect = dialect # 15 total connections conns = [eng.connect() for i in range(15)] # return 8 back to the pool for conn in conns[3:10]: conn.close() def attempt(conn): time.sleep(random.random()) try: conn._handle_dbapi_exception(Error(), "statement", {}, Mock(), Mock()) except tsa.exc.DBAPIError: pass # run an error + invalidate operation on the remaining 7 open #connections threads = [] for conn in conns: t = threading.Thread(target=attempt, args=(conn, )) t.start() threads.append(t) for t in threads: t.join() # return all 15 connections to the pool for conn in conns: conn.close() # re-open 15 total connections conns = [eng.connect() for i in range(15)] # 15 connections have been fully closed due to invalidate assert slow_closing_connection._slow_close.call_count == 15 # 15 initial connections + 15 reconnections assert slow_closing_connection.connect.call_count == 30 assert len(pools) <= 2, len(pools)
def mock_dbapi(): return Mock(paramstyle='qmark', connect=Mock(return_value=Mock(cursor=Mock( return_value=Mock(description=None, rowcount=None)))))
def connect(): while True: yield Mock(cursor=Mock(side_effect=cursor()))
def cursor(): while True: yield Mock()
def test_plugin_multiple_url_registration(self): from sqlalchemy.dialects import sqlite global MyEnginePlugin1 global MyEnginePlugin2 def side_effect_1(url, kw): eq_(kw, {"logging_name": "foob"}) kw["logging_name"] = "bar" return MyEnginePlugin1 def side_effect_2(url, kw): return MyEnginePlugin2 def update_url(url): return url.difference_update_query( ["myplugin1_arg", "myplugin2_arg"] ) MyEnginePlugin1 = Mock( side_effect=side_effect_1, update_url=update_url ) MyEnginePlugin2 = Mock( side_effect=side_effect_2, update_url=update_url ) plugins.register("engineplugin1", __name__, "MyEnginePlugin1") plugins.register("engineplugin2", __name__, "MyEnginePlugin2") url_str = ( "sqlite:///?plugin=engineplugin1&foo=bar&myplugin1_arg=bat" "&plugin=engineplugin2&myplugin2_arg=hoho" ) e = create_engine( url_str, logging_name="foob", ) eq_(e.dialect.name, "sqlite") eq_(e.logging_name, "bar") # plugin args are removed from URL. eq_(e.url.query, {"foo": "bar"}) assert isinstance(e.dialect, sqlite.dialect) eq_( MyEnginePlugin1.mock_calls, [ call(url.make_url(url_str), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], ) eq_( MyEnginePlugin2.mock_calls, [ call(url.make_url(url_str), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], )
def test_once_unless_exception(self): Target = self._fixture() m1 = Mock() m2 = Mock() m3 = Mock() m4 = Mock() m1.side_effect = ValueError m2.side_effect = ValueError m3.side_effect = ValueError event.listen(Target, "event_one", m1) event.listen(Target, "event_one", m2, _once_unless_exception=True) event.listen(Target, "event_one", m3, _once_unless_exception=True) t1 = Target() # only m1 is called, raises assert_raises(ValueError, t1.dispatch.event_one, "x") # now m1 and m2 can be called but not m3 m1.side_effect = None assert_raises(ValueError, t1.dispatch.event_one, "y") # now m3 can be called m2.side_effect = None event.listen(Target, "event_one", m4, _once_unless_exception=True) assert_raises(ValueError, t1.dispatch.event_one, "z") assert_raises(ValueError, t1.dispatch.event_one, "q") eq_(m1.mock_calls, [call("x"), call("y"), call("z"), call("q")]) eq_(m2.mock_calls, [call("y"), call("z")]) eq_(m3.mock_calls, [call("z"), call("q")]) eq_(m4.mock_calls, []) # m4 never got called because m3 blocked it # now m4 can be called m3.side_effect = None t1.dispatch.event_one("p") eq_( m1.mock_calls, [call("x"), call("y"), call("z"), call("q"), call("p")], ) # m2 already got called, so no "p" eq_(m2.mock_calls, [call("y"), call("z")]) eq_(m3.mock_calls, [call("z"), call("q"), call("p")]) eq_(m4.mock_calls, [call("p")]) t1.dispatch.event_one("j") eq_( m1.mock_calls, [call("x"), call("y"), call("z"), call("q"), call("p"), call("j")], ) # nobody got "j" because they've all been successful eq_(m2.mock_calls, [call("y"), call("z")]) eq_(m3.mock_calls, [call("z"), call("q"), call("p")]) eq_(m4.mock_calls, [call("p")])
def _fixture(self, **kw): dbapi = Mock() return dbapi, pool.QueuePool(creator=lambda: dbapi.connect('foo.db'), **kw)
def _dbapi(self): return Mock(paramstyle='qmark', connect=Mock(return_value=Mock( server_version="UI-V6.3.2.18118 Firebird 2.1", cursor=Mock(return_value=Mock()))))
def connect(*arg, **kw): return Mock(cursor=Mock(side_effect=cursor))
def test_bind_base_table_concrete_sub_class(self): base_class_bind = Mock() session = self._fixture({self.tables.base_table: base_class_bind}) is_(session.get_bind(self.classes.ConcreteSubClass), testing.db)
def _invalidate_event_fixture(self): p = self._queuepool_fixture() canary = Mock() event.listen(p, 'invalidate', canary) return p, canary
def __init__(self): self.mock = Mock()
def test_bind_mixin_class_simple_class(self): base_class_bind = Mock() session = self._fixture({self.classes.MixinOne: base_class_bind}) is_(session.get_bind(self.classes.ClassWMixin), base_class_bind)
def mock_conn_scalar(self): return lambda text: Mock(exec_driver_sql=Mock(return_value=Mock( scalar=Mock(return_value=text))))
def test_bind_base_class_concrete_sub_class(self): base_class_bind = Mock() session = self._fixture({self.classes.BaseClass: base_class_bind}) is_(session.get_bind(self.classes.ConcreteSubClass), base_class_bind)
def connect(): while True: yield Mock( spec=["cursor", "commit", "rollback", "close"], cursor=Mock(side_effect=cursor()), )
def _test_validator_backrefs(self, include_backrefs, include_removes): users, addresses = (self.tables.users, self.tables.addresses) canary = Mock() class User(fixtures.ComparableEntity): if include_removes: @validates('addresses', include_removes=True, include_backrefs=include_backrefs) def validate_address(self, key, item, remove): canary(key, item, remove) return item else: @validates('addresses', include_removes=False, include_backrefs=include_backrefs) def validate_address(self, key, item): canary(key, item) return item class Address(fixtures.ComparableEntity): if include_removes: @validates('user', include_backrefs=include_backrefs, include_removes=True) def validate_user(self, key, item, remove): canary(key, item, remove) return item else: @validates('user', include_backrefs=include_backrefs) def validate_user(self, key, item): canary(key, item) return item mapper(User, users, properties={'addresses': relationship(Address, backref="user")}) mapper(Address, addresses) u1 = User() u2 = User() a1, a2 = Address(), Address() # 3 append/set, two removes u1.addresses.append(a1) u1.addresses.append(a2) a2.user = u2 del a1.user u2.addresses.remove(a2) # copy, so that generation of the # comparisons don't get caught calls = list(canary.mock_calls) if include_backrefs: if include_removes: eq_( calls, [ # append #1 call('addresses', Address(), False), # backref for append call('user', User(addresses=[]), False), # append #2 call('addresses', Address(user=None), False), # backref for append call('user', User(addresses=[]), False), # assign a2.user = u2 call('user', User(addresses=[]), False), # backref for u1.addresses.remove(a2) call('addresses', Address(user=None), True), # backref for u2.addresses.append(a2) call('addresses', Address(user=None), False), # del a1.user call('user', User(addresses=[]), True), # backref for u1.addresses.remove(a1) call('addresses', Address(), True), # u2.addresses.remove(a2) call('addresses', Address(user=None), True), # backref for a2.user = None call('user', None, False) ]) else: eq_(calls, [ call('addresses', Address()), call('user', User(addresses=[])), call('addresses', Address(user=None)), call('user', User(addresses=[])), call('user', User(addresses=[])), call('addresses', Address(user=None)), call('user', None) ]) else: if include_removes: eq_(calls, [ call('addresses', Address(), False), call('addresses', Address(user=None), False), call('user', User(addresses=[]), False), call('user', User(addresses=[]), True), call('addresses', Address(user=None), True) ]) else: eq_(calls, [ call('addresses', Address()), call('addresses', Address(user=None)), call('user', User(addresses=[])) ])
def mock_conn(res): return Mock(execute=Mock(return_value=Mock(scalar=Mock( return_value=res))))
def connect(): while True: yield Mock( spec=['cursor', 'commit', 'rollback', 'close'], cursor=Mock(side_effect=cursor()), )
class Dialect(DefaultDialect): initialize = Mock()
def close(): cursor.fetchall = cursor.fetchone = \ Mock(side_effect=MockError("cursor closed"))