From f1bb57c604baa50d818ec9f8d550a8fa9e51c507 Mon Sep 17 00:00:00 2001 From: Ilya Grishnov Date: Thu, 12 Jan 2023 12:16:48 +0300 Subject: [PATCH 1/2] test: fixes the moduleless error of crud instance In crud tests, if the necessary rocks dependencies are missing, an error message is now displayed. Prior to this fix, an error in importing missing models caused the tests to freez forever. Part of #205 --- test/suites/crud_server.lua | 115 +++++++++++++++++++++--------------- test/suites/test_crud.py | 6 ++ 2 files changed, 72 insertions(+), 49 deletions(-) diff --git a/test/suites/crud_server.lua b/test/suites/crud_server.lua index ba6fe82a..55d4fc48 100644 --- a/test/suites/crud_server.lua +++ b/test/suites/crud_server.lua @@ -1,7 +1,58 @@ #!/usr/bin/env tarantool -local crud = require('crud') -local vshard = require('vshard') +local function configure_crud_instance(primary_listen, crud, vshard) + box.schema.create_space( + 'tester', { + format = { + {name = 'id', type = 'unsigned'}, + {name = 'bucket_id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + } + }) + box.space.tester:create_index('primary_index', { + parts = { + {field = 1, type = 'unsigned'}, + }, + }) + box.space.tester:create_index('bucket_id', { + parts = { + {field = 2, type = 'unsigned'}, + }, + unique = false, + }) + + -- Setup vshard. + _G.vshard = vshard + box.once('guest', function() + box.schema.user.grant('guest', 'super') + end) + local uri = 'guest@0.0.0.0:' .. primary_listen + local cfg = { + bucket_count = 300, + sharding = { + [box.info().cluster.uuid] = { + replicas = { + [box.info().uuid] = { + uri = uri, + name = 'storage', + master = true, + }, + }, + }, + }, + } + vshard.storage.cfg(cfg, box.info().uuid) + vshard.router.cfg(cfg) + vshard.router.bootstrap() + + -- Initialize crud. + crud.init_storage() + crud.init_router() + crud.cfg{stats = true} +end + +local crud_imported, crud = pcall(require, 'crud') +local vshard_imported, vshard = pcall(require, 'vshard') local admin_listen = os.getenv("ADMIN") local primary_listen = os.getenv("LISTEN") @@ -18,51 +69,17 @@ box.schema.user.grant( 'read,write,execute', 'universe' ) -box.schema.create_space( - 'tester', { - format = { - {name = 'id', type = 'unsigned'}, - {name = 'bucket_id', type = 'unsigned'}, - {name = 'name', type = 'string'}, - } -}) -box.space.tester:create_index('primary_index', { - parts = { - {field = 1, type = 'unsigned'}, - }, -}) -box.space.tester:create_index('bucket_id', { - parts = { - {field = 2, type = 'unsigned'}, - }, - unique = false, -}) - --- Setup vshard. -_G.vshard = vshard -box.once('guest', function() - box.schema.user.grant('guest', 'super') -end) -local uri = 'guest@0.0.0.0:' .. primary_listen -local cfg = { - bucket_count = 300, - sharding = { - [box.info().cluster.uuid] = { - replicas = { - [box.info().uuid] = { - uri = uri, - name = 'storage', - master = true, - }, - }, - }, - }, -} -vshard.storage.cfg(cfg, box.info().uuid) -vshard.router.cfg(cfg) -vshard.router.bootstrap() --- Initialize crud. -crud.init_storage() -crud.init_router() -crud.cfg{stats = true} +if crud_imported == false or vshard_imported == false then + -- Set flag for unittest. + _G['ROCKS_IMPORT_FAIL'] = true + local fail_msg = 'The crud/vshard modules are not detected, ' .. + 'installation via rocks install is required ' .. + 'for CRUD testing purposes. You can use ' .. + ' or ' .. + ' to install modules' + -- The print output will be captured in the logs. + print(fail_msg) +else + configure_crud_instance(primary_listen, crud, vshard) +end diff --git a/test/suites/test_crud.py b/test/suites/test_crud.py index 633b7159..02f8c6b8 100644 --- a/test/suites/test_crud.py +++ b/test/suites/test_crud.py @@ -40,6 +40,12 @@ def setUp(self): user='guest', password='') # Time for vshard group configuration. time.sleep(1) + if self.conn.eval('return ROCKS_IMPORT_FAIL').data[0] == True: + raise unittest.SkipTest('The crud/vshard modules are not detected, ' + + 'installation via rocks install is required ' + + 'for CRUD testing purposes. You can use ' + + ' or ' + + ' to install modules') crud_test_cases = { 'crud_insert': { From d89651ee8c625a94059ab372025d1de01a4bcfcf Mon Sep 17 00:00:00 2001 From: Ilya Grishnov Date: Thu, 12 Jan 2023 12:21:07 +0300 Subject: [PATCH 2/2] api: extend connect with fetch_schema param Added support of the fetch_schema parameter, which allows to ignore schema changes on the server. Closes #219 --- .gitignore | 2 + CHANGELOG.md | 1 + docs/source/quick-start.rst | 2 +- tarantool/connection.py | 79 +++++++++++-- tarantool/connection_pool.py | 9 +- tarantool/mesh_connection.py | 9 +- tarantool/request.py | 10 +- test/suites/test_crud.py | 7 +- test/suites/test_schema.py | 220 +++++++++++++++++++++++++++++++++-- 9 files changed, 309 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 9d3a8412..53a8daa2 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ test/data/*.key !test/data/localhost.enc.key test/data/*.pem test/data/*.srl + +.rocks diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb88ae8..27582a49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +- Support `fetch_schema` parameter for a connection (#219). ### Added diff --git a/docs/source/quick-start.rst b/docs/source/quick-start.rst index 27633012..81526276 100644 --- a/docs/source/quick-start.rst +++ b/docs/source/quick-start.rst @@ -359,7 +359,7 @@ Through the :class:`~tarantool.Connection` object, you can access >>> import tarantool >>> from tarantool.error import CrudModuleError, CrudModuleManyError, DatabaseError - >>> conn = tarantool.Connection(host='localhost',port=3301) + >>> conn = tarantool.Connection(host='localhost',port=3301,fetch_schema=False) >>> conn.crud_ conn.crud_count( conn.crud_insert( conn.crud_insert_object_many( diff --git a/tarantool/connection.py b/tarantool/connection.py index 7fd43b9e..73352662 100644 --- a/tarantool/connection.py +++ b/tarantool/connection.py @@ -579,7 +579,8 @@ def __init__(self, host, port, ssl_password_file=DEFAULT_SSL_PASSWORD_FILE, packer_factory=default_packer_factory, unpacker_factory=default_unpacker_factory, - auth_type=None): + auth_type=None, + fetch_schema=True): """ :param host: Server hostname or IP address. Use ``None`` for Unix sockets. @@ -736,6 +737,18 @@ def __init__(self, host, port, ``"chap-sha1"``. :type auth_type: :obj:`None` or :obj:`str`, optional + :param bool fetch_schema: If ``False``, schema is not loaded on connect + and schema updates are not automatically loaded. + As a result, these methods become unavailable: + :meth:`~tarantool.Connection.replace`, + :meth:`~tarantool.Connection.insert`, + :meth:`~tarantool.Connection.delete`, + :meth:`~tarantool.Connection.upsert`, + :meth:`~tarantool.Connection.update`, + :meth:`~tarantool.Connection.select`, + :meth:`~tarantool.Connection.space`. + :type fetch_schema: :obj:`bool`, optional + :raise: :exc:`~tarantool.error.ConfigurationError`, :meth:`~tarantool.Connection.connect` exceptions @@ -766,8 +779,9 @@ def __init__(self, host, port, self.socket_timeout = socket_timeout self.reconnect_delay = reconnect_delay self.reconnect_max_attempts = reconnect_max_attempts - self.schema = Schema(self) - self.schema_version = 1 + self.fetch_schema = fetch_schema + self.schema = None + self.schema_version = 0 self._socket = None self.connected = False self.error = True @@ -1023,7 +1037,11 @@ def connect(self): if self.transport == SSL_TRANSPORT: self.wrap_socket_ssl() self.handshake() - self.load_schema() + if self.fetch_schema: + self.schema = Schema(self) + self.load_schema() + else: + self.schema = None except SslError as e: raise e except Exception as e: @@ -1118,7 +1136,8 @@ def _send_request_wo_reconnect(self, request, on_push=None, on_push_ctx=None): response = request.response_class(self, self._read_response()) break except SchemaReloadException as e: - self.update_schema(e.schema_version) + if self.schema is not None: + self.update_schema(e.schema_version) continue while response._code == IPROTO_CHUNK: @@ -1255,6 +1274,9 @@ def update_schema(self, schema_version): :meta private: """ + if self.schema is None: + self.schema = Schema(self) + self.schema_version = schema_version self.flush_schema() @@ -1269,6 +1291,19 @@ def flush_schema(self): self.schema.flush() self.load_schema() + def _schemaful_connection_check(self): + """ + Checks whether the connection is schemaful. + If the connection is schemaless, an exception will be thrown + about unsupporting the method in connection opened + with fetch_schema=False. + + :raise: :exc:`~tarantool.error.NotSupportedError` + """ + if self.schema is None: + raise NotSupportedError('This method is not available in ' + + 'connection opened with fetch_schema=False') + def call(self, func_name, *args, on_push=None, on_push_ctx=None): """ Execute a CALL request: call a stored Lua function. @@ -1366,11 +1401,14 @@ def replace(self, space_name, values, on_push=None, on_push_ctx=None): :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _replace: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/replace/ """ + self._schemaful_connection_check() + if isinstance(space_name, str): space_name = self.schema.get_space(space_name).sid if on_push is not None and not callable(on_push): @@ -1411,7 +1449,7 @@ def authenticate(self, user, password): password=self.password, auth_type=self._get_auth_type()) auth_response = self._send_request_wo_reconnect(request) - if auth_response.return_code == 0: + if auth_response.return_code == 0 and self.schema is not None: self.flush_schema() return auth_response @@ -1584,11 +1622,14 @@ def insert(self, space_name, values, on_push=None, on_push_ctx=None): :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _insert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/insert/ """ + self._schemaful_connection_check() + if isinstance(space_name, str): space_name = self.schema.get_space(space_name).sid if on_push is not None and not callable(on_push): @@ -1623,11 +1664,14 @@ def delete(self, space_name, key, *, index=0, on_push=None, on_push_ctx=None): :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _delete: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/delete/ """ + self._schemaful_connection_check() + key = wrap_key(key) if isinstance(space_name, str): space_name = self.schema.get_space(space_name).sid @@ -1682,11 +1726,14 @@ def upsert(self, space_name, tuple_value, op_list, *, index=0, on_push=None, on_ :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _upsert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/upsert/ """ + self._schemaful_connection_check() + if isinstance(space_name, str): space_name = self.schema.get_space(space_name).sid if isinstance(index, str): @@ -1770,11 +1817,14 @@ def update(self, space_name, key, op_list, *, index=0, on_push=None, on_push_ctx :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _update: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/update/ """ + self._schemaful_connection_check() + key = wrap_key(key) if isinstance(space_name, str): space_name = self.schema.get_space(space_name).sid @@ -1956,11 +2006,14 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i :exc:`~tarantool.error.DatabaseError`, :exc:`~tarantool.error.SchemaError`, :exc:`~tarantool.error.NetworkError`, - :exc:`~tarantool.error.SslError` + :exc:`~tarantool.error.SslError`, + :exc:`~tarantool.error.NotSupportedError` .. _select: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/select/ """ + self._schemaful_connection_check() + if iterator is None: iterator = ITERATOR_EQ if key is None or (isinstance(key, (list, tuple)) and @@ -1996,6 +2049,8 @@ def space(self, space_name): :raise: :exc:`~tarantool.error.SchemaError` """ + self._schemaful_connection_check() + return Space(self, space_name) def generate_sync(self): diff --git a/tarantool/connection_pool.py b/tarantool/connection_pool.py index 362b7618..b5e5f4f4 100644 --- a/tarantool/connection_pool.py +++ b/tarantool/connection_pool.py @@ -378,7 +378,8 @@ def __init__(self, call_16=False, connection_timeout=CONNECTION_TIMEOUT, strategy_class=RoundRobinStrategy, - refresh_delay=POOL_REFRESH_DELAY): + refresh_delay=POOL_REFRESH_DELAY, + fetch_schema=True): """ :param addrs: List of dictionaries describing server addresses: @@ -452,6 +453,9 @@ def __init__(self, `box.info.ro`_ status background refreshes, in seconds. :type connection_timeout: :obj:`float`, optional + :param fetch_schema: Refer to + :paramref:`~tarantool.Connection.params.fetch_schema`. + :raise: :exc:`~tarantool.error.ConfigurationError`, :class:`~tarantool.Connection` exceptions @@ -500,7 +504,8 @@ def __init__(self, ssl_ciphers=addr['ssl_ciphers'], ssl_password=addr['ssl_password'], ssl_password_file=addr['ssl_password_file'], - auth_type=addr['auth_type']) + auth_type=addr['auth_type'], + fetch_schema=fetch_schema) ) if connect_now: diff --git a/tarantool/mesh_connection.py b/tarantool/mesh_connection.py index cc4def5a..2cb44ee3 100644 --- a/tarantool/mesh_connection.py +++ b/tarantool/mesh_connection.py @@ -283,7 +283,8 @@ def __init__(self, host=None, port=None, addrs=None, strategy_class=RoundRobinStrategy, cluster_discovery_function=None, - cluster_discovery_delay=CLUSTER_DISCOVERY_DELAY): + cluster_discovery_delay=CLUSTER_DISCOVERY_DELAY, + fetch_schema=True): """ :param host: Refer to :paramref:`~tarantool.Connection.params.host`. @@ -425,6 +426,9 @@ def __init__(self, host=None, port=None, list refresh. :type cluster_discovery_delay: :obj:`float`, optional + :param fetch_schema: Refer to + :paramref:`~tarantool.Connection.params.fetch_schema`. + :raises: :exc:`~tarantool.error.ConfigurationError`, :class:`~tarantool.Connection` exceptions, :class:`~tarantool.MeshConnection.connect` exceptions @@ -489,7 +493,8 @@ def __init__(self, host=None, port=None, ssl_ciphers=addr['ssl_ciphers'], ssl_password=addr['ssl_password'], ssl_password_file=addr['ssl_password_file'], - auth_type=addr['auth_type']) + auth_type=addr['auth_type'], + fetch_schema=fetch_schema) def connect(self): """ diff --git a/tarantool/request.py b/tarantool/request.py index f6f6dfcb..73ef9bd2 100644 --- a/tarantool/request.py +++ b/tarantool/request.py @@ -188,9 +188,13 @@ def header(self, length): """ self._sync = self.conn.generate_sync() - header = self._dumps({IPROTO_REQUEST_TYPE: self.request_type, - IPROTO_SYNC: self._sync, - IPROTO_SCHEMA_ID: self.conn.schema_version}) + header_fields = { + IPROTO_REQUEST_TYPE: self.request_type, + IPROTO_SYNC: self._sync, + } + if self.conn.schema is not None: + header_fields[IPROTO_SCHEMA_ID] = self.conn.schema_version + header = self._dumps(header_fields) return self._dumps(length + len(header)) + header diff --git a/test/suites/test_crud.py b/test/suites/test_crud.py index 02f8c6b8..4af62d90 100644 --- a/test/suites/test_crud.py +++ b/test/suites/test_crud.py @@ -33,11 +33,12 @@ def setUp(self): time.sleep(1) # Open connections to instance. self.conn = tarantool.Connection(host=self.host, port=self.port, - user='guest', password='') + user='guest', password='', fetch_schema=False) self.conn_mesh = tarantool.MeshConnection(host=self.host, port=self.port, - user='guest', password='') + user='guest', password='', fetch_schema=False) self.conn_pool = tarantool.ConnectionPool([{'host':self.host, 'port':self.port}], - user='guest', password='') + user='guest', password='', + fetch_schema=False) # Time for vshard group configuration. time.sleep(1) if self.conn.eval('return ROCKS_IMPORT_FAIL').data[0] == True: diff --git a/test/suites/test_schema.py b/test/suites/test_schema.py index 09017b2a..7e26b1a0 100644 --- a/test/suites/test_schema.py +++ b/test/suites/test_schema.py @@ -2,6 +2,7 @@ import unittest import tarantool from .lib.tarantool_server import TarantoolServer +from tarantool.error import NotSupportedError # FIXME: I'm quite sure that there is a simpler way to count @@ -41,8 +42,47 @@ def setUpClass(self): self.srv = TarantoolServer() self.srv.script = 'test/suites/box.lua' self.srv.start() + self.srv.admin("box.schema.user.create('test', {password = 'test', " + + "if_not_exists = true})") + self.srv.admin("box.schema.user.grant('test', 'read,write,execute', 'universe')") + + # Create server_function and tester space (for fetch_schema opt testing purposes). + self.srv.admin("function server_function() return 2+2 end") + self.srv.admin(""" + box.schema.create_space( + 'tester', { + format = { + {name = 'id', type = 'unsigned'}, + {name = 'name', type = 'string', is_nullable = true}, + } + }) + """) + self.srv.admin(""" + box.space.tester:create_index( + 'primary_index', { + parts = { + {field = 1, type = 'unsigned'}, + } + }) + """) + self.srv.admin("box.space.tester:insert({1, null})") + self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'], - encoding=self.encoding) + encoding=self.encoding, user='test', password='test') + self.con_schema_disable = tarantool.Connection(self.srv.host, self.srv.args['primary'], + encoding=self.encoding, fetch_schema=False, + user='test', password='test') + if not sys.platform.startswith("win"): + # Schema fetch disable tests via mesh and pool connection + # are not supported on windows platform. + self.mesh_con_schema_disable = tarantool.MeshConnection(host=self.srv.host, + port=self.srv.args['primary'], + fetch_schema=False, + user='test', password='test') + self.pool_con_schema_disable = tarantool.ConnectionPool([{'host':self.srv.host, + 'port':self.srv.args['primary']}], + user='test', password='test', + fetch_schema=False) self.sch = self.con.schema # The relevant test cases mainly target Python 2, where @@ -97,12 +137,6 @@ def verify_unicode_index(self, index): self.assertEqual(index.name, self.unicode_index_name_u) self.assertEqual(len(index.parts), 1) - def test_00_authenticate(self): - self.assertIsNone(self.srv.admin("box.schema.user.create('test', { password = 'test' })")) - self.assertIsNone(self.srv.admin("box.schema.user.grant('test', 'read,write', 'space', '_space')")) - self.assertIsNone(self.srv.admin("box.schema.user.grant('test', 'read,write', 'space', '_index')")) - self.assertEqual(self.con.authenticate('test', 'test')._data, None) - def test_01_space_bad(self): with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'): @@ -341,9 +375,181 @@ def test_07_schema_version_update(self): self.srv.admin("box.schema.create_space('ttt22')") self.assertEqual(len(self.con.select('_space')), _space_len + 1) + # For schema fetch disable testing purposes. + testing_methods = { + 'unavailable': { + 'replace': { + 'input': ['tester', (1, None)], + 'output': [[1, None]], + }, + 'delete': { + 'input': ['tester', 1], + 'output': [[1, None]], + }, + 'insert': { + 'input': ['tester', (1, None)], + 'output': [[1, None]], + }, + 'upsert': { + 'input': ['tester', (1, None), []], + 'output': [], + }, + 'update': { + 'input': ['tester', 1, []], + 'output': [[1, None]], + }, + 'select': { + 'input': ['tester', 1], + 'output': [[1, None]], + }, + 'space': { + 'input': ['tester'], + }, + }, + 'available': { + # CRUD methods are also tested with the fetch_schema=False opt, + # see the test_crud.py file. + 'call': { + 'input': ['server_function'], + 'output': [4], + }, + 'eval': { + 'input': ['return 2+2'], + 'output': [4], + }, + 'ping': { + 'input': [], + }, + }, + } + + def _run_test_schema_fetch_disable(self, con, mode=None): + # Enable SQL test case for tarantool 2.* and higher. + if int(self.srv.admin.tnt_version.__str__()[0]) > 1: + self.testing_methods['available']['execute'] = { + 'input': ['SELECT * FROM "tester"'], + 'output': [[1, None]], + } + + # Testing the schemaless connection with methods + # that should NOT be available. + if mode is not None: + for addr in con.pool.keys(): + self.assertEqual(con.pool[addr].conn.schema_version, 0) + self.assertEqual(con.pool[addr].conn.schema, None) + else: + self.assertEqual(con.schema_version, 0) + self.assertEqual(con.schema, None) + for method_case in self.testing_methods['unavailable'].keys(): + with self.subTest(name=method_case): + if isinstance(con, tarantool.ConnectionPool) and method_case == 'space': + continue + testing_function = getattr(con, method_case) + try: + if mode is not None: + _ = testing_function( + *self.testing_methods['unavailable'][method_case]['input'], + mode=mode) + else: + _ = testing_function( + *self.testing_methods['unavailable'][method_case]['input']) + except NotSupportedError as e: + self.assertEqual(e.message, 'This method is not available in ' + + 'connection opened with fetch_schema=False') + # Testing the schemaless connection with methods + # that should be available. + for method_case in self.testing_methods['available'].keys(): + with self.subTest(name=method_case): + testing_function = getattr(con, method_case) + if mode is not None: + resp = testing_function( + *self.testing_methods['available'][method_case]['input'], + mode=mode) + else: + resp = testing_function( + *self.testing_methods['available'][method_case]['input']) + if method_case == 'ping': + self.assertEqual(isinstance(resp, float), True) + else: + self.assertEqual( + resp.data, + self.testing_methods['available'][method_case]['output']) + + # Turning the same connection into schemaful. + if mode is not None: + for addr in con.pool.keys(): + con.pool[addr].conn.update_schema(con.pool[addr].conn.schema_version) + else: + con.update_schema(con.schema_version) + + # Testing the schemaful connection with methods + # that should NOW be available. + for method_case in self.testing_methods['unavailable'].keys(): + with self.subTest(name=method_case): + if isinstance(con, tarantool.ConnectionPool) and method_case == 'space': + continue + testing_function = getattr(con, method_case) + if mode is not None: + resp = testing_function( + *self.testing_methods['unavailable'][method_case]['input'], + mode=mode) + else: + resp = testing_function( + *self.testing_methods['unavailable'][method_case]['input']) + if method_case == 'space': + self.assertEqual(isinstance(resp, tarantool.space.Space), True) + else: + self.assertEqual( + resp.data, + self.testing_methods['unavailable'][method_case]['output']) + # Testing the schemaful connection with methods + # that should have remained available. + for method_case in self.testing_methods['available'].keys(): + with self.subTest(name=method_case): + testing_function = getattr(con, method_case) + if mode is not None: + resp = testing_function( + *self.testing_methods['available'][method_case]['input'], + mode=mode) + else: + resp = testing_function( + *self.testing_methods['available'][method_case]['input']) + if method_case == 'ping': + self.assertEqual(isinstance(resp, float), True) + else: + self.assertEqual( + resp.data, + self.testing_methods['available'][method_case]['output']) + if mode is not None: + self.assertNotEqual(con.pool[addr].conn.schema_version, 1) + self.assertNotEqual(con.pool[addr].conn.schema, None) + else: + self.assertNotEqual(con.schema_version, 1) + self.assertNotEqual(con.schema, None) + + def test_08_schema_fetch_disable_via_connection(self): + self._run_test_schema_fetch_disable(self.con_schema_disable) + + @unittest.skipIf(sys.platform.startswith("win"), + 'Schema fetch disable tests via mesh connection on windows platform are not supported') + def test_08_schema_fetch_disable_via_mesh_connection(self): + self._run_test_schema_fetch_disable(self.mesh_con_schema_disable) + + @unittest.skipIf(sys.platform.startswith("win"), + 'Schema fetch disable tests via connection pool on windows platform are not supported') + def test_08_schema_fetch_disable_via_connection_pool(self): + self._run_test_schema_fetch_disable(self.pool_con_schema_disable, + mode=tarantool.Mode.ANY) + @classmethod def tearDownClass(self): self.con.close() + self.con_schema_disable.close() + if not sys.platform.startswith("win"): + # Schema fetch disable tests via mesh and pool connection + # are not supported on windows platform. + self.mesh_con_schema_disable.close() + self.pool_con_schema_disable.close() self.srv.stop() self.srv.clean()